ディープラーニングを数式で理解する

Convolutional Neural Network (CNN)の数理をまとめました。

本稿の目標は、Kerasの以下のメソッド

- `keras.layers.convolutional.Conv2D()`
- `model.add(Activation('relu'))`
- `model.add(Activation('softmax'))`
- `model.fit()`

が、どのようなアルゴリズムでデータを解析しているかを理解することです。

画像を入力する場合、実際の入力データは3階のテンソル（横ピクセルの値、縦ピクセルの値、RGBチャンネル）ですが、本稿では理解を簡単にするため、入力データを1階のテンソル（ベクトル）、つまりRチャンネルの横ピクセルのみとします。

執筆にあたり、「[高卒でもわかる機械学習](http://hokuts.com/category/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92/)」を参考にさせて頂きました。

## 公式

### 偏微分の連鎖則（Chain Rule）

$f$ が $x_1, x_2, \cdots x_n$ の関数であり、 $x_i$ が $u_1, u_2, \cdots u_n$ の関数であるとき、以下の公式が成立する。

```math
\frac{\partial f(x_1, x_2, \cdots x_n)}{\partial u_i} = \sum_k \frac{\partial x_k(u_1, u_2, \cdots u_n)}{\partial u_i}\frac{\partial f}{\partial x_k}
```

## 関数の定義

### 識別関数

- $l \  (0 \leq l \leq L)$:  
第 $l$ 層。入力層を第 $0$ 層、出力層を第 $L$ 層とする。
- $N^{(l)}$:  
第 $l$ 層のユニットの総数。画像データを入力する場合、縦（または横）のピクセル数が第 $0$ 層（入力層）のユニットの総数 $N^{(0)}$ となる。
- $x^{(l)}\_{i} \  (1 \leq i \leq N^{(l)})$ :  
第 $l$ 層 $i$ 番目のユニットの出力値。画像データを入力する場合、赤（または青、緑）のチャンネルにおける縦（または横）から $i$ 番目のピクセルの値（0~255）が第 $0$ 層 $i$ 番目のユニットの値 $x^{(0)}_{i}$ となる。
- $w^{(l)}_{ij} \  (1 \leq i \leq N^{(l)}, \ 1 \leq j \leq N^{(l-1)})$:  
第 $l$ 層 $i$ 番目のユニットに紐付いている第 $l-1$ 層 $j$番目の重み（「フィルタ」とも呼ばれる）。

上記のように変数を定義したとき、第 $l$ 層 $i$ 番目のユニットの識別関数 $u^{(l)}_i$は

```math
\begin{eqnarray}
u^{(l)}_i
&\equiv&
w^{(l)}_{i1}x^{(l-1)}_{1} + w^{(l)}_{i2}x^{(l-1)}_{2} + \dots + w^{(l)}_{in}x^{(l-1)}_{N^{(l-1)}} + b^{(l)}_i
\qquad
( b^{(l)}_i = \mathrm{Const})\\
&=&
\sum_{k=1}^{N^{(l-1)}} w^{(l)}_{ik}x^{(l-1)}_{k} + b^{(l)}_i \\
&\equiv&
\sum_k w^{(l)}_{ik}x^{(l-1)}_{k} + b^{(l)}_i
\tag{1.1}
\end{eqnarray}
```

と表すことができる。ここで、定数$b^{(l)}_i$ は「バイアス」と呼ばれる。このような演算を「畳み込み」と呼び、Kerasでは`keras.layers.convolutional.Conv2D()`で上記の計算を行っている。

### 活性化関数
識別関数 $u^{(l)}_i$を基に出力値 $x^{(l)}_i$ を決定する関数（活性化関数）$f$ を以下のように定義する。

```math
x^{(l)}_i \equiv f(u^{(l)}_i) \tag{1.2}
```

### 誤差関数（損失関数）

出力値 $x^{(L)}_i$ に対する教師データを$t_i$と したときの誤差関数$E$ を以下のように定義する。

```math
E(x^{(L)}_1, x^{(L)}_2, \cdots x^{(L)}_{N^{(L)}}) \equiv \frac{1}{2} \sum_k (x^{(L)}_k - t_k)^2 \tag{1.3}
```

## 勾配降下法による重みの更新式

学習率 $\rho \ (0 \leq \rho \leq 1)$ としたとき、勾配降下法による重みの更新式は

```math
w^{(l)}_{ij}
\leftarrow
w^{(l)}_{ij} - \rho \frac{\partial E}{\partial w^{(l)}_{ij}}
\tag{2.1}
```

と表すことができる。ここで $(1.1)$ より、

```math
\begin{eqnarray}
\frac{\partial E}{\partial w^{(l)}_{ij}}
&=&
\sum_{k} \frac{\partial u^{(l)}_{k}}{\partial w^{(l)}_{ij}}
\frac{\partial E}{\partial u^{(l)}_{k}} \\
&=&
\sum_{k} \frac{\partial}{\partial w^{(l)}_{ij}}
\left( \sum_{k'} w^{(l)}_{kk'}x^{(l-1)}_{k'} + b^{(l)}_k \right)
\frac{\partial E}{\partial u^{(l)}_{k}} \\
&=&
x^{(l-1)}_{j}
\frac{\partial E}{\partial u^{(l)}_{i}}
\tag{2.2}
\end{eqnarray}
```

```math
\begin{eqnarray}
\because k \neq i, k' \neq j
&\rightarrow&
\frac{\partial}{\partial w^{(l)}_{ij}}
\left( w^{(l)}_{kk'}x^{(l-1)}_{k'} \right)
= 0 \\
k = i, k' = j
&\rightarrow&
\frac{\partial}{\partial w^{(l)}_{ij}}
\left( w^{(l)}_{kk'} x^{(l-1)}_{k'} \right)
= x^{(l-1)}_{j}
\end{eqnarray}
```

ここで、誤差関数 $E$ に対する $u^{(l)}_{i}$ の偏微分を

```math
\delta^{(l)}_{i}
\equiv
\frac{\partial E}{\partial u^{(l)}_{i}}
\tag{2.3}
```

と定義すると、重みの更新式 $(2.1)$ は $(2.2),(2.3)$ より、

```math
w^{(l)}_{ij}
\leftarrow
w^{(l)}_{ij} - \rho
x^{(l-1)}_{j}
\delta^{(l)}_{i}
\tag{2.4}
```

と表すことができる。

## 誤差逆伝播法（バックプロパゲーション）

$(1.2), (2.3)$ より、

```math
\begin{eqnarray}
\delta^{(l)}_{i}
&=&
\frac{\partial E}{\partial u^{(l)}_{i}} \\
&=&
\sum_k \frac{\partial x^{(l)}_{k}}{\partial u^{(l)}_{i}}
\frac{\partial E}{\partial x^{(l)}_{k}} \\
&=&
\sum_k \frac{\partial f(u^{(l)}_k)}{\partial u^{(l)}_{i}}
\frac{\partial E} {\partial x^{(l)}_{k}} \\
&=&
f'(u^{(l)}_i) \frac{\partial E} {\partial x^{(l)}_{i}}
\tag{3.1}
\end{eqnarray}
```

```math
\begin{eqnarray}
\because
k = i
&\rightarrow&
\frac{\partial f(u^{(l)}_k)}{\partial u^{(l)}_{i}}
=
\frac{\partial f(u^{(l)}_i)}{\partial u^{(l)}_{i}}
=
f'(u^{(l)}_i) \\
k \neq i
&\rightarrow&
\frac{\partial f(u^{(l)}_k)}{\partial u^{(l)}_{i}}=0
\end{eqnarray}
```

$l = L$ のとき、$(1.3)$ より、

```math
\begin{eqnarray}
\frac{\partial E} {\partial x^{(l)}_{i}}
=
\frac{\partial E} {\partial x^{(L)}_{i}}
&=&
\frac{\partial} {\partial x^{(L)}_{i}}
\left(
\frac{1}{2} \sum_k (x^{(L)}_k - t_k)^2
\right) \\
&=&
\frac{\partial} {\partial x^{(L)}_{i}}
\left(
  \frac{1}{2} \sum_k (x^{(L)2}_k - 2t_kx^{(L)}_k + t_k^2)
\right) \\
&=&
x^{(L)}_i - t_i
\tag{3.2}
\end{eqnarray}
```

```math
\begin{eqnarray}
\because
k \neq i
\rightarrow
\frac{\partial} {\partial x^{(L)}_{i}}
  (x^{(L)2}_k - 2t_kx^{(L)}_k + t_k^2) = 0
\end{eqnarray}
```

$(3.1),(3.2)$ より、

```math
\begin{eqnarray}
\delta^{(l)}_{i}
=
f'(u^{(l)}_i) (x^{(L)}_i - t_i)
\tag{3.3}
\end{eqnarray}
```

$l \neq L$ のとき、$(1.1),(2.3)$ より、

```math
\begin{eqnarray}
\frac{\partial E} {\partial x^{(l)}_{i}}
&=&
\sum_k \frac{\partial u^{(l+1)}_k}{\partial x^{(l)}_i}
\frac{\partial E}{\partial u^{(l+1)}_k} \\
&=&
\sum_k \frac{\partial}{\partial x^{(l)}_i}
\left(
  \sum_{k'} w^{(l+1)}_{kk'} x^{(l)}_{k'} + b^{(l+1)}_{k}
\right)
\delta^{(l+1)}_{k} \\
&=&
\sum_k w^{(l+1)}_{ki}
\delta^{(l+1)}_{k}
\tag{3.4}
\end{eqnarray}
```

```math
\begin{eqnarray}
\because
k' \neq i
\rightarrow
\frac{\partial} {\partial x^{(l)}_{i}}
(w^{(l+1)}_{kk'} x^{(l)}_{k'} ) = 0
\end{eqnarray}
```

よって $(3.1),(3.4)$ より、

```math
\delta^{(l)}_i
=
f'(u^{(l)}_i) \sum_k w^{(l+1)}_{ki} \delta^{(l+1)}_{k}
\tag{3.5}
```

$(2.4),(3.3),(3.5)$ より、重みの更新式は

```math
w^{(l)}_{ij}
\leftarrow
w^{(l)}_{ij} - \rho
x^{(l-1)}_{j}
\delta^{(l)}_{i}
```

```math
\delta^{(l)}_i = \left\{ \begin{array}{ll}
    f'(u^{(l)}_i) (x^{(l)}_i - t_i) & (l=L) \\
    f'(u^{(l)}_i) \sum_k w^{(l+1)}_{ki} \delta^{(l+1)}_{k} & (l \neq L)
  \end{array} \right.
\tag{3.6}
```

となる。

Kerasでは`model.fit()`で上記の計算を行っている。

## 活性化関数
### ReLU（Rectified Linear Unit）

活性化関数としてReLU（Rectified Linear Unit）を採用した場合、 $f(u^{(l)}_i)$ は以下のように表すことができる。

```math
f(u^{(l)}_i)
\equiv
\mathrm{max}(0,u^{(l)}_i)
=
\left\{ \begin{array}{ll}
    u^{(l)}_i & (u^{(l)}_i \geq 0) \\
    0 & (u^{(l)}_i < 0)
\end{array} \right.
```

```math
\therefore
\frac{\partial f(u^{l}_i)}{\partial u_i}
=
f'(u^{(l)}_i)
=
\left\{ \begin{array}{ll}
    1 & (u^{(l)}_i \geq 0) \\
    0 & (u^{(l)}_i < 0)
\end{array} \right.
\tag{4.1}
```

Kerasでは`model.add(Activation('relu'))`で上記の計算を行っている。

### Softmax

活性化関数としてSoftmaxを採用した場合、 $f(u^{(l)}_i)$ は以下のように表すことができる。

```math
f(u^{(l)}_i)
\equiv
\frac{\exp(u^{(l)}_i)}{\sum_{k} \exp(u^{(l)}_k)}
```

```math
\begin{eqnarray}
\therefore
\frac{\partial f(u^{l}_i)}{\partial u_i}
&=&
f'(u^{(l)}_i) \\
&=&
\frac{
\frac{\partial \exp(u^{(l)}_i)}{\partial u^{(l)}_i} \sum_{k} \exp(u^{(l)}_k) - \exp(u^{(l)}_i) \frac{\partial}{\partial u^{(l)}_i} \sum_{k} \exp(u^{(l)}_k)
}{\left( \sum_{k} \exp(u^{(l)}_k) \right)^2} \\
&=&
\frac{
\exp(u^{(l)}_i) \sum_{k} \exp(u^{(l)}_k) - \exp(u^{(l)}_i)^2}
{\left( \sum_{k} \exp(u^{(l)}_k) \right)^2} \\
&=&
f(u^{(l)}_i) \left( 1 - f(u^{(l)}_i) \right)
\tag{4.2}
\end{eqnarray}
```

Kerasでは`model.add(Activation('softmax'))`で上記の計算を行っている。

## テンソルでさらに理解を深めたいあなたに

[Introduction to Convolution all Neural Networks - Jianxin Wu](https://cs.nju.edu.cn/wujx/paper/CNN.pdf#page11)が参考になりそうです。