深層学習-NN

#深層学習-NN
- 入力層〜中間層
- 活性化関数
- 出力層
- 勾配降下法
- 誤差逆伝播法
- 確認テスト


##深層学習
深層学習の目的は、明示的なプログラムの代わりに、多数の中間層を持つニューラルネットワークを用いて、入力層から目的とする出力値に変換する数学モデルを構築することである。そのために重みとバイアスの最適化が最終目標となる。

##入力層〜中間層
入力層には、入力値が存在する。入力値はxで表し、xは何かを判断するときの要素となる。
例えば、犬、猫、ネズミの分類問題の時。
xには、毛の色、鼻の高さ、体の大きさ、目の色などの要素が入力層に与えられる。

そして、そのxに重み（どこの要素のデータが結果にどれほど影響しているかを数値にしたもの）をつけて、中間層に渡される。その時に、バイアス（切片のようなもの）も一緒に渡される。

####入力層の総入力

```math 
u = w_1x_1 + w_2x_2 + ... + w_ix_i + b
```

##活性化関数
ニューラルネットワークにおいて、次の層への出力の大きさを決める非線型の関数。
入力値によって、次の層への信号のON/OFFや強弱を定める働きを持つ。

####中間層への活性化関数
- ステップ関数
- シグモイド（ロジスティック）関数
- ReLU関数

###ステップ関数
出力は常に１か０。パーセプトロン（ニューラルネットワークの前身）で利用された関数。
デメリットとして、線形分離可能なものしか学習できない。


```math 
\begin{align} 
f(x) &= 1 (x≧0)\\
&=0 (x<0)
\end{align}
```
```python 
def step_function(x)
    if x > 0:
        return 1
    else:
        return 0
```


###シグモイド（ロジスティック）関数
0~1を緩やかに変化する関数で、信号の強弱を伝えられるようになり、予想ニューラルネットワーク普及のきっかけとなった。
課題は、大きな値では出力の変化が微小なため、勾配消失問題を引き起こすことがある。

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

```python 
def sigmoid(x):
    return 1/(1 + np.exp(-x))
```

###ReLU関数
今最も使われている活性化関数。
勾配消失問題の回避とスパース化に貢献することで良い結果をもたらしている。

```math
\begin{align} 
f(x) &= x (x>0)\\
&=0 (x≦0)
\end{align}
```


```python
def relu(x): 
    return np.maximum(0, x)
```

##出力層
出力層では、中間層から出された出力と訓練データの誤差を導き出し、より正確な値を出力するための計算が行われる。

###誤差関数

```math 
E_n(w) = \frac{1}{2}∑(y_j - d_j)^2 = \frac{1}{2}||(y - d)||^2
```
誤差関数では、回帰問題に対しては二乗誤差関数、2値分類・多クラス分類に関しては、交差エントロピーを用いる。

####二乗誤差関数

```math 
E_n(w) = \frac{1}{2}∑(y_i - d_i)^2
```

```python 
def mean_squared_error(d, y):
    return np.mean(np.aquared(d, y)) / 2
```
####交差エントロピー

```math 
E_n(w) = -∑d_ilogy_i
```

```ptython 
def cross_entropy_error(d, y):
    if y.ndim == 1:
        d = d.reshape(1, d.size)
        y = y.reshape(1, y.size)

    #教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
    if d.size == y.size:
        d = d.argmax(axis = 1)
        batch_size = y.shape[0]

    return np.sum(np.log(y[np.arange(batch_size), d] + 1e - 7)) / batch_size
```
###活性化関数
中間層と出力層の活性化関数は目的が違う。
出力層における活性化関数は、信号の大きさ（比率）はそのままに変換する。一方、中間層ではしきい値の前後で信号の強弱を調整する。
分類問題の場合、出力値の出力は０〜１の範囲に限定し、総和を１とする必要がある。

回帰問題では、項等写像。
２値分類問題では、シグモイド関数。
多クラス分類問題では、ソフトマックス関数を用いる。

####項等写像

```math 
f(u) = u
```
####シグモイド関数

```math 
f(u) = \frac{1}{1 + e^{-u}}
```
####ソフトマックス関数

```math 
f(i, u) = \frac{e^{ui}}{∑e^{uk}}
```

##勾配降下法
学習を通して、誤差を最小にするネットワークを作成することを目的とする。
誤差E(w)を最小とするパラメータwを発見し、勾配降下法を利用してパラメータを最適化する。
役割としては、誤差関数の値をより小さくする方向に重みおよびバイアスを更新し、次の周（エボック）に反映させることである。

####計算式

```math 
w^{T + 1} = w^t - ξΔE　\\
ΔE = \frac{∂E}{∂W} = [\frac{∂E}{∂W_1}...\frac{∂E}{∂W_M}]
```

###学習率ξ
上記の式で現れるξは学習率と呼ばれる。
この値が大きすぎた場合は最小値にいつまでも辿り着けず発散してしまう。
一方、小さすぎる場合、発散することはないが収束するまでに時間がかかってしまう。
学習率の決定、収束性向上のためのアルゴリズムについては複数の論文が公開されている。

<b>アルゴリズム</b>
- Momentum
- AdaGrad
- Adadelta
- Adam   ←よく使う
###確率的勾配降下法
勾配降下法では、全サンプルの平均誤差を取るのに対し、確率的勾配降下法はランダムに抽出したサンプルの誤差を取る。
利点は主に3点あって、
- データが助長な場合の計算コストの削減
- 望まない局所極小解に収束するリスクの軽減
- オンライン学習ができる　　→
学習データが入ってくるたびに都度パラメータを更新し、学習を進めていく方法である。
通常行われるバッチ学習は、一度に全ての学習データを使ってパラメータ更新を行う。
そのため、オンライン学習はコストの削減をすることができる。

```math 
W^{t+1} = W^t - ξΔE_n
```

###ミニバッチ勾配降下法
オンライン学習の特徴をうまくバッチさせるようにしたのがミニバッチ勾配降下法である。
利点は、確率的勾配降下法のメリットを損なわず、計算機の計算資源を有効活用できる。
つまり、CPUを利用したスレッド並列化やGPUを利用したSIMD並列化をすることができる。
これらはCPUやGPUなどで並列処理を行うための設計様式の一つで、一つの命令を同時に複数のデータに適用し、並列に処理する方式である。
スレッド並列化はCPUにおける並列化を指し、SIMD並列化はスーパーコンピュータやGPUなどでの並列化を指す。

 ```math 
W^{t+1} = W^t - ξΔE_t \\
\\
E_t = \frac{1}{N_t}∑E_n   ,  N_t = |D_t|
```
E_tは、ランダムに分割したデータの集合（ミニバッチ）D_tに属するサンプルの平均誤差を表す。

###ΔEの計算

```math 
ΔE = \frac{∂E}{∂W} = [\frac{∂E}{∂W_1}...\frac{∂E}{∂W_M}]
```
####数値微分
プログラムで微小な数値を生成し、擬似的に微分を計算する一般的な手法

```math 
\frac{∂E}{∂W_M}　≈　\frac{E(W_m + h) - E(W_m - h)}{2h}
```
#####デメリット
- 計算量が大きくなってしまう
- 各パラメータw_mそれぞれについてE(W_m+h)やE(W_m-h)を計算するために順伝播の計算を繰り返し行う必要があり負荷が大きい。

→<b>誤差逆伝播法を使う！</b>

##誤差逆伝播法
最低限の計算で各パラメータでの微分値を解析的に計算する手法。
算出された誤差を出力側から順に微分し、前の層前の層へと伝播する。
計算結果（＝誤差）から微分を逆算することで不要な再起的計算を避けて微分を計算することができる。

```math 
E(y) = \frac{1}{2}∑(y_j - d_j)^2 = \frac{1}{2}||y - d||^2 : 誤差関数＝二乗誤差関数\\
\\
y = u^{(2)} : 出力層の活性化関数＝恒等写像\\
\\
u^{(l)} = W^{(l)}Z^{(l - 1)} + b^{(l)} : 総入力の計算
```
パラメータを求めるには、

```math 
\frac{∂E}{∂W^{(2)}_{ji}} = \frac{∂E}{∂y}\frac{∂y}{∂u}\frac{∂u}{∂W^{(2)}_{ji}}\\
\\
\frac{∂E(y)}{∂y} = \frac{∂}{∂y}\frac{1}{2}||y - d||^2 = y - d\\
\\
\frac{∂y(u)}{∂u} = \frac{∂u}{∂u} = 1
```
#####コード
```math 
\frac{∂E}{∂y}
```

```python 
delta2 = function.d_mean_squared_error(d, y)
```

```math 
\frac{∂E}{∂y}\frac{∂y}{∂u}
```

```python 
delta1 = np.dot(delta2, w2.T) * functions.d_sigmoid(z1)
```

```math 
\frac{∂E}{∂y}\frac{∂y}{∂u}\frac{∂u}{∂W^{(2)}_{ji}}
```

```python
grad['W'] = np.dot(x.T, delta1)
```

##確認テスト
###Q1
ディープラーニングは結局何をやろうとしているのか？
また、次の中のどの値の最適化が最終目的か？
（入力値、出力値、重み、バイアス、総入力、中間層入力、学習率）

・明示的なプログラムの代わりに、多数の中間層を持つニューラルネットワークを用いて、入力層から目的とする出力値に変換する数学モデルを構築することである。
・重みとバイアス
###Q2
次のネットワークを紙にかけ。
入力層：２ノード１層
中間層：３ノード２層
出力層：１ノード１層
![IMG-5967.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906331/4dc15df3-5439-f970-5a47-25d5ff80e95b.jpeg)


###Q3
入力層から中間層の図に動物分類の実例を入れてみよ。
![IMG-5968.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906331/fcd2a128-276c-c469-ff02-749251bea0d6.jpeg)


###Q4

```math 
\begin{align}
u &= w_1x_1 + w_2x_2 + w_3x_3 + w_4x_4 + b\\
&=Wx + b ..(1.2)
\end{align}
```
この数式をPythonで書け。

```python 
u1 = np.dot(x, W1) + b1
```

###Q5
中間層の出力を定義しているソースを書き出せ。

```python 
z2 = functions.relu(u2)
```
###Q6
線形と非線形の違いを図に書いて簡易に説明せよ。
![IMG-5969.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906331/9685d438-7435-6232-ead6-34e26d4bd0cb.jpeg)

###Q7
　
```math 
z = f(u) .. (1.5)
```
この数式をPythonで書け。

```python 
z1 = funcitons.sigmoid(u)
```
###Q8
誤差関数ではなぜ二乗するのか述べよ。
また、誤差関数で1/2をすることにはどのような意味が込められているか述べよ。

・訓練データと出力値の差がたとえマイナスになったとしても正の方向に行くようにするためである。
・誤差逆伝播を行う時に計算が楽になるからと言う意味合いがある。
###Q9
![スクリーンショット 2021-01-04 18.19.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906331/4533d7a5-7607-f0c3-a9db-b3ba4d5295c5.png)
①〜③の数式に該当するソースコードを示し、１行ずつ処理の説明をせよ。
①出力値
②np.exp(x)
③np.sum(np.exp(x))
###Q10
![スクリーンショット 2021-01-04 18.26.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906331/7f292b28-1422-3f0f-66ce-1f47421f8b70.png)
①〜②の数式に該当するソースコードを示し、１行ずつ処理の説明をせよ。
①出力値
②-np.sum(np.log(y[np.arange(batch_size), d] + 1e-7))
###Q11

```math 
w^{(t+1)} = w^{(t)} - ξΔE
```
該当するソースコードは？

```python 
network[key] -= learning_rate * grad[key]
```
###Q12
オンライン学習とは何か？

その時々で学習させること。
###Q13
```math 
w^{(t+1)} = w^{(t)} - ξΔE
```
この数式の意味を図に書いて説明せよ。
![IMG-5970.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906331/8a177a7d-c58f-8879-4c69-a23c8a8a7e68.jpeg)

###Q14

```math 
\frac{∂E}{∂y}\frac{∂y}{∂u}　
\frac{∂E}{∂y}\frac{∂y}{∂u}\frac{∂u}{∂W^{(2)}_{ji}}
```
のコードをpythonで書け。


```python 
delta1 = np.dot(delta2, w2.T) * functions.d_sigmoid(z1)
```


```python
grad['W'] = np.dot(x.T, delta1)
```