"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

CNNの畳み込み層(Convolution)について数式なしでざっくり整理/ディープラーニング

f:id:arakan_no_boku:20190330090249j:plain

CNN(Convolutional Neural Network)の Convolution=「畳み込み層」についてざっくり整理してみます。 

目次

Convolution=畳み込み

 Convolution=「畳み込み層」は、画像処理で非常に優秀な成績をたたきだす「CNN(Convolutional Neural Network)」の構成要素のひとつとして、超有名です。

通常は、Pooling層とセットで使われて、説明も両方セットでされることが多いですが、今回は「Convolution=畳み込み層)だけに絞って整理します。

例によって、まずはレイヤーリファレンスの引用から。

Convolution


入力値に対して畳み込み演算を行うレイヤーです。

Ox,m = Σ_i,n Wi,n,m Ix+i,n + bm(1次元Convolutionの場合)

Ox,y,m = Σ_i,j,n Wi,j,n,m Ix+i,y+j,n + bm(2次元Convolutionの場合)

(Oは出力、Iは入力、i,jはカーネルサイズ、x,y,nは入力のIndex、mは出力マップ(OutMapsプロパティ)、Wはカーネルの重み、bは各カーネルのバイアス項を示す)

 

さらに、Wikipediaの説明を引用すると。

畳み込み(たたみこみ、英: convolution)とは関数 g を平行移動しながら関数 f に重ね足し合わせる二項演算である。

畳み込み積分、合成積、重畳積分、あるいは英語に倣いコンボリューションとも呼ばれる。

なんだそうですが、なかなか難しいです。 

そもそも、これでわかる人は、この先読む必要はありません。

全結合層だけだと位置情報が考慮されない 

MNISTの手書き文字データくらいなら全結合層でも、それなりの精度はでます。

でも、それなり・・です。

全結合層には画像の特徴をつかまえるには不適な問題があるからです。

これを、超わざとらしい例ですが、以下のような画像データで確認してみます。

画像データ「A」がこちら。

f:id:arakan_no_boku:20181109003219j:plain

画像データ「B」がこちら。

f:id:arakan_no_boku:20181109003324j:plain

画像としてみると、「A」と「B」は、明らかに違うものです。

似ても似つかない形ですから。

でも、画像データを構成する要素「0」と「255」の数は同じです。

つまり、この「あきらかな違い」は、データを構成する要素の出現数の違いではなく、その要素が出現する「位置」によって決定されています。

こういうふうなデータが全結合だと、同じに見えてしまうことがあります。

そうなる理由は、こちらで整理しています。

arakan-pgm-ai.hatenablog.com  

位置関係の情報を考慮するための畳み込み演算

上記の例みたいな画像データの位置関係の情報を考慮して比較する。

それを実現するのが「CNN(Convolutional Neural Network)」であり、その中核をになう「Convolutionレイヤー=畳み込み層)」なわけです。

だから、画像に関しては「CNN(Convolutional Neural Network)」を使う方が、より高い精度が得られるといわれる所以です。  

位置情報を残すには、畳み込み演算というのを使います。

畳み込み演算の例を説明するのに、上記例の28*28だとごちゃごちゃするので、シンプルな5*5の以下の例を使います。

f:id:arakan_no_boku:20181110133906j:plain

形は全く違う(別物)だけれど、数値データとしてみると、「5」と「0」の数が同じという点については、上記例と同じにしてあります。

畳み込み演算には、全結合のようなウエイトではなく、フィルターを使います。

フィルターはカーネルKernel)とも言います。

Neural Network Consoleではカーネルなのですが、自分の個人的好みで「フィルター」のほうがしっくりくるので、あえて「フィルター」と書かせてもらいます。

今回の例では、3×3のフィルターを使います。

フィルターの各値は、計算しやすいように全部「1」にしてます。

f:id:arakan_no_boku:20181110135710j:plain

畳み込み演算の計算例

これで、どうやって計算するかというと。

まず、入力の左上から、フィルターのサイズと同じ領域とフィルターで計算します。

計算方法は、入力とフィルターの対応する位置の数字同士を掛け算して足します。

f:id:arakan_no_boku:20181110141852j:plain

上記なら「0*1+0*1+5*1+0*1+0*1+0*1+0*1+0*1+0*1」で答えは「5」です。

そして、左上の計算が終わったら、右に1つずらして、同じ計算をします。

そして、その答えをさっきの横に置きます。

f:id:arakan_no_boku:20181110142712j:plain

次にもう一つ右にずらして同じようにします。

f:id:arakan_no_boku:20181110142806j:plain

で・・端までいったら、一つ下にずらして、また左から。

f:id:arakan_no_boku:20181110143325j:plain

これを繰り返すと、結果は以下のようになります。

f:id:arakan_no_boku:20181110143446j:plain

そして、もうひとつの図形にも同じ畳み込み演算を適用します。

すると。

f:id:arakan_no_boku:20181110143638j:plain

どうですか。

出力同士を見比べてもらうと、全然別物になりました。

画像全体を構成している数値の数が同じでも、出現する位置によって出力結果が異なり、別物と識別しやすくなってますよね。

位置情報が残っている・・と言えます。

これが、「Convolutionレイヤー=畳み込み層)」が「Affine=全結合層」では区別が難しかった画像でも違いを認識して精度があがる理由です。

NNCのConvolutionレイヤープロパティの例 

Neural Network ConsoleのConvolutionレイヤーのプロパティの例です。

f:id:arakan_no_boku:20181110144120j:plain

ここの、kernelShapeとあるのが、上記のフィルターのサイズです。

上記例なら、3,3ですね。

Strideは、横と下にいくつずつずらすか?です。

上記例ならひとつずつなので1,1になります。

あと、paddingとかありますが、よく考えたら、この辺の説明は以下の記事で詳しく書いているので、この辺にします。

arakan-pgm-ai.hatenablog.com

ではでは。