ほぼコピペになってしまいますが、ちょっとずつみていきます。
https://www.kaggle.com/code/ryanholbrook/convolution-and-relu
畳み込み画像分類器のベースに通常見られる2つの最も重要なタイプの層について学びます。これらは、ReLU活性化関数を持つ畳み込み層と、最大プーリング層です。ここでは、これらの層を組み合わせて特徴抽出を行うブロックを構成することで、独自のconvnetを設計する方法を学びます。
まずは、ReLU活性化関数を持つ畳み込み層についてです。
import numpy as np
from itertools import product
def show_kernel(kernel, label=True, digits=None, text_size=28):
# Format kernel
kernel = np.array(kernel)
if digits is not None:
kernel = kernel.round(digits)
# Plot kernel
cmap = plt.get\_cmap('Blues\_r')
plt.imshow(kernel, cmap=cmap)
rows, cols = kernel.shape
thresh = (kernel.max()+kernel.min())/2
# Optionally, add value labels
if label:
for i, j in product(range(rows), range(cols)):
val = kernel\[i, j\]
color = cmap(0) if val > thresh else cmap(255)
plt.text(j, i, val,
color=color, size=text\_size,
horizontalalignment='center', verticalalignment='center')
plt.xticks(\[\])
plt.yticks(\[\])
特徴抽出
畳み込みの詳細に入る前に、ネットワーク内のこれらの層の目的について話しましょう。これらの三つの操作(畳み込み、ReLU、最大プーリング)が特徴抽出プロセスを実装するためにどのように使用されるかを見ることになります。
ベースによって実行される特徴抽出は、三つの基本操作から成り立っています:
特定の特徴のために画像をフィルタリングする(畳み込み)
フィルタリングされた画像内でその特徴を検出する(ReLU)
特徴を強化するために画像を凝縮する(最大プーリング)
次の図はこのプロセスを示しています。これらの三つの操作が、元の画像の特定の特徴(この場合は水平線)をどのように際立たせることができるかを見ることができます。
通常、ネットワークは1つの画像に対して複数の抽出を並行して実行します。現代のconvnetsでは、ベースの最終層が1000以上のユニークな視覚的特徴を生成することは珍しくありません。
畳み込みによるフィルタリング
畳み込み層はフィルタリングステップを実行します。Kerasモデルでの畳み込み層の定義は、以下のように行うことができます:
from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
layers.Conv2D(filters=64, kernel_size=3), # activation is None
# More layers follow
])
これらのパラメーターを、層の重みと活性化との関係性を見ることで理解することができます。それでは、それを見てみましょう。
重み
訓練中にconvnetが学ぶ重みは、主にその畳み込み層に含まれています。これらの重みを我々はカーネルと呼びます。これらを小さな配列として表現することができます。カーネルは、画像をスキャンしピクセル値の加重和を生成することで動作します。このようにして、カーネルは偏光レンズのように機能し、情報の特定のパターンを強調したり、弱調したりします。
カーネルは、畳み込み層が次に続く層にどのように接続されるかを定義します。上記のカーネルは、出力の各ニューロンを入力の9つのニューロンに接続します。kernel_sizeでカーネルの寸法を設定することで、convnetにこれらの接続をどのように形成するかを指示しています。ほとんどの場合、カーネルは奇数の寸法を持っています - 例えばkernel_size=(3, 3)や(5, 5)のように - そのため中央に1つのピクセルが位置するようになっていますが、これは必須ではありません。
畳み込み層のカーネルは、それが作成する特徴の種類を決定します。訓練中、convnetは分類問題を解決するために必要な特徴を学ぶことを試みます。これは、そのカーネルの最適な値を見つけることを意味します。
活性化関数
ネットワーク内の活性化関数は特徴マップと呼ばれます。これらは、フィルタを画像に適用した結果として得られるもので、カーネルが抽出する視覚的特徴を含んでいます。以下は、それらが生成した特徴マップと共に示されるいくつかのカーネルです。
カーネル内の数字のパターンから、それが作成する特徴マップの種類がわかります。一般的に、畳み込みがその入力で強調するものは、カーネル内の正の数字の形状と一致します。上記の左と中央のカーネルは、どちらも水平の形状をフィルタリングします。
filtersパラメータを使用して、畳み込み層に何個の特徴マップを出力として作成してほしいかを指示します。
ReLUで検出
フィルタリングの後、特徴マップは活性化関数を通過します。整流関数は、このようなグラフを持っています:
整流器が付加されたニューロンは、整流線形ユニットと呼ばれます。そのため、整流関数をReLU活性化やReLU関数とも呼ぶことがあります。
ReLU活性化は、独自のActivationレイヤーで定義することができますが、ほとんどの場合、Conv2Dの活性化関数としてそれを含めるだけで十分です。
model = keras.Sequential([
layers.Conv2D(filters=64, kernel_size=3, activation='relu')
# More layers follow
])
活性化関数については、ある重要性の基準に従ってピクセルの値を評価するものと考えることができます。ReLU活性化は、負の値は重要でないとし、それらを0に設定します。("重要でないものはすべて同じくらい重要でない。")
上記の特徴マップにReLUを適用したものがこちらです。特徴を際立たせることに成功しているのがわかります。
ReLU関数のような他の活性化関数は非線形です。基本的には、ネットワーク内のすべての層の全体的な効果は、効果を単純に足し合わせて得られるものとは異なるということを意味します。これは、単一の層だけで達成できるのと同じです。非線形性により、特徴はネットワークの深い部分に移動するにつれて興味深い方法で組み合わさります。
わかりやすい。
例題です。
import tensorflow as tf
import matplotlib.pyplot as plt
plt.rc('figure', autolayout=True)
plt.rc('axes', labelweight='bold', labelsize='large',
titleweight='bold', titlesize=18, titlepad=10)
plt.rc('image', cmap='magma')
image_path = '../input/computer-vision-resources/car_feature.jpg'
image = tf.io.read_file(image_path)
image = tf.io.decode_jpeg(image)
plt.figure(figsize=(6, 6))
plt.imshow(tf.squeeze(image), cmap='gray')
plt.axis('off')
plt.show();
フィルタリングステップのために、カーネルを定義し、それを畳み込みで適用します。この場合のカーネルは「エッジ検出」カーネルです。tf.constantを使用してカーネルを定義することができます。これは、Numpyでnp.arrayを使用して配列を定義するのと同じような方法です。これにより、TensorFlowが使用するタイプのテンソルが作成されます。
import tensorflow as tf
kernel = tf.constant([
[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1],
])
plt.figure(figsize=(3, 3))
show_kernel(kernel)
ちょっとした準備
# Reformat for batch compatibility.
image = tf.image.convert_image_dtype(image, dtype=tf.float32)
image = tf.expand_dims(image, axis=0)
kernel = tf.reshape(kernel, [*kernel.shape, 1, 1])
kernel = tf.cast(kernel, dtype=tf.float32)
フィルタをかけてみます。
image_filter = tf.nn.conv2d(
input=image,
filters=kernel,
# we'll talk about these two in lesson 4!
strides=1,
padding='SAME',
)
plt.figure(figsize=(6, 6))
plt.imshow(tf.squeeze(image_filter))
plt.axis('off')
plt.show();
次に、ReLU関数を使用した検出ステップです。この関数は畳み込みよりもはるかにシンプルで、設定するパラメータがありません。
image_detect = tf.nn.relu(image_filter)
plt.figure(figsize=(6, 6))
plt.imshow(tf.squeeze(image_detect))
plt.axis('off')
plt.show();
そして、特徴マップを作成しました!このような画像は、ヘッドが分類問題を解決するために使用するものです。ある特徴が車の特徴であり、他の特徴がトラックの特徴である可能性があることを想像することができます。訓練中のconvnetのタスクは、それらの特徴を見つけることができるカーネルを作成することです。