ラビットチャレンジ 深層学習day2

##本記事について
ラビットチャレンジの深層学習day2のレポートです。
ラビットチャレンジはStudy-AI開講のE資格受験資格を得られる認定プログラムとなっています。

## 深層モデルのための学習テクニック
### 勾配消失問題

#### 誤差逆伝播法
- 特徴
  - 計算結果（=誤差）から微分を逆算することで、不要な再帰的計算を避けて微分を算出できる
 
- 確認テスト
  - 連鎖律の原理を使い、$ \frac{dz}{dx} $を求めよ。
$$ z = t^2 $$
$$ t = x + y $$

- 確認テスト解答

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/dce53a54-7004-baf0-b55f-404ef46a7a85.png)

#### 勾配消失問題
- 課題
  - 誤差逆伝播法が下位層に進んでいくに連れて、勾配がどんどん緩やかになっていく。
  - そのため、勾配降下法による更新では下位層のパラメータはほとんど変わらず、訓練は最適値に収束しなくなる。

- なぜ発生するのか
  - 連鎖率を用いて勾配を求める際、各関数の微分値は0から1の値を取るため勾配が小さくなる。

- 確認テスト
  - シグモイド関数を微分した時、入力値が0の時に最大値をとる。その値はいくつか。

- 確認テスト解答

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/ae137e7a-0f95-9572-0bae-7fe23685ece3.png)

### 勾配消失の解決方
#### 活性化関数の選択 → ReLU関数 
- 数式

```math
\begin{equation} x(x)=\begin{cases} x & \text{($x>0$)} \\ 0 & \text{($x\leq0$)} \end{cases} \end{equation}
```

- サンプルコード

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

- グラフ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/4e88316a-3e8a-0861-251c-de0542db53cc.png)

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

#### 重みの初期値設定
##### Xavier
- 特徴 
  - 重みの要素を前の層のノード数の平方根で除算した値

- Xavierの初期値を設定する際の活性化関数
  - ReLU関数
  - シグモイド（ロジスティック）関数
  - 双曲線正接関数

##### He
- 特徴
  - ReLU関数のようなS字カーブでない関数に利用される
  - 重みの要素を前の層のノード数の平方根で除算した値に対し√２をかけ合わせた値

- Heの初期値を設定する際の活性化関数
  - Relu関数

- 参考
  - ゼロから作るDeep Learning 6章  
https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/ch06/weight_init_activation_histogram.py

- 確認テスト
  - 重みの初期値に0を設定するとどのような問題が発生するか簡潔に説明せよ。

- 確認テスト解答
  - 重みが0の場合すべての重みの値が均一に更新されるため、正しい学習が行えない問題が発生する。

#### バッチ正規化
- バッチ正規化とは
  - ミニバッチ単位で、入力値のデータの偏りを抑制する手法

- バッチ正規化の使い所とは
    - 活性化関数に値を渡す前後に、バッチ正規化の処理を持つ層を加える

- バッチ正規化層への入力値
$$ u^{(l)} = w^{(l)}z^{(l-1)} + b または z $$

- 確認テスト
  - 一般的に考えられるバッチ正規化の効果を2点挙げよ。

- 確認テスト解答
  - 中間層の重みの更新が安定化され学習速度が上がる
  - 正規化により過学習を起きにくくする

### Section1 実装演習
- 勾配消失問題の解決実装
  - 付属のソースコード「2_2_2_vanishing_gradient_modified.ipynb」を利用する

- 対策をせずに多層ネットワークの学習をした場合
 - 正答率が低いままであり、うまく学習を行えていないことがわかる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/8cdeecd8-db5a-5439-bdba-009ff11f2605.png)

- ReLUを用いた場合
  - 徐々に正答率が上がり、うまく学習できていることがわかる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/d2ddf061-eae6-2a1c-25cd-967e47b358b5.png)

- sigmoid - Xavier
  - はじめから順調に学習できている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/f2223639-0816-978f-5b4c-29f22ed95d68.png)

- ReLU - He
  - 学習速度が速いことがわかる
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/4f734ea2-ea2a-311e-8e70-2739128b22ea.png)

### 学習率最適化手法
- 最適化の目的
  - 学習率は大きすぎると発散し、小さすぎると学習の速度が遅くなってしまうため

- 学習率の決め方
  - 初期の学習率を大きく設定し、徐々に学習率を小さくしていく
  - パラメータ毎に学習率を可変させる

- 学習率最適化手法
  - モメンタム
  - AdaGrad
  - RMSProp
  - Adam

#### モメンタム
- 特徴
  - 勾配降下法誤差をパラメータで微分したものと学習率の積を減算した後、現在の重みに前回の重みを減算した値と慣性の積を加算する

- 数式
$$ V_{t} = \mu V_{t-1} - \varepsilon \nabla E $$
$$ w^{(t+1)} = w^{(t)} + V_{t} $$

- ソースコード

```python
self.v[key] = self.momentum* self.v[key] -self.learning_rate* grad[key]
params[key] += self.v[key]
```

- メリット
  - 局所的最適解にはならず大域的最適解となる
  - 谷間についてから最も低い位置(最適値)にいくまでの時間が早い

#### AdaGrad
- 特徴
  - 誤差をパラメータで微分したものと再定義した学習率の積を減算する

- 数式
$$ h_{0} = \theta $$
$$ h_{t} = h_{t-1} - (\nabla E)^2 $$
$$ w^{(t+1)} = w^{(t)} - \varepsilon \frac{1}{\sqrt{h_{t}} + \theta \nabla E } $$

- ソースコード

```python
self.h[key] = np.zeros_like(val)
self.h[key] += grad[key] * grad[key]
params[key] -= self.learning_rate* grad[key] / (np.sqrt(self.h[key]) + 1e-7)
```

- メリット
  - 勾配の緩やかな斜面に対して最適値に近づける

- 課題
  - 学習率が徐々に小さくなるので、鞍点問題を引き起こす事があった

#### RMSProp
- 特徴
  - 誤差をパラメータで微分したものと再定義した学習率の積を減算する

- 数式
$$ h_{t} = \alpha h_{t-1} - (1 - \alpha)(\nabla E)^2 $$
$$ w^{(t+1)} = w^{(t)} - \varepsilon \frac{1}{\sqrt{h_{t}} + \theta \nabla E } $$

- ソースコード

```python
self.h[key] *= self.decay_rate
self.h[key] += (1 -self.decay_rate) * grad[key] * grad[key]
params[key] -= self.learning_rate* grad[key] / (np.sqrt(self.h[key]) + 1e-7)
```

- メリット
  - 局所的最適解にはならず、大域的最適解となる
  - ハイパーパラメータの調整が必要な場合が少ない

#### Adam
- 特徴
  - モメンタムの過去の勾配の指数関数的減衰平均とRMSPropの過去の勾配の2乗の指数関数的減衰平均を含む

- メリット
  - モメンタムおよびRMSPropの両方のメリットを持つアルゴリズムである
 
### Section2 実装演習
- 学習率最適化手法
  - 付属のソースコード「2_4_optimizer.ipynb」を利用する

- 確率的勾配降下法の場合
  - うまく学習できていない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/110cbf4d-ab28-6abc-3950-8601f990a033.png)

- Momentum
  - Momentumでもうまくいかない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/85ffe0d2-ad0e-b5c9-b59a-6ea80673f577.png)

- AdaGrad
  - うまくいかない… 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/f28e79cd-1810-c486-27f4-047ce0f733e1.png)

- RSMprop
  - うまく学習できた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/e343dcd7-670d-6adc-937d-e1f85a6d648d.png)

- Adam
  - Adamでもうまく学習できた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/58500e0c-2a41-875a-57d5-49c690cf6a2f.png)

- 問題に合わせて使い分けていくのが重要


### 過学習の抑制
#### 正則化
- 特徴
  - ネットワークの自由度(層数、ノード数、パラメータの値etc...)を制約すること

- 正則化手法
  1. L1正則化、L2正則化
  1. ドロップアウト

##### L1正則化、L2正則化
- 目的　→　Weight decay(荷重減衰)
    - Weight decayとは
       - 誤差に対して、正則化項を加算することで、重みを抑制する
       - 過学習がおこりそうな重みの大きさ以下で重みをコントロールし、かつ重みの大きさにばらつきを出す必要がある

- 数式
  - p=1のときL1正則化、p=2のときL2正則化という

$$ E_{n}(W) + \frac{1}{p} \lambda ||x||_{p} $$
$$ {\| {\bf x} \|_p = (\ |x_1|^p + |x_2|^p + \cdots + |x_n|^p )^{1/p}
} $$

- コード

```python
weight_decay+= weight_decay_lambda*np.sum(np.abs(network.params['W' + str(idx)]))
loss = network.loss(x_batch, d_batch) + weight_decay
np.sum(np.abs(network.params['W' + str(idx)]))
```

- 確認テスト
  - 下図について、L1正則化を表しているグラフはどちらか答えよ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/c9ce59f0-7c6c-8413-318b-300b821b37ad.png)

- 確認テスト解答
  - L1正則化のグラフは下記の通り

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/e6deafe7-bd8b-f8fd-2cc0-031efc108367.png)

##### ドロップアウト
- 目的
  - ノードの数を減らす

- 方法
  - ランダムにノードを削除して学習させること

- メリット
  - データ量を変化させずに異なるモデルを学習させていると解釈できる

#### Section3 実装演習
- 過学習解決手法
  - 付属のソースコード「2_5_overfiting.ipynb」を利用する

- 過学習が起こるようにトレーニング
  - 訓練データには100％正解しているがテストデータは70%程度の正解率になっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/00f877c3-5e3b-7d70-2b88-51434d397197.png)

- weight decay(L2正則化)を行う
  - テストデータの正解率にはほとんど変化がないが、訓練データの正解率が92%程度になっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/c4c7f8bb-daf8-626d-4e6c-cf4727ad105d.png)

- weight decay(L1正則化)を行う
  - 一部の重みが0となる(スパース化)ため特徴的な動きとなる
  - 依然として訓練データの正解率は90%程度、テストデータの正解率は70%程度

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/07e5de6f-a955-2edc-09bf-eeba7022921e.png)

- ドロップアウト
  - 順調に学習できていることがわかる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/cf192f31-0c91-fc3d-eda8-bc4f01c07d2e.png)

## 畳み込みニューラルネットワーク
### 畳み込みニューラルネットワークの概念
- CNNの構造
  - 入力層の後に畳み込み層、プーリング層(CNN)が使われているのが特徴
  - 入力は下、出力は上になる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/e451f39c-de09-4931-0866-7c17e7c30b48.png)

- CNNで扱えるデータの種類
  - 次元間でつながりのあるデータを扱うことができる
  - 例)音声データ、CTスキャン画像、カラー画像、動画

- LeNet
  - 特徴
     - 32×32の入力を扱う
     - 出力は10種類

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/99db16b3-573b-a9c1-9606-b7a8c7630df9.png)

- 畳み込み層
  - 畳み込み層では、画像の場合、縦、横、チャンネルの3次元のデータをそのまま学習し、次に伝えることができる
  - 3次元の空間情報も学習できるような層が畳み込み層である


- 畳み込み層の流れ
  - 入力値にフィルタ(重み)を適用し、出力する
  - 出力値にバイアスを足す
  - 活性化関数にかける
  - 出力される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/4c7fa514-7db7-83c5-bdc0-28684865e313.png)

- 全結合層
  - CNNでは、入力層からプーリング層までは次元のつながりを保ったまま(画像のまま)出力される
  - 最後に出力を1次元の形にするのが全結合層

#### 畳み込み層
##### バイアス
- 畳み込み層の演算とバイアスの計算イメージ

![IMG_3816.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/dd6c05c6-a531-d64a-44dc-8ef62c84955c.png)

##### パディング
- パディングとは
  - 出力画像の大きさを変更するため、入力画像の周りにデータを追加すること
  - 追加するデータは0や最も近い値などを取ることが多い

##### ストライド
- ストライドとは
  - フィルタを動かす幅のこと
  - 出力画像のサイズを小さくできる

##### チャンネル
- チャンネルとは
  - 入力値の数
  - 例)カラー画像はR、G、Bの3チャンネル

#### Section4 実装演習
- 畳み込み層
  - 付属のソースコード「2_6_simple_convolution_network.ipynb」を利用する
  - 利用するデータセットはMNIST

![di-01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/bd795fef-5fd2-d2fd-c09b-6a260611e885.gif)

- 演習結果
  - 徐々に正答率が上がっていることがわかる
  - 実行に10分程度かかった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/1fb4d6ad-7863-fd56-f7cd-0a64be0700b8.png)

#### プーリング層
- 特徴
  - 畳み込み層とは異なり、フィルタや重みを利用しない
  - 入力画像を小さくするために利用される
  - 最大値や平均値をとって演算する

- 確認テスト
  - サイズ6×6の入力画像を、サイズ2×2のフィルタで畳み込んだ時の出力画像のサイズを答えよ。なおストライドとパディングは1とする。

- 確認テスト解答

![IMG_3817.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/8df2fb48-fdc7-b8d9-c1eb-69ff494030f7.png)

### 最新のCNN
#### AlexNet
- 特徴
  - 過学習を防ぐ施策・サイズ4096の全結合層の出力にドロップアウトを使用している
  - 畳み込み層→プーリング層→畳み込み層→プーリング層→畳み込み層→畳み込み層→畳み込み層→プーリング層→全結合層(3層)という構造

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/bd332570-e664-3099-e8a5-df937046e85d.png)

#### GoogLeNet
- 特徴
  - AlexNetよりもさらに深い
  - Inceptionモジュールというブロックを構成することで並列計算が可能

#### 実装演習
- 講義内になかったため割愛

### 参考
「ディープラーニングG検定公式テキスト」