[Deep Learning解析]　第一回　イキナリCNN

学位研究はLSTM＋CNNを使った3次元点群データでの物体認識でしたので、自分は深層学習にはかなり深く理解できたと思ってましたが、仕事やってきたこの一年では、いろいろ現実の問題にDLを適用してきて、以前当たり前として受けてた知識にもっと深く理解できました。最近人に教えているうちに気づいた、以前学生時代で無視してしまったところを[Deep Learning解析]というシリーズで記事していきます。
*WARNING*: **これはNeural Networkの入門ではありません。深層学習をある程度知っているという前提です。And i'm sure my Japanese make less sense sometime, bear me**
>you can find ipynb [here](https://colab.research.google.com/drive/1s_B7sBN5J40pcDSB3fLVmWtupljP77T0), and push "PLAYGROUND" to play with ![here.JPG](https://qiita-image-store.s3.amazonaws.com/0/148692/49c37e79-b17e-752f-9949-ed30bf1dab4f.jpeg)


##　背景 
今度の話は以下のような6層のConv2D+DenseのNetworkを対照します。使うデータセットはKerasが準備したCIFAR10。一般的に深層学習ではデータのやり取りが一番大事ですが、今度の話外とします。

```python
model.add(Conv2D(filters=32, (3, 3), padding='same', input_shape=(32,32,3)))
model.add(Activation('relu'))
model.add(Conv2D(filters=96, kernel_size=(3,3), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Conv2D(filters=192, kernel_size=(3,3)))
model.add(Activation('relu'))
model.add(Conv2D(filters=192, kernel_size=(3,3), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dense(nb_classes, activation="softmax"))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
```
このモデル（モデル　→　コンパイルできた計算グラフのこと）ではbatch_size=64でAdamを使って50epoch学習すると、テストデータでの認識率が78％になります。

## Feed-forwardの視点
CNNから学習、MAX Pooling、Dropoutなど部分を抜けましょう。それで残りは単純なLinear Systemと思いましょう。たぶん、「？？どいうこと？？」って考えている人もおるでしょう、今から説明します。
#### Linear System Equation
以下の式が前提としましょう
$$
\begin{align}
ax+by+cz=d \\\\
ex+fy=g \\\\
hx-iy+jz=k
\end{align}
$$
それを行列で書き直ししましょう
$$
\left(\begin{array}{cc} 
a & b & c\\\\
e & f & 0\\\\
h & i & j
\end{array}\right)
\left(\begin{array}{cc} 
x \\\\
y \\\\
z
\end{array}\right)=
\left(\begin{array}{cc} 
d \\\\
g \\\\
k
\end{array}\right)
$$ 

それをこんな形にできます
$$
AX =B
$$
ここで、$A$がCNNの入力画像、Bがその画像のクラスベクトルであると設定しましょう、$X$はフィルタ（またカーネル、特徴フィルタなども言う）です。
$$
\begin{array}{cc}
AX =B\\\\
↓\\\\
X  = A^{-1}B
\end{array}
$$
問題が複雑ではない（バイナリクラスである、また$A$が大きすぎない）場合は、フィルタ$X$がそのままで計算できます。だが、実問題はそう簡単ではありません。そういうわけで、以前（DL前）はSVD(Singular-value decomposition)ど前処理して、edge kernelなどう人間の経験に依存したフィルタを使って$A$を圧縮したりのことをやてた。しかし、$A$が圧縮できても、$B$次元が大きいだと、$X$の次元も増やすことになる、$X$の内容は$B$によっても変わる。だからいくつにする、どんな形にするというのは人間が決めることになって非常に難しいです。
前提したモデルで話しすると、こんな式が4つ繋げっています。$X^1$が$(32,32,3)$、$X^2$が$(15, 15, 96)$、$X^3$が$(13, 13, 192)$、$X^4$が$(6, 6, 192)$である、それに対してフィルタは32,96,192,192であります。
#### Bを見てみましょう

とりあえず、認識率が78％になったモデルを各Convolutional Layerごとに分けましょう。

```python
from keras.models import Model
conv2d_1 = Model(inputs=model.input, outputs=model.get_layer("conv2d_1").output)
conv2d_2 = Model(inputs=model.input, outputs=model.get_layer("conv2d_2").output)
conv2d_3 = Model(inputs=model.input, outputs=model.get_layer("conv2d_3").output)
conv2d_4 = Model(inputs=model.input, outputs=model.get_layer("conv2d_4").output)
```
それぞれの構造はこのようになります：

```bash
>>>conv2d_1.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1_input (InputLayer)  (None, 32, 32, 3)         0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 32, 32, 32)        896       
=================================================================
Total params: 896
Trainable params: 896
Non-trainable params: 0
_________________________________________________________________
```

```bash
>>>conv2d_2.summary()
_________________________________________________________________
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1_input (InputLayer)  (None, 32, 32, 3)         0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 32, 32, 32)        896       
_________________________________________________________________
activation_1 (Activation)    (None, 32, 32, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 15, 15, 96)        27744     
=================================================================
Total params: 28,640
Trainable params: 28,640
Non-trainable params: 0
_________________________________________________________________
```

*ここでは２層目まで表示します。
Step 1
-------------------
$A^1$にあたる画像
![ダウンロード.png](https://qiita-image-store.s3.amazonaws.com/0/148692/8d2d34ae-4a0a-1296-d9fc-3539fa645f73.png)
$X^1_{0:32}$にあたる1層目のフィルタ(一部)
![filter1.png](https://qiita-image-store.s3.amazonaws.com/0/148692/97cdded8-aabf-e7e6-adad-4a1f68b62777.png)
それの結果$B^1_{0:96}$は(一部)
![result1.png](https://qiita-image-store.s3.amazonaws.com/0/148692/c1f318c7-7398-1f78-3ac2-2054770d1faa.png)

この結果$B^1$はCNNで1層目の特徴マップとも言う。

Step 2
-------------------
$B^1$と$X^2$の計算をする

$X^2_{0:96}$にあたる2層目のフィルタ(一部)
![filter2.png](https://qiita-image-store.s3.amazonaws.com/0/148692/a5627a51-088e-765d-c23c-c258d15608f3.png)
それの結果$B^2_{0:96}$は(一部)
![result2.png](https://qiita-image-store.s3.amazonaws.com/0/148692/0c372981-9b93-1128-d859-629140142d68.png)

Step 3
-------------------
$B^2$と$X^3$の計算をする
$X^3_{0:192}$にあたる3層目のフィルタ(一部)
![filter3.png](https://qiita-image-store.s3.amazonaws.com/0/148692/6a21a473-8779-ee65-db80-e84bb69e2da4.png)
それの結果$B^3_{0:192}$は(一部)
![result3.png](https://qiita-image-store.s3.amazonaws.com/0/148692/217af6fa-d951-a32a-ea0a-138ba6db9854.png)

Step 4
-------------------
$B^3$と$X^4$の計算をする
$X^4_{0:192}$にあたる4層目のフィルタ(一部)
![filter4.png](https://qiita-image-store.s3.amazonaws.com/0/148692/fc5ffc39-2301-15ff-9b98-c98bc2ab2a8f.png)
それの結果$B^4_{0:192}$は(一部)
![result4.png](https://qiita-image-store.s3.amazonaws.com/0/148692/1a322b95-4c93-ab4a-b448-54300d281f7f.png)


$B^i$は学習手法で自動で最適できたフィルタとの結果ですが、$B^1$と$B^2$の結果を見て、$X^1$と$X^2$がどんなフィルタか、いえます、たとえば、$B^1$はエッジ検出した結果なように見えます、ただ$B^4$に見ると人間で説明し難いいです。
CNNは最適化の方法で、最後の$B$に合うような$X$を計算するということ。

最後に
----
始めって日本語で記事してて、書いている途中で、自分が何書きたいかも分からなくなって、もう良いわという気分でした（笑）。
日本語の勉強にも繋がるそうです。