畳み込みニューラルネットワークの入門メモ

Python, ML07 January 2021

What's CNN

畳み込みニューラルネットワーク(CNN)はディープラーニング領域で用いられるアルゴリズム(手法)の1つ。 元々は画像認識分野において使用するものをとして開発されたが、便利すぎるので以下のような分野でも使用されている。

  • 画像認識
    • 画像にある動物は何か?文字は何か?
  • 画像処理
    • 色の抽出や、縦線のみの取り出しなんかも
  • 音声解析
    • 自動音声翻訳とか

基本定義

CNNは一見難しそうに聞こえるが、とても難しい。(僕にとっては) しかし、実際に行われる仕組みは以下の3つに集約される。

  1. 畳み込み
  2. Activation(活性化関数)
  3. プーリング

この内、2. Activation(活性化関数)についてはCNNと言うよりも、一般的なニューラルネットワークにおいて必須となるものなので 本記事内での解説は省略する。 ちなみに活性化関数は、現在ではほぼReLUが使用される。

フィルタ

  • 畳み込みにおいてはフィルタという概念で計算を行う。
  • フィルタは本体の画像よりも小さいグリッドで、画像グリッドの左上から行列演算的に画像の上をスライドする
  • 全てスライドし終わった=畳み込みを行ったということになる
  • ずらす数のことを「ストライド」という
  • フィルタを使用することで、本来画像のピクセル分の重みが必要なところを、フィルタサイズ分の重みで可能になる
  • 画像はどこに何が写っていてもその位置は関係ないという特製があるので、フィルタを動かしても同じ重みを使うことができる

CNNではこのフィルタを組み合わせることで、必要な情報を画像から抽出していく

グリッド描くの面倒なので参考

以下、特別なフィルタには名前がついている

ラプラシアンフィルタ

  • 中心が「8」で他が「-1」のフィルタ
  • 輪郭だけを抽出できる

ソーベルフィルタ

  • 縦線だけを抽出できる

フィルタと入出力のサイズ

以下の通り入力とフィルタのサイズ、個数を定義する

入力

  • 高さ: h
  • 幅: w
  • チャンネル数: c

フィルタ

  • 高さ: k
  • 幅: k
  • チャンネル数: c
  • フィルタの個数: N

上記の場合、出力のサイズは以下となる

出力

  • 高さ: h'
  • 幅: w'
  • チャンネル数: N

ここで、h', w'は以下の条件を満たす。(一般的には小さくなる)

$$ h'<=h$$
$$ w'<=w$$

パディング

  • 上記の通り、畳み込みを行うと普通出力のサイズは入力よりも小さくなってしまう。
  • 畳み込みは繰り返し行いたいので、小さくなり続けられると画像が消えてしまい困る。
  • そこでパディングという手法で予め入力の画像を大きくする

zero-padding

小さくなってしまう分を予め0埋めで大きくする手法。

どれくらいパディングすれば良いか?=出力サイズの計算方法

パディングするにあたって、予め出力時にどれだけ小さくなるか?がわかっている必要がある。 以下の通り計算可能

  • h': 出力時の高さ
  • w': 出力時の幅
  • p: パディングサイズ
  • k: フィルタサイズ(高さ=幅)
  • s: ストライド
$$ h'= \frac{(h+2p-k)}{s} +1 $$
$$ w'= \frac{(w+2p-k)}{s} +1 $$

プーリング

  • 入力画像を縮小する
  • フィルタは基本3✖️3程度なので、大きい画像を大局的に見たい(畳み込みたい)場合は縮小する
  • 対象の並進移動に強くなる(ロバストという)

MAXPooling

  • 画像の一定範囲の最大数だけ抽出する
  • 基本これを使う

AveragePooling

  • 画像の一定範囲の平均を抽出する
  • あまり精度でない

DilatedConv

  • フィルタの当て方を0詰めでなく、飛ばし飛ばしに当てる
  • 実際コードで書くときには、間に0で埋めたフィルタを当てる

UpConvolution(DeConvolution)

  • 画像を大きくする
  • Poolingの逆
  • 入力画像をDilatedConvのように0埋めする

tags: Python, ML