7章 畳み込みニューラルネットワーク

7.1 全体の構造

CNNはニューラルネットワークと同様、複数のレイヤを組み合わせて作成する。CNNでは新たに「Convolutionレイヤ(畳み込み層)」と「Poolingレイヤ(プーリング層)」が登場する。

これまで出てきたニューラルネットワークは隣接する層の全てのニューロン間を結合する全結合(fully-connected)であり、Affineレイヤと言う名前で実装してきた。例として全結合のニューラルネットワークでは「Affineレイヤ→活性化関数ReLUレイヤ」の組み合わせを1層として複数層で構築し、出力層にはSoftmaxレイヤを用いていた。

CNNでは「Convolutionレイヤ→ReLU→(Poolingレイヤ。省略される場合あり)」を1層として構築する。また、出力に近い層ではこれまでの「Affine→ReLU」が、出力層には「Affine→Softmax」が用いられることが一般的には多い。

7.2 畳み込み層

7.2.1 全結合層の問題点

全結合層では隣接する層のニューロンがすべて連結されており、出力数は任意に定めることができる。問題点としてはデータの形状が無視されてしまうことである。入力データが画像の際には縦・横・チャンネル方向の3次元形状だが、全結合層へ入力する際には一列の配列(1次元)にする必要がある。そのため空間的な近さなどの本質的な近さを無視して扱うので情報を活かす事ができていない。

畳み込み層(Convolutionレイヤ)は形状を維持する。画像のデータを3次元として扱い、次の層にデータ出力することができる。CNNでは畳み込み層の入出力データを「特徴マップ(feature map)」と言う場合がある。更に、畳み込み層の入力データを「入力特徴マップ(input feature map)」、出力データを「出力特徴マップ(output feature map)」と言う。

7.2.2 畳み込み演算

畳み込み層で行う処理は「畳み込み演算」である。畳み込み演算は入力データに対してフィルターを適用する。

入力データが縦・横方向の形状を持つデータに対して、フィルターも同様に縦・横方向の次元を持たせる。例として、入力サイズが4×4、フィルターサイズが3×3、出力サイズが2×2などのようになる。文献によっては「フィルター」という単語は「カーネル」とも言われる。

畳み込み演算は入力データに対してフィルターのウィンドウを一定の間隔でスライドさせながら適用する。それぞれの場所でフィルターの要素と入力の要素を乗算し、その和を求める(この計算を積和演算と呼ぶ)。結果を出力の対応する場所へ格納するプロセスをすべての場所で行なう子男tで畳み込み演算の出力を得ることが出来る。

CNNにおける重みパラメータはフィルターのパラメータにあたる。また、バイアスはフィルター適用後のデータに対して加算する、一つの固定値(いずれの要素に対しても)である。

7.2.3 パディング

畳み込み層の処理を行うにあたり、入力データの周囲に固定のデータ(0など)を埋めることがある。これを「パディング」という。例として4×4の入力データに対して幅1のパディングを適用するなどである。周囲を幅1ピクセル0で埋めることを言う。(パディング適用後は6×6のデータとなる)

パディングを用いる理由は出力サイズを調整するためにある。4×4の入力データに3×3のフィルターを適用した場合、出力サイズは2×2となってしまう。ディープなネットワークにおいては小さくなり続けて処理できなくなってしまう。そこでパディングを用いるとデータサイズを保つことができる。

7.2.4 ストライド

フィルターを適用する位置の感覚を「ストライド(stride)」と言う。ストライドを2とするとフィルターを適用する窓の間隔が2要素毎になる。

ストライドを大きくすると出力サイズが小さくなるが、パディングを用いると出力サイズは大きくなる。出力サイズの計算を考えてみる。 入力サイズを$(H,W)$、フィルターサイズを$(FH,FW)$、出力サイズを$(OH,OW)$、パディングを$P$、ストライドを$S$とする。出力サイズは以下式で求められる。

$$ OH = \frac{H + 2P - FH}{S} + 1 \\ OH = \frac{W + 2P - FW}{S} + 1 $$

(例)入力サイズ:(4,4)、パディング:1、ストライド:1、フィルターサイズ:(3,3) $$ OH = \frac{4+2・1-3}{1} + 1 = 4\\ OH = \frac{4+2・1-3}{1} + 1 = 4 $$

7.2.5 3次元データの畳み込み演算

画像の場合、縦・横方向に加えてチャンネル方向も合わせた3次元データを扱う必要がある。チャンネル別にフィルターを用意して畳み込み演算を行い、すべての結果を加算して出力を得る。

チャンネル数とフィルターの数は一致している必要があり、チャンネル毎のフィルターサイズは全て統一する必要がある。

7.2.6 ブロックで考える

3次元の畳み込み演算はデータやフィルターを直方体のブロックで考える事ができる。多次元配列として表す時は(channel, height, width)の順に並べて書く。フィルターの場合フィルターの高さをFH(Filter Height)、横幅をFW(Filter Width)と記載する。

フィルターが一つの時には出力データはチャンネル数1つの特徴マップになる。チャンネル方向にも複数持たせるためには、複数のフィルター(重み)を用いる。フィルターの重みデータは4次元データとして(output_channel, input_channel, height, width)の順に書く。 また、バイアスは1チャンネル毎に1つ持つため形状は(FN, 1, 1)である。

7.2.7 バッチ処理

ニューラルネットワークの処理では、入力データをひと束にまとめたバッチ処理を行っていた。畳み込み演算でも同様にバッチ処理を行なう。その為、各層を流れるデータとして4次元のデータ(batch_num, channnel, height, width)を格納する。

7.3 プーリング層

プーリングは縦・横方向の空間を小さくする演算である。例えば2×2の領域を一つの要素に集約するような処理である。 「Maxプーリング」は対象とする領域のサイズ無いで最大値を取る演算である。一般的にプーリングのウィンドウサイズとストライドは同じ手に設定する。

プーリングにはMaxプーリングの他に、Averageプーリングなどがある。Averageプーリングは対象領域の平均を計算する。画像認識の分野においては主にMaxプーリングが使われる

7.3.1 プーリング層の特徴

  • 学習するパラメータが無い プーリング層は畳み込み層と違って学習するパラメータを持たない。(最大値を取るだけなので)

  • チャンネル数は変化しない チャンネルごとに独立して計算が行われるため、チャンネル数は変化しない。

  • 微小な位置変化に対してロバスト(頑健) 入力データの小さなズレに対してプーリングは同じような結果を返す。

7.4 Convoultion/Poolingレイヤの実装

7.4.1 4次元配列

CNNで流れる4次元データが(10, 1, 28, 28)だとすると、高さ28・横幅28・1チャンネル・データが10個ある場合に対応する。

以下処理でランダムデータが作成できる。 x = np.random.rand(10, 1, 28, 28)

7.4.2 im2colによる展開

畳み込み演算をfor文で行なうと処理が遅くなってしまう(Numpyでは要素アクセスの際にfor文を使わないほうがよい)。そこでim2colという関数を用いる。

im2colはフィルターにとって都合の良いように展開する関数である。入力データに対してフィルターを適用する場所の領域を横方向に1列に展開する。im2colによる展開はフィルター適用における重複要素を配列として出力するために元ブロックの要素数よりも多くなるため、メモリを多く消費してしまう。

7.4.3 Convolutionレイヤの実装

Convolutionクラスで用いるim2colの引数は以下を設定。

  • input_data:データ数、チャンネル、高さ、横幅の4次元配列からなる入力データ
  • filter_h:フィルターの高さ
  • filter_w:フィルターの横幅
  • stride:ストライド
  • pad:パディング

Convolutionクラスは以下処理を実装する

  • init:初期化メソッド。
    フィルターとバイアス、ストライドとパディングを受け取る
  • forward:順伝播メソッド。
    初期化メソッドで定めたパラメータから出力の高さ、幅のサイズを定める。 Affineレイヤと同じように計算出来るように入力データをim2colを用いて配列化する。 重みもreshape( ,-1)とすることによって配列化を行なう。 入力データ配列と重み配列のドット積を求め、バイアスを加算する。 計算結果をtransposeを用いて整形し、返却する。

7.4.4 Poolingレイヤの実装

Poolingレイヤも同じくim2colを使って入力データを展開するが、チャンネル方向には独立である点が異なる。

7.5 CNNの実装

ネットワークの構成は「Convolution-ReLU-Pooling-Affine-ReLU-Affine-Softmax」とする。

7.6 CNNの可視化

7.6.1 1層目の重みの可視化

今まで行ったMNISTのCNNにおける学習では1層目の重みの形状は(30,1,5,5)(サイズが5×5、チャンネルが1のフィルターが30個)である。フィルターは1チャンネルのグレー画像として可視化出来ると言うことを意味する。 (サンプルコードch07/visualize_filter.py)

学習前のフィルターはランダムに初期化されているため白黒の濃淡に規則性は無いが、学習後は規則性のある画像になっている。白から黒へグラデーションを伴って変化するフィルターや塊のある領域(「ブロブ(blob)」)を持つフィルターなど学習によって更新されていることが分かる。

規則性のあるフィルターは何を見てるのかというと、エッジやブロブなどを見ている。畳み込み層のフィルターはエッジやブロブなどのプリミティブな情報を抽出することが分かる。

7.6.2 階層構造による情報抽出

1層目の畳み込み層ではエッジやブロブなどの低レベルな情報が抽出される。何層も重ねたCNNにおいて各層でどのような情報が抽出されるのかというと、層が深くなるに従って抽出される情報(強く反応するニューロン)はより抽象化されていく。

一般物体認識(車や犬など)を行なう8層のCNNであるAlexNetは畳み込み層とプーリング層が何層も重なり、最後に全結合層を用いて結果が出力される。最初の層は単純なエッジに反応し、続いてテクスチャ、より複雑な物体のパーツへと反応するように変化している。

7.7 代表的なCNN


In [ ]:


In [ ]:


In [ ]: