"BOKU"のITな日常

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

ニューラルネットワークの学習を部品(レイヤー)別にざっくり整理/CNNの畳み込み層(Convolution)

f:id:arakan_no_boku:20190330090249j:plain

目次

CNN(Convolutional Neural Network)の前説

ニューラルネットワークの学習を部品(レイヤー)別にざっくり整理をタイトルにした記事は、専門用語を極力使わず、多少の不正確さは目をつぶっても、なんとなくイメージできることを目標にして整理しています。

まず、ニューラルネットワークで学習する流れをざっくり図にしてみました。

f:id:arakan_no_boku:20170825221728j:plain

ニューラルネットワークの目的のひとつとして「既存の正解がわかっているデータで勉強(学習)して、未知のデータから、正解が導けるようになること」があります。

ポイントはどうやって「勉強(学習)」するか?ですが、ニューラルネットワークでは、それを「計算」でやってます。

どういうことかというと。

既存の正解のわかっている入力データにたいして、パラメータ(重み)をかけあわせる計算を行い、その結果をもとに答えを出して、答え合わせを行い、間違ってたら、正解に近づけるようにパラメータ(重み)を少し修正するみたいなことを延々と繰り返して、もっとも。正解に近い結果を計算で求められる確率の高いパラメータ(重み)の値を決めていく・・のを学習と呼んでいるわけです。

上記の図は、それをごく簡易的に書いてます。

上記の図では「計算して結果を整えて、それを次の入力にする」部分を1回しか書いてませんが、実際は、そこが何層にもわかって繰り返されることで、学習の精度をあげようというのが、ニューラルネットワークであり、ディープラーニングなどと言われるゆえんということです。

今回とりあげるCNN(Convolutional Neural Network)というのは、上図では「① 計算(計算×重み+α)」にあたります。

同じ部分にあたる部品(レイヤー)としては、「全結合層(Affine)」がありますが、画像データの分類に関して、より優れた方法として考え出されたのが、CNN(Convolutional Neural Network)です。

CNN(Convolutional Neural Network)は2段階で構成されます。

  • Convolution(畳み込み)層
  • Pooling層

です。

ここからは、Convolution(畳み込み)層に絞って話を続け、Pooling層については別記事とします。

画像データを全結合層で処理して精度があがらない理由 

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レイヤー=畳み込み層)」です。

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

畳み込み演算の例を説明するのに、上記例の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=全結合層」では区別が難しかった画像でも違いを認識して精度があがる理由です。

個人的には。

このあたりがイメージできるようになると、CNNの理解が一歩すすんだ感じになれるんじゃないかと思っています。

説明はこんなところです。

おまけ:Neural Network Consoleのレイヤーリファレンス

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

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

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

相変わらず、難しいです。

でも、まあ意味するところは、この記事の前のほうで書いたことと同じです。

おまけ: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

ではでは。

 

PS:他の部品(レイヤー)については、以下にまとめてます。

arakan-pgm-ai.hatenablog.com