深層学習 Day 1 - Section 5 誤差逆伝播法 のまとめ

この記事は個人的なお勉強用のメモです。

# このお勉強の位置

深層学習 Day 1

Section 0 ニューラルネットワークの全体像
Section 1 入力層～中間層
Section 2 活性化関数
Section 3 出力層
Section 4 勾配降下法
**Section 5 誤差逆伝播法**　←　これ

# 講義

## 誤差逆伝播法

それぞれの処理の場所で微分する。
微分した値を前の層で使う。

1. 誤差関数
2. 出力層での活性化関数
3. 出力層での重み計算
4. 中間層での活性化関数（1層ずつ）
5. 中間層での重み計算（1層ずつ）

微分した値を連鎖率で掛け合わせる。

#### 誤差関数

入力1：出力層からの値 y
入力2：正解値 d
出力：誤差 E

数式 $\frac{\partial E}{\partial y}$

#### 出力層の活性化関数

入力1：総入力 u
出力；活性化関数処理後の値 y

数式 $\frac{\partial y}{\partial u}$

#### 重みの計算

入力1：入力データ値 x
入力2：重みの値 w
出力：上記の掛け算の総和 u

数式 $\frac{\partial u}{\partial w}$


#### 誤差 E を重み w で偏微分した微分値

最終的に求めた微分値

```math
\begin{align}
\frac{\partial E}{\partial w} 
= \frac{\partial E}{\partial y}\frac{\partial y}{\partial u}\frac{\partial u}{\partial w}
\end{align}
```

上記のように間接的に微分値を計算できる。
それぞれの微分値は人間が事前に計算しておく。

# 実装演習

1_3_stochastic_gradient_descent.ipynb

与えられたソースは、
　順伝播：ReLU関数
　逆伝播：シグモイド関数の導関数
になっていて関数が不統一だったので、順伝播をシグモイド関数に変更して実行した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/ada5ce80-7505-676c-8ffe-29d219e68807.png)

学習が進むにつれて、急速に誤差が小さくなっていく様子が確認できる。

# 確認テスト

### 既に行った計算結果を保持しているソースコードの位置

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/2c3c6de1-0846-1d8c-387b-81cbb065a833.png)

z1：前の層の出力値
delta2：誤差関数 MSEを微分した値を保持
grad['W2']：以下の3つの値を掛け算した値を保持
1. delta2の値
2. 恒等関数を微分した値 1（y = u2より）
3. u2をW2で微分した値 z1（u2=W2 z1 + b2より）

（保持とはいえ、1回の重み更新で一時的に保持するだけ。次のエポックでの重み更新時はすべて再計算する。）

### 2つの空欄に該当するソースコードの位置

数式 $\frac{\partial E}{\partial y}\frac{\partial y}{\partial u}$ のソースコード
$\frac{\partial y}{\partial u}$ は 1 なので、上記の数式専用のソースコードは見当たらないが
強いて言えば以下のソースコード。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/277e439e-b40b-8416-be92-c04e32c786f4.png)

数式 $\frac{\partial E}{\partial y}\frac{\partial y}{\partial u}\frac{\partial u}{\partial w_{ji}^2}$ のソースコード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/150f349f-8fda-40e4-c301-5bb28a2cba3d.png)

模範解答によると、上に貼り付けた自分の2つの解答はどちらも不正解とのことだが、
本当だろうか。
forward関数を読むと、以下のように中間層が2層になっている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/dbc95f57-ab55-1133-96c0-ae1dd55136be.png)


この問は $w_{ji}^{(2)}$ つまり2層目の重みの傾きを求めるソースコードを探す。
しかし、なぜか模範解答は1層目の重みの傾きを求めるソースコードを指している。
もし1層名の重みの傾きを求めるのであれば、数式は以下であるはず。

```math
\frac{\partial E}{\partial y}
\frac{\partial y}{\partial u2}
\frac{\partial u2}{\partial z1}
\frac{\partial z1}{\partial u1}
\frac{\partial u1}{\partial w_{ji}^{(1)}}
```

# 修了テスト～練習問題～

### 問題4（シグモイド関数の微分）

これは暗記するのが一番早い。

```math
f'(z)=f(z)(1-f(z))
```

計算でも求められる。

```math
f(z)=\frac{1}{1+e^{-z}}\\
```

$1+e^{-z} = t$ とおくと、$f(z) = \frac{1}{t} \Rightarrow \frac{\partial f(z)}{\partial t}=-t^{-2}=-\frac{1}{t^2}$
$e^{-z} = s$ とおくと、$1+s=t \Rightarrow \frac{\partial t}{\partial s}=1$
$-z=u$ とおくと、$e^u=s \Rightarrow \frac{\partial s}{\partial u}=e^u$
また、$\frac{\partial u}{\partial z}=-1$

```math
\begin{align}
\frac{\partial f(z)}{\partial z}
&=
\frac{\partial f(z)}{\partial t}
\frac{\partial t}{\partial s}
\frac{\partial s}{\partial u}
\frac{\partial u}{\partial z}
\\
&=
\biggl(-\frac{1}{t^2}\biggr)
\times
1
\times
e^u
\times
(-1)
\\
&=
\frac{e^{-z}}{(1+e^{-z})^2}
\\
&=
\frac{1}{1+e^{-z}}
\frac{1+e^{-z}-1}{1+e^{-z}}
\\
&=
\frac{1}{1+e^{-z}}
\Biggl(
1-
\frac{1}{1+e^{-z}}
\Biggr)
\\
&=
f(z)(1-f(z))
\end{align}
```

### 問題5（計算グラフでの逆伝播）

右の赤線の値は $1$ かつ中央下の黒線は $20$ であることから、中央の赤線は $1 \times 20=20$ 
中央の赤線は $20$ かつ左上の黒線は $3$ であることから、左の赤線は $20 \times 3=60$

参考
赤本の 5.3.2 乗算ノードの逆伝播