導入
前の2つのレッスンで、画像からの特徴抽出を行う3つの操作について学びました:
1. 畳み込み層を使ったフィルタリング
2. ReLU活性化関数による検出
3. 最大プーリング層を使った集約
畳み込みとプーリングの操作には共通の特徴があります:両方ともスライディングウィンドウ上で実行されます。畳み込みの場合、この「ウィンドウ」は、kernel_sizeというパラメータによって与えられるカーネルの次元によって与えられます。プーリングの場合、それはpool_sizeによって与えられるプーリングウィンドウです。
引用:https://www.kaggle.com/code/ryanholbrook/the-sliding-window
ウィンドウのストライドと画像の端でのパディングの使用に影響する2つの追加のパラメータが、畳み込み層とプーリング層の両方に存在します。stridesパラメータは、ウィンドウが各ステップでどれだけ移動するかを指定し、paddingパラメータは、入力の端にあるピクセルをどのように扱うかを説明しています。
これら2つのパラメータを使用して、2つのレイヤーを定義すると次のようになります:
from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
layers.Conv2D(filters=64,
kernel_size=3,
strides=1,
padding='same',
activation='relu'),
layers.MaxPool2D(pool_size=2,
strides=1,
padding='same')
# More layers follow
])
ストライド
ウィンドウが各ステップで移動する距離をストライドと呼びます。画像の両方の次元でストライドを指定する必要があります:左から右への移動と上から下への移動のためのものです。このアニメーションは、各ステップで2ピクセル移動するstrides=(2, 2)を示しています。
引用:https://www.kaggle.com/code/ryanholbrook/the-sliding-window
ストライドが持つ効果は何でしょうか? いずれの方向のストライドも1より大きい場合、スライディングウィンドウは各ステップで入力の一部のピクセルをスキップします。
分類のための高品質の特徴を使用したいので、畳み込み層はほとんどの場合、strides=(1, 1)を持つことが最も一般的です。ストライドを増やすと、私たちのサマリーの中で有用な情報を逃す可能性があります。しかし、最大プーリング層は、(2, 2)や(3, 3)のように1より大きいストライド値をほぼ常に持っていますが、ウィンドウ自体より大きくはありません。
最後に、ストライドの値が両方の方向で同じ数字の場合、その数字を設定するだけでよいことに注意してください。例えば、strides=(2, 2)の代わりに、パラメータの設定にstrides=2を使用することができます。
パディング
スライディングウィンドウの計算を実行する際に、入力の境界で何をすべきかという疑問が生じます。入力画像の完全に内側にとどまると、ウィンドウは入力の他のすべてのピクセルと同様に、これらの境界ピクセルの上に正確に座ることはありません。すべてのピクセルを正確に同じように扱っていないので、問題があるのではないでしょうか?
これらの境界値での畳み込みの動作は、そのpaddingパラメータによって決まります。TensorFlowでは、padding='same'またはpadding='valid'の2つの選択肢があります。それぞれにはトレードオフがあります。
padding='valid'を設定すると、畳み込みウィンドウは入力の完全に内側にとどまります。欠点は、出力が縮小する(ピクセルが失われる)ことで、大きなカーネルではさらに縮小します。これにより、ネットワークが含むことができるレイヤーの数が制限され、特に入力が小さい場合には影響します。
代わりにpadding='same'を使用する方法があります。ここでのコツは、入力の周囲に0をパディングして、出力のサイズを入力のサイズと同じにするために十分な0を使用することです。ただし、これにより境界のピクセルの影響が薄れる効果がある場合があります。以下のアニメーションは、'same'パディングを持つスライディングウィンドウを示しています。
VGGモデルは、すべての畳み込み層でsameパディングを使用しています。最新の畳み込みネットワークの多くは、2つの組み合わせを使用します。(さらに調整するパラメータもあります!)
例 - スライディングウィンドウの探索
スライディングウィンドウのパラメータの影響をよりよく理解するために、個々のピクセルを見ることができる低解像度の画像で特徴抽出を観察すると役立ちます。単純な円を見てみましょう。
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 = circle([64, 64], val=1.0, r_shrink=3)
image = tf.reshape(image, [*image.shape, 1])
Bottom sobel
kernel = tf.constant(
[[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]],
)
show_kernel(kernel)
VGGアーキテクチャはかなりシンプルです。ストライド1の畳み込みと、2x2のウィンドウとストライド2の最大プーリングを使用しています。visiontoolsユーティリティスクリプトには、すべてのステップを表示する関数が含まれています。
show_extraction(
image, kernel,
# Window parameters
conv\_stride=1,
pool\_size=2,
pool\_stride=2,
subplot\_shape=(1, 4),
figsize=(14, 6),
)
それはかなりうまくいきますね!カーネルは水平線を検出するように設計されているので、結果として得られる特徴マップでは、入力の中でより水平な部分が最も高い活性化を持っているのがわかります。
畳み込みのストライドを3に変更した場合、どうなるでしょうか?
show_extraction(
image, kernel,
# Window parameters
conv\_stride=3,
pool\_size=2,
pool\_stride=2,
subplot\_shape=(1, 4),
figsize=(14, 6),
)
これは抽出された特徴の質を低下させるように見えます。入力された円は、幅が1ピクセルしかないため、「細かいディテール」を持っています。ストライド3の畳み込みは、これから良質な特徴マップを生成するのに粗すぎるようです。
時々、モデルは初期の層で大きなストライドを持つ畳み込みを使用します。これは通常、より大きなカーネルと組み合わされます。たとえば、ResNet50モデルは、最初の層でストライド2の7×7カーネルを使用します。これは、入力からの情報をあまり犠牲にせずに、大規模な特徴の生成を加速するように見えます。
結論
このレッスンでは、畳み込みとプーリングの両方に共通する特徴的な計算、すなわちスライディングウィンドウとこれらの層での動作に影響を与えるパラメータについて見てきました。このようなウィンドウ化された計算スタイルは、畳み込みネットワークの特徴の多くを寄与し、その機能の不可欠な部分です。