【入門者向け解説】畳み込み処理入門(TensorFlowで説明)

#入門者向けに「畳み込み」処理について解説
TensorFlowエキスパート向けチュートリアル[Deep MNIST for Experts](https://www.tensorflow.org/get_started/mnist/pros)を実行して、まずわかりにくいのが「畳み込み」処理でした。文系卒からすると一般用語でもないですし、少し時間がかかりましたが、分かれば簡単です。基本的には**四則演算ができれば理解できます**。
[【入門者向け解説】TensorFlowチュートリアルDeep MNIST](http://qiita.com/FukuharaYohei/items/0aef74a0411273705512)記事で、畳み込みニューラルネットワークの処理を解説していますので参考にしてください。
また、[「【入門者向け解説】プーリング処理入門(TensorFlowで説明)」](http://qiita.com/FukuharaYohei/items/73cce8f5707a353e3c3a)の記事でプーリングについても解説しています。
<sup>※TensorBoardで出力した画像を参考に載せました(2017/7/27)</sup>

#概説
###概要
[「【入門者向け解説】TensorFlowチュートリアルDeep MNIST」](http://qiita.com/FukuharaYohei/items/0aef74a0411273705512)の記事で解説しましたが、「畳み込み」処理では画像の特徴を見つけます。画像だけでなく音声やデータでもいいですのですが、画像の方が視覚的でわかりやすいので、画像を使って解説します。
![10.Overview.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/45c8cad3-a42f-29f6-4543-e3487da28df1.jpeg)
###畳み込み処理の入出力
畳み込み処理は特徴を出すためにフィルターをかけます。画像をインプットとしてフィルターを使って、フィルターの枚数分の画像を出力します。MNISTデータを使った場合は、下記のとおりです。
![Convolve01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/e79ce0d5-3ebe-f1d2-0b14-b9756ec6e188.jpeg)

TensorBoardに出した実際の畳み込み処理入出力画像を整理したらこんな感じでした。人間にはイマイチ理解できませんが、雰囲気はわかると思います(画像処理のプロはわかるかも・・・)。
![Convolve06_images01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/e945041b-a78c-67b2-29db-c1ae222e3c23.jpeg)


###フィルター例
フィルターに関しては画像に対する編集処理ということで、[「画像処理フィルタ一覧、比較」](http://imagingsolution.net/imaging/filter-algorithm/)を参照ください。実際にどんな種類のフィルターを適用すると画像がどう変わるかがわかりやすいです。
#具体的な処理
四則演算のみを使います。
TensorFlowエキスパート向けチュートリアル[Deep MNIST for Experts](https://www.tensorflow.org/get_started/mnist/pros)の以下のプログラム箇所が畳み込み処理です。第1層でも第2層でも同じで、TensorFlowのAPIを使うことでこの程度で実装することができます。

```py3
# 畳み込み処理
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
```

###画像例
入力画像例として縦4×横4×1色(黒のみ)の斜め棒画像を使います。斜め棒を1と0で表現しました。
![Convolve02.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/ac128898-7297-33a0-dc46-d24c92a9cd5f.jpeg)

###ゼロパディング
padding='SAME'と書かれているオプションはゼロパディングといい、周囲を0で埋めます。なんでこんなことをしているかというと、入力画像と出力画像のTensor(テンソル)を同一にしたいからです。
![Convolve03.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/9dbd9fff-c26f-5d29-5107-cee29b1ae1f8.jpeg)

###フィルターの使用
斜め棒のフィルターを例示すると下図のとおりです。斜め棒に対して同じ角度の斜め棒で特徴を出します。
![Convolve04_filter.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/a18a2c18-e80f-f4bc-674f-6c666ef16320.jpeg)


TensorFlowエキスパート向けチュートリアル[Deep MNIST for Experts](https://www.tensorflow.org/get_started/mnist/pros)の以下の箇所がフィルター生成時のコードです(ここでは5(縦)×5(横)×1(色)×32(種類))。

```py3
W_conv1 = weight_variable([5, 5, 1, 32])
```

weight_variableの関数で、初期値を標準偏差0.1の正規分布乱数で生成しています。あとは学習しているうちに、最適なフィルターの値を探索してくれます。tf.truncated_normalの関数は[リンク先](http://qiita.com/FukuharaYohei/items/f9bb9a0afd47be9ecef8#truncated_normal)を参照ください。

```py3
# 重み付け値
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)    #標準偏差0.1の正規分布乱数
    return tf.Variable(initial)
```

###掛け算と足し算
下図の形で掛け算と足し算をします。
![Convolve05_step01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/c1fc38dd-ee70-59cf-6a32-88cf8667c7cb.jpeg)
あとは、ひとつずつずらして計算を繰り返します。ゼロパディングをしているため、畳み込み処理結果の画像は同じ縦4×横4となります。下の絵は2つ目(1番上の左から2つ目)の畳み込み処理をしている概要図です。
![Convolve05_step02_new.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/cfb2c902-ae26-fc82-1181-1f056015f6ac.jpeg)

最終的に計算をし終わると下図に結果が出てきます。斜め棒に対して斜め棒フィルターを適用したので、同じ様な形となっています。
![Convolve05_step03_new.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/9ea48a54-f1f8-4447-2040-77adf30ef29c.jpeg)
※値が間違っていたので修正しました(2018/4/2)

###参考
[「高卒でもわかる機械学習 (7) 畳み込みニューラルネット その1」](http://hokuts.com/2016/12/13/cnn1/)や[TensorFlow Tutorialの数学的背景 − Deep MNIST for Experts（その1）](http://enakai00.hatenablog.com/entry/2016/02/27/111116)の記事では、非常に詳しくまとまっています。

#畳み込みの数学での意味
畳み込みは数学で出てくる合成積のことです。[Wikipedia](https://ja.wikipedia.org/wiki/%E7%95%B3%E3%81%BF%E8%BE%BC%E3%81%BF)に詳しく載っています。筆者は、教材[「スバラシク実力がつくと評判の**統計学**キャンパス・ゼミ」](http://amzn.to/2oOPJM2)を使って勉強しました。
数学勉強に関しては[「文系卒社会人が統計・機械学習を理解するための数学勉強方法」](http://qiita.com/FukuharaYohei/items/0a66c37091dc27c71fe6)の記事を参照ください。