Pynote

Python、機械学習、画像処理について

Deep Learning - 畳み込みニューラルネットワーク (CNN) について

CNN

畳み込み層 (convolutional layer) を含むニューラルネットワークを畳み込みニューラルネットワーク (convolutional neural network / CNN) という。
入力が画像である場合に、画像から特徴を抽出する目的で用いられる。

畳み込み層

畳み込み層は画像処理のフィルタリングに該当する処理を行う。
フィルタリングは、入力から輪郭や色などの特徴を抽出することができる。

pynote.hatenablog.com

フィルタリングは入力画像の各画素に対して、カーネルと重なる部分の画素値とカーネルの重みを乗算し、総和を計算し、出力画像を作成する処理であった。
これは、以下のニューラルネットワークで表現できる。

実際は、出力はニューロンを以下のようにすることで、カーネルをスライドさせるのではなく、一度に計算できる。

畳み込み層の出力は、フィルタリングによって抽出された特徴を含むので、特徴マップ (feature map) という。また、入力に対してニューロンが反応した結果と見ることもできるので、活性化マップ (activation map) ということもある。
フィルタリングは使用するカーネルの重みによって、抽出できる特徴が変わってくるが、これをパラメータとすることで、学習を通してタスクを解くために有益な重みが決定する。

全結合層との違い

全結合層では、あるニューロンは前のすべてのニューロンと結合していた。
一方、畳み込みニューラルネットワークはあるニューロンは前の層の一部のニューロンとのみ結合している。
これを疎結合という。

また、全結合では結合ごとに異なる重みを保持していたが、畳み込み層では、出力の各要素を計算する際に用いられる重みはすべて同じである。これを重み共有という。

上記の場合は、畳み込み層の各ニューロンは前の層の 3 \times 3 \times 3 = 27 個のニューロンと結合している。各ニューロンでの結合の重みは全部同じものが用いられる。

畳み込み層の出力数

1つのカーネルによる畳み込みの結果は、1チャンネルの特徴マップになるので、M 個のカーネルをそれぞれ適用すれば、M 個の異なる特徴マップが得られる。


畳み込み層の各ニューロンの入力

前の層から受け取る入力の形状が H_x \times W_x \times C_x で各要素は

\displaystyle
x_{ijk} \ , (
    i = 0, 1, \cdots, H_x - 1;
    j = 0, 1, \cdots, W_x - 1;
    k = 0, 1, \cdots, C_x - 1)
と参照する。

M 個のカーネルの形状が H_f \times W_f \times C_f で各要素は

\displaystyle
w_{ijkm} \ , (
    i = 0, 1, \cdots, H_f - 1;
    j = 0, 1, \cdots, W_f - 1;
    k = 0, 1, \cdots, C_f - 1;
    m = 0, 1, \cdots, M)
と参照する。ただし、カーネルのチャンネル数と入力のチャンネル数は同じ C_f = C_x とする。

このとき、各ニューロンが受け取る入力 u_{ijkm} は次のように計算される。

\displaystyle
u_{ijm} = \sum_{s = 0}^{H_f - 1} \sum_{t = 0}^{W_f - 1} \sum_{k = 0}^{C_f - 1} x_{i + s, j + t, k} \ \ w_{stum} + b_m

b_m はバイアス項である。

畳み込み層の各ニューロンの出力

ニューロンの入力に対し、活性化関数 f を適用したものが出力となる。

y_{ijm} = f(u_{ijm})

パディング

畳み込みを行った結果、出力される特徴マップの幅及び高さは元の画像より小さくなる。
これを防ぐため、出力の特徴マップの幅及び高さが元の画像と同じになるように、畳み込みをする前に入力の周囲に余白を足すパディング (padding)を行うことがある。
追加した余白にどのような値を入れるかが問題となりますが、Deep Learning では、値が 0 の余白を追加するゼロパディング (zero padding) が一般的に使用される。
詳しくは以下を参照されたい。

pynote.hatenablog.com

ストライド

今までフィルタは幅及び高さ方向に1ステップずつ移動させていたが、このフィルタの移動量をストライド (stride) という。
ストライドを増やすと出力される特徴マップのサイズは小さくなるが、その分入力から拾える情報量が減ってしまうため、畳み込みでは基本的にストライドは幅及び高さ方向に (1, 1) が使われる。

ストライド(W_s, H_s) とした場合、特徴マップの各要素は以下のように計算できる。

\displaystyle
u_{ij} = \sum_{s=0}^{H_f - 1} \sum_{t=0}^{W_f - 1} x_{H_s i + s, W_s j + t} w_{st}

特徴マップのサイズは以下のようになる。

\displaystyle
(
(\left\lfloor (H_x – 1) / H_s \right\rfloor + 1) – 2 \left\lfloor H_f /2 \right\rfloor)
\times
(\left\lfloor (W_x – 1) / W_s \right\rfloor + 1) – 2 \left\lfloor W_f /2 \right\rfloor)

ストライドで移動していった結果、端で余ってしまった部分は切り捨てられる。

5 \times 5 の画像に対して、2 \times 2カーネルストライド (2, 2) で移動させた結果である。
余ってしまった5行目、5列目は切り捨てられる。

参考