今回は、ディープラーニングの画像処理で一般的なCNNで使うメインのレイヤーの出力を視覚化して確認してみます。
レイヤーの出力を眼で見て確認(Convolution/Max Pooling)
仕組とかについては、こちらで整理したりもしてるのですが、やっぱ、理論だけよりも視覚でも確認してみると、また違った理解ができるかな・・という感じです。
SquaredErrorを使います
SquaredError を使い、Max Epoch 0 で学習・評価実行すると、その直前のレイヤーまでの加工結果をモニタすることができるのを利用します。
今回は画像データで
Inputデータは、とりあえずMNISTを使います。
対象にするレイヤーは、CNNではお馴染みのConvolutionとPoolingです。
日本語では畳み込み層とプーリング層といわれているものですが、このレイヤーの加工結果を見るには、ある程度、この2つの層の働きと動きを知っておかないと・・たぶん・・訳が分からないです。
だから、その説明も混ぜ込みながら、ぼちぼちやっていきます。
画像の場合はNeural Network ConsoleのOutput Resultで画像を表示してくれます。
EXCELとかは不要です。
まずはConvolution層のみ
さて、まず、Convolutionのみの加工結果をアウトプットしてみます。
例によって、Max Epoch=0にしています。
InputデータはMINISTの「4」。
それに対して、OUTPUTされたのは以下の16画像です。
これを見て、「なんで16個も画像がOUTPUTされるの?」とか「同じINPUTなのに、なんでOUTPUTの画像がそれぞれ違うの?」などと疑問を持つ人もいると思うので、ちょっとざっくり補足しておきます。
1つの画像にたいして16画像も出力されるわけ
まず、なんで「16画像も出力されるのか」ですが、それはConvolutionのレイヤープロパティの「OutMaps」が16になっているからです。
何故、16がデフォルトか?というと、たぶん、それが標準的に良い精度を期待できると考えられたからでしょう。(ざっくり・・笑)
生成される16画像はなぜ違う?
じゃあ・・。
何故、16個のOUTPUT画像がそれぞれ違うのか?・・です。
まず、Convolutionで出力を計算する手順の理解が必要です。
実際のデータではややこしいので、説明用に元の画像データ(7×7)で、KarnelShape(フィルターサイズ)が「3×3」、OUTPUTが「3×3」の簡単なモデルで例をのせます。
元データの左上の「3×3」の数値と、カーネル(フィルター)の「3×3」の対応する位置の数値を掛け合わせて全部足して(上記の例なら 0*8+1*7+2*6+3*5+4*4+5*3+6*2+7*1+8*0)、結果の84をOUTPUTの左端にセットする・・みたいな感じで計算するわけです。
そうして横や下方向にStridesで指定された数の分ずらしながら同じことをやって、OUTPUTを埋めていくわけですね。
これが意味すること・・つまり、カーネル(フィルター)の数字によって、OUTPUTのデータは変化するということです。
ディープラーニングって、結局、学習データのバリエーションが沢山あった方が精度があがるという傾向があります。
なので、OUTPUT16パターンがデフォルトで、しかも同じものばっかり出力しても無駄なだけなので、カーネル(フィルター)の数字を買えながら、バリエーションを作っている・・ということなんでしょうね。
続いてPooling層を付け加えてみます
今度はPooling層を追加してみます。
使うのは「MaxPooling」です。
このアウトプットイメージはこんな感じです。
上のConvolutionの出力だとギザギザだったところが均されて、シャープな印象の画像になっているのがわかると思います。
これが、まさしくPooling層の仕事です。
Max Poolingの仕組をさらっと
デフォルトのMaxPoolingのパラメータは、こうなってます。
やってることは単純です。
元データの左上から「KernelShape」で指定した範囲(上だと2×2)の中で、一番大きい数字のみをOUTPUTに出力する。
終わったら、Strides分だけずらながら同じことをやっていくわけです。
Convolutionと違って、Poolingでは重複させないように、KernelShapeとStridesは同じにするものだそうです。
言葉だとイメージしづらいので、8×8の簡単なサンプルを描きました。
KernelShapeが2×2なので、上記左上の4つ(色付きのところ)をまず、見ます。
そうすると「1,2,7,8」の4つの数字なので、一番大きい「8」がアウトプットになる。
こんな感じです。
なので、KernelShape、Stridesが2,2の場合は、OUTPUTのサイズは縦横とも半分になります。
実際、Neural Network Consoleが自動計算したサイズを見ても、24×24が、12×12と縦横半分になってますよね。
一番大きい数字=その領域で最も特徴を強く表す数字だけをOUTPUTしていくので、上記の図みたいに、Convolutionの出力の特徴をより明確にした感じになるわけです。
視覚的なイメージを持つのは悪くない
やっぱ、文系人間ですから。
数式とかで見ても、イメージがしづらい。
ディープラーニングだとレイヤーを何層も重ねていくので、前のアウトプットが次のインプットになって・・みたいな感じになるので、アウトプットのイメージがないと何となくやってますになってしまいがちです。
なので、Neural Network Consoleで気軽にアウトプットイメージをつかめるのは、有難いです。
同じことは、tensorflowとかでもできますけど、ちょっとイメージをつかむために、ガリガリpythonでプログラムを書くよりは、GUIで簡単にできるに越したことありませんからねえ。
ではでは。