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

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

なんだそうです。

だから、ニューラルネットワークの「Convolution」は、まんまじゃないか・・。

そういわれてもねえ。

自分にはさっぱりです。

自分以外の文系出身者で同じ思いをしている人は多いのではないですかね。

 

何でCNNが必要なのか

 

実際のところ。

Neural Network Consoleとか、kerasとかでやってみると、MNISTデータとかなら全結合層だけだけでも、それなりの精度はでます。

でも、全結合層にはある問題があり、画像に関しては「CNN(Convolutional Neural Network)」を使う方が、より高い精度が得られるようになってます。。

その全結合層のある問題とは何か?

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

画像データ「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レイヤー=畳み込み層)」なわけです。

 

 どういうやり方で位置情報を残すのか

 

どうやって位置情報を残すのか?です。

それには、畳み込み演算というのを使います。

畳み込み演算の例をするのに、上記例の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

ではでは。