"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

CNNの畳み込み層(Convolution)の仕組みを数式なしで整理してみた/ディープラーニング

今回は、 Convolution=「畳み込み層」について頭の整理を兼ねて、ざっくり整理してみます。

f:id:arakan_no_boku:20190330090249j:plain

 

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 に重ね足し合わせる二項演算である。

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

なんだそうです。

文系出身の自分にはピンときませんが。

 

画像にはCNNが有効なわけをざっくり見てみる

 

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

「Affineレイヤー=全結合層」は、上記のような「28×28」の二次元のデータでも、計算するときに28×28×1=>784のサイズの1次元のデータにして計算します。

 

例えば、以下みたいなイメージですね。

f:id:arakan_no_boku:20181029005046j:plain

こうなってしまうと。

画像を識別する上で重要な「位置情報」なんか、影も形もありません。

だから、数値データとして「255」と「0」の数が同じ上記のような画像は、同じものと判断される確率が高くなってしまって、結果的に間違った分類につながるリスクがあるわけです。

 

そこでCNNの登場です

 

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

それを実現するのが「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=全結合層」では区別が難しかった画像でも違いを認識して精度があがる理由です。

 

Neural Network Consoleのプロパティで見てみる

 

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

f:id:arakan_no_boku:20181110144120j:plain

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

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

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

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

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

arakan-pgm-ai.hatenablog.com

ではでは。