コンピュータとオセロ対戦36　～10層のハイパーパラメータ～

https://qiita.com/tt_and_tk/items/068f2afde6db637e189f

[前回](https://qiita.com/tt_and_tk/items/100a2751abe39a95442f)

# 今回の目標
[前回](https://qiita.com/tt_and_tk/items/100a2751abe39a95442f)作成したモデルの正解率を上げるハイパーパラメータを探します。

# ここから本編
## model_test.ipynb
[31の実験](https://qiita.com/tt_and_tk/items/a06e3c9ddf88b0213cb9#%E5%AE%9F%E9%A8%93)の際と同様、まずは精度が悪くてもいいのである程度学習してくれるパラメータを探します。
プログラムは[35のmodel.ipynb](https://qiita.com/tt_and_tk/items/100a2751abe39a95442f#modelipynb)と全く同じものを用いて、そのパラメータを変更しながら実験を行いました。
まず、勾配消失を疑ったので活性化関数を変えようと思いましたが、relu以外の絶対値1以上をとる活性化関数ではうまく学習できませんでした。そのため、tanhを2倍してみました。強引な方法ではありますが一応学習はしてくれました。reluとtanh以外でうまく学習できなかった理由は勾配爆発の可能性もあると考えました。誤差が非常に大きくなった時にエラーが起きるためです。
また、GradientHardClippingの引数を-2と2にすると何とか学習してくれました。
その時のグラフを以下に示します。

![mean squared error each epoch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/90d8ec7c-52dc-3239-80ca-dc7a9c067c7e.png)
![mean absolute error each epoch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/8610dedd-effc-f261-3915-17a5758aa691.png)

また、最終的に何とか学習が進んだパラメータを載せておきます。

* 層の数は10層
* データ集めの量は1(詳しくは後述)
* 活性化関数は2xtanh
* バッチサイズは200
* boundは2
* エポック数は100(上のグラフを見る限り40程度でも十分)
* 最適化手法はAdaBound
* 誤差関数は平均二条誤差

## run.ipynb
基本的には[31の実験](https://qiita.com/tt_and_tk/items/a06e3c9ddf88b0213cb9#%E5%AE%9F%E9%A8%93)とほぼ同じ実験手法ですが、もう一度説明します。
今回使用するクラスやファイルは以下のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/d835b6e4-2fc5-f429-6351-ee411a998d85.png)

ファイル構造は以下のようになっています。

```
36
├── fig
│   └── ※実験データをグラフ化した画像が入る※
├── BitBoard.py　　  ・・・オセロのための基本クラスを定義
├── deep_learn.py　 ・・・深層学習のためのクラスを定義
├── Net.py          ・・・ニューラルネットワークを定義
├── osero_learn.py 　・・・データ集めのためのクラスを定義
└── run.ipynb　　　　・・・実験実行のためのファイル
```

また、学習時間短縮のためエポック数は40にしたいと思います。本番のモデルのみ100回で学習させようと思います。

### 準備
学習を行うためのクラスをインポートします。

```py
from deep_learn import *
```

### 実験
#### データ量
学習に用いるデータの量を変えながら実験を行いました。
ここでデータ量とは、random、1hand、1hand_custom、1least、1mostのそれぞれが総当たり戦を一通り行い、そこで集まるデータの量を1とします。

```py
run = deep_learn()

num_arr = [1, 5, 10]
run.save_dir = "fig/data_quantity"
i = 1
MSE_test = []
MAE_test = []

for num in num_arr:
    print("\r%d/%d" % (i, len(num_arr)), end="")
    run.num = num
    run.fig_name1 = "MSE of each epoch (data quantity is %d)" % num
    run.fig_name2 = "MAE of each epoch (data quantity is %d)" % num
    run.set_data()
    run.fit()
    run.plot()
    test_error = run.cal_test_error()
    MSE_test.append(test_error[0])
    MAE_test.append(test_error[1])
    i += 1
```

実行結果はこちら。

![MSE of each epoch (data quantity is 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/086dd868-aace-ace7-be51-f126621da6b7.png)
![MSE of each epoch (data quantity is 5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/a6c3761d-fac1-8ce2-67a9-1e9184af216a.png)
![MSE of each epoch (data quantity is 10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/6efc2750-3d2d-9d32-8061-e018e22836ad.png)
![MAE of each epoch (data quantity is 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/b38c604d-c70c-0189-8d8d-e34710036657.png)
![MAE of each epoch (data quantity is 5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/ec1f6a46-408f-d20e-0163-631f28fd32b2.png)
![MAE of each epoch (data quantity is 10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/5cee5a82-06f3-a423-face-c8ddef9723bf.png)

```
number:  [1, 5, 10]
MSE:  [variable(318.2084), variable(184.82645), variable(302.7841)]
MAE:  [variable(11.776607), variable(9.148406), variable(12.213117)]
```

四層の時と同様、1の時しか学習しませんでした。

#### バッチサイズ
バッチサイズを変えながら調べました。
またこれ以降のプログラムはほとんどデータ量の時と変わらないので省略し実行結果のみ載せます。

![MSE of each epoch (batch size is 100).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/6a2c33af-e801-69ba-0943-b1efe132faa2.png)
![MSE of each epoch (batch size is 150).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/7cd309f3-bc73-ef9c-e3c1-0ea610ab89f6.png)
![MSE of each epoch (batch size is 200).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/10b0647d-71f8-82ff-551f-568a654b47ed.png)
![MSE of each epoch (batch size is 250).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/7f729407-67a2-6d3a-ab1c-9529cfda684c.png)
![MSE of each epoch (batch size is 300).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/b6f75497-af78-4ab3-153c-69ec7edc567b.png)
![MAE of each epoch (batch size is 100).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/d9127bfa-d2e6-719d-73b1-a80994ad8bf1.png)
![MAE of each epoch (batch size is 150).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/f459a7ae-f8ca-2a59-a9a3-9514a7f6eac3.png)
![MAE of each epoch (batch size is 200).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/1066b9b2-0c81-0093-faf8-28acdd436cef.png)
![MAE of each epoch (batch size is 250).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/378cf82d-9bea-af6a-828c-c90924f99f08.png)
![MAE of each epoch (batch size is 300).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/cb05dbae-9bfd-f9ea-9d90-b74759047941.png)

```
batch size:  [100, 150, 200, 250, 300]
MSE:  [variable(208.28833), variable(237.04642), variable(208.90796), variable(231.01593), variable(377.63495)]
MAE:  [variable(10.089901), variable(10.971919), variable(9.383556), variable(10.808541), variable(14.816)]
```

グラフを見ると、きれいに学習できているのは150から250の間くらいですね。
最終結果もその付近が最小ごさとなっています。
#### 活性化関数の乗数
活性化関数の種類については、上述のとおりtanh一択という状態なので実験しません。
tanhにかける乗数を変更しながら学習させてみました。

![MSE of each epoch (num of multi is 1.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/71b495be-c4d8-5d6e-58db-42807a56d749.png)
![MSE of each epoch (num of multi is 1.5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/d1e04171-1f0e-f9b9-5e76-8aeb1c4a5002.png)
![MSE of each epoch (num of multi is 2.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/9b60000f-1952-57dd-e6b1-66050782e443.png)
![MSE of each epoch (num of multi is 2.5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/b558f571-a82f-3379-a70c-200311249537.png)
![MSE of each epoch (num of multi is 3.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/72c7e706-47ae-1399-4fc0-ace3bc9f24c2.png)
![MSE of each epoch (num of multi is 4.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/477f0332-ce1b-b5c9-3001-aff111b59fe3.png)
![MAE of each epoch (num of multi is 1.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/fed752d5-c7e6-402e-ccc4-06e0e24ccaeb.png)
![MAE of each epoch (num of multi is 1.5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/dbb72f23-f699-cc33-9d83-ecf75ea4e128.png)
![MAE of each epoch (num of multi is 2.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/072a4926-88a6-f8b9-d72d-f43d25cea782.png)
![MAE of each epoch (num of multi is 2.5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/d858f620-cd5e-881e-1f87-98393a57736e.png)
![MAE of each epoch (num of multi is 3.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/6c87555c-73b9-8765-a992-270c7d37a676.png)
![MAE of each epoch (num of multi is 4.0).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/cb04d181-e4d0-bd62-3286-b526f24d4584.png)

```
num of multi:  [1, 1.5, 2, 2.5, 3, 4]
MSE:  [variable(493.82068), variable(229.75685), variable(335.4347), variable(222.12787), variable(299.72604), variable(299.94046)]
MAE:  [variable(18.411568), variable(10.173277), variable(13.183862), variable(10.945747), variable(12.994248), variable(13.425252)]
```

1は当然のように学習しませんでした。しかし値が大きすぎても発散するようです。
ここでは1.5が最小誤差でした。

#### 最適化関数
最適化関数について、四層の時も用いた関数たちをもう一度集め検証しました。

![MSE of each epoch (optimizer is SGD).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/a4af79bd-327c-8087-0c93-d772e8a150fb.png)
![MAE of each epoch (optimizer is SGD).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/460c114e-82c2-0ccc-ede3-ba39754be465.png)

グラフ数が非常に多いので、一つずつ見ていきます。
まずSGDですが全く学習していませんでした。
確認データでの誤差が周期的に変動しているのが気になります。

![MSE of each epoch (optimizer is MomentumSGD).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/c626b464-50bb-cf2d-5627-fda6b164fc6c.png)
![MAE of each epoch (optimizer is MomentumSGD).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/92401228-9b7d-be3a-1038-771d470414cb.png)

次にMomentumSGDですが、こちらも同様に学習していません。

![MSE of each epoch (optimizer is AdaGrad).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/f338f9b3-bc27-6912-ee9a-324da4917c5d.png)
![MAE of each epoch (optimizer is AdaGrad).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/36facbd2-b7f9-7892-7b92-5408354f041d.png)

AdaGradは過学習を起こしました。

![MSE of each epoch (optimizer is RmSprop).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/71705e7f-6344-421f-2a36-54cbe1794a03.png)
![MAE of each epoch (optimizer is RmSprop).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/c4231d0e-c946-3530-a578-cddb1b0404bb.png)

RMSpropはSGDと似たようなグラフを作りましたが、SGDと異なり確認データでの誤差はほとんど変動していません。
このことからパラメータ更新すらほぼ行われていないのではないかと考えました。
しかし理論上では、RMSpropはAdaGradに比べパラメータが更新されやすくなっているはずです。そのAdaGradが過学習を引き起こすほどにパラメータ更新され、RMSpropは変動なしというのは考えにくいと思うのですが・・・。

![MSE of each epoch (optimizer is AdaDelta).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/e7ef636e-03f1-caf4-4542-503653c8f3ad.png)
![MAE of each epoch (optimizer is AdaDelta).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/20f16338-6cd4-94a5-9254-ccb815c5ad35.png)

AdaDeltaもあまり学習していませんでした。しかし、確認データでの誤差推移がトレーニングデータでのそれよりはるかに穏やかである特徴がRmSprop以上に顕著であるように見えます。

![MSE of each epoch (optimizer is Adam).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/d2fe2bce-f42a-26c9-6716-a7fe2750c7b0.png)
![MAE of each epoch (optimizer is Adam).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/4faee86c-1314-eab3-53d9-69c8d147bc95.png)

Adamこれまでの関数に比べるとまっとうに学習しているように見えます。
しかし最終的な精度はあまり高くないですね。
RMSpropは全く学習していなかったのに対し、Adamがある程度学習できているのは不思議です。

![MSE of each epoch (optimizer is RMSpropGraves).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/ea50e54f-b0d0-e562-f811-a863001de9e5.png)
![MAE of each epoch (optimizer is RMSpropGraves).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/65022931-2d49-e141-8769-a87899ebc29e.png)

RMSpropGravesもAdamと同様、学習できています。

![MSE of each epoch (optimizer is SMORMS3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/9c32a660-1d7d-6989-bbb4-c802056630d9.png)
![MAE of each epoch (optimizer is SMORMS3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/6cd1c856-73f6-acbe-18af-5a580c865533.png)

SMORMS3も学習できていますが、収束まで時間がかかっています。

![MSE of each epoch (optimizer is AMSGrad).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/0c343644-a057-68a8-5469-6d20aaf480bc.png)
![MAE of each epoch (optimizer is AMSGrad).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/50269102-24e8-c3a9-fba3-31eef9d7f67a.png)

AMSGradはきれいに学習できていますが、Adam同様最終的な精度はいまいちです。

![MSE of each epoch (optimizer is AdaBound).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/952e3eeb-0090-984b-49f3-1f024917d80e.png)
![MAE of each epoch (optimizer is AdaBound).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/1b5eece2-ab0f-320c-e19e-e66156f41a58.png)

AdaBoundは最初の段階よりやや誤差が小さくなっているので一応学習はしているようです。しかしその精度、学習の進み具合は上のいくつかの手法に比べ明らかに劣っています。

![MSE of each epoch (optimizer is AMSBound).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/4798fcab-19b3-0f06-6e8d-abab4db10dfb.png)
![MAE of each epoch (optimizer is AMSBound).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/4dec9710-baf5-17c9-8b42-5a3d666573b2.png)

最後にAMSBoundです。こちらもAdaBoundと同様、一応学習はしているもののあまりいい方法ではなさそうです。

```
opt name:  ['SGD', 'MomentumSGD', 'AdaGrad', 'RmSprop', 'AdaDelta', 'Adam', 'RMSpropGraves', 'SMORMS3', 'AMSGrad', 'AdaBound', 'AMSBound']
MSE:  [variable(596.67865), variable(748.88885), variable(481.1794), variable(581.58185), variable(567.9831), variable(257.87805), variable(183.6314), variable(225.72916), variable(242.25677), variable(317.26895), variable(299.14655)]
MAE:  [variable(20.720228), variable(22.436901), variable(17.671604), variable(20.507269), variable(20.240658), variable(11.837251), variable(9.939592), variable(10.39656), variable(11.440739), variable(13.673), variable(13.514401)]
```

各最適化関数でのテストデータでの誤差です。
最小はRMSpropGravesでした。

#### bound
boundとは、GradientHardClippingに与える引数のことで、その絶対値を指定します。

![MSE of each epoch (bound is 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/44b41d08-71ef-1739-199e-c4e524bfd7ab.png)
![MSE of each epoch (bound is 2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/2597caf8-4eaf-377a-48b0-1b2b0b59c41b.png)
![MSE of each epoch (bound is 3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/ad57b294-b5ab-53af-a8e6-9dd3485ef55f.png)
![MSE of each epoch (bound is 4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/b5790c5e-8cba-db85-11b1-a28cf64e8620.png)
![MSE of each epoch (bound is 5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/bfe9e0fb-0771-dd65-37c5-eb1b4170781e.png)
![MAE of each epoch (bound is 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/d14408cd-48af-3ec0-9556-9819bd9d382d.png)
![MAE of each epoch (bound is 2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/dd27ebcb-e423-04b5-5902-cf82ea1b273c.png)
![MAE of each epoch (bound is 3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/a36a7a03-e3d9-8bff-dd60-0d59d0ce2d4d.png)
![MAE of each epoch (bound is 4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/72f59f10-e7cd-5eff-7490-522636c4a0e4.png)
![MAE of each epoch (bound is 5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/6bc9573b-b1a6-e2c6-685a-69a0fbeb75fe.png)

あまり学習していないように見えますが、4は比較的きれいなグラフになっています。

```
bound : [1, 2, 3, 4, 5]
MSE:  [variable(373.4251), variable(277.93234), variable(436.827), variable(403.12445), variable(308.02844)]
MAE:  [variable(14.932132), variable(13.277081), variable(16.416647), variable(16.157673), variable(13.493976)]
```

誤差はどれも非常に大きくなる結果となりました。

#### 更新回数
エポック数を1000まで増やしてみました。

![MSE of each epoch (n_epohc is 1000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/bdae9fef-928c-0623-c162-91b27c67fb83.png)
![MAE of each epoch (n_epoch is 1000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/1da6de1f-11d0-ba20-7129-e9ca8facc058.png)

```
n_epoch:  1000
MSE:  variable(671.48865)
MAE:  variable(21.532646)
```

序盤は学習するものの、エポック数が100付近になったところから誤差が急増しそのまま減らなくなりました。これは[四層の時](https://qiita.com/tt_and_tk/items/a06e3c9ddf88b0213cb9#%E6%9B%B4%E6%96%B0%E5%9B%9E%E6%95%B0%E3%82%92%E5%A4%89%E6%9B%B4)とは全く異なる挙動です。
理由はわかりませんが、本番用のモデルはいいところで学習を止める必要性があるかもしれません。

#### 調査ターン
データ集めの際、何ターンごとにデータを集めるかを変えながら調べてみました。

![MSE of each epoch (turn is every 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/cc05614d-b3a7-2510-32e8-f999cfbe91bf.png)
![MSE of each epoch (turn is every 5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/329a0b54-6900-a14f-cb5a-f9fe91e31199.png)
![MSE of each epoch (turn is every 10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/7e01ca5c-2470-0139-81bf-ae065ab5c9ec.png)
![MAE of each epoch (turn is every 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/5ffa52df-7f84-be6e-a26e-aab934e5469d.png)
![MAE of each epoch (turn is every 5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/3c400ee3-af1f-8809-37ad-969609479708.png)
![MAE of each epoch (turn is every 10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/bf2c72c3-52ee-c812-4b02-c6f25ab8141e.png)

```
['every 1', 'every 5', 'every 10']
MSE:  [variable(199.15181), variable(414.1164), variable(571.50305)]
MAE:  [variable(9.791213), variable(15.582603), variable(17.601833)]
```

こちらは予想通り、より多くデータを集めたほうが過学習しにくい結果となりました。

#### 重み減衰
重み減衰の手法を変えながら実験を行いました。

![MSE of each epoch (hook function is WeightDecay).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/7f38669f-be90-64b5-48d8-c6fd3b7fc254.png)
![MAE of each epoch (hook function is WeightDecay).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/f7e965cf-fdfe-739b-77c3-fba40a72face.png)

途中まで誤差が小さくなっているように見えるものの、35付近で大きくなっています。
また、誤差が小さくなっているというのもはっきりとそうであるとは言えないと思います。

![MSE of each epoch (hook function is Lasso).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/4fc6b82f-0540-e1e8-97b3-8a76182a3e03.png)
![MAE of each epoch (hook function is Lasso).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/ba402f4c-3089-0ede-c47d-0f4438daf9dc.png)

こちらはほぼ学習していないように見えます。

![MSE of each epoch (hook function is GradientHardClipping).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/2f5492bd-a9c1-c1f1-d0a0-1d018a118fc2.png)
![MAE of each epoch (hook function is GradientHardClipping).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/4a7de8d1-ed57-6e09-9b61-b12193891841.png)

上二つと違い、きれいな形ではないものの学習はしているようです。
GradientHardClippingの基本概念は上二つと同じく重みを大きくしすぎないことですが、WeightDecayとLassoにはあまり効果が見られずこれだけがうまくいきました。
そのため、説明変数が多い状態で重み0を目指すのはあまりよくないのではと考えました。GradientHardClippingは重みの最大を制限はするものの、最小を目指すわけではありません。

![MSE of each epoch (hook function is GradientNoise).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/a165a347-ded5-e47e-7766-44f7caae427a.png)
![MAE of each epoch (hook function is GradientNoise).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/2ff54c50-889b-431e-2cea-64b1eb22d001.png)

エポック数15までの部分のみを見ると順調に下がっているようにも見えなくない結果となりました。
誤差の最小記録だけを見れば悪くないですが、安定してこの精度が出るかどうかはわかりません。

![MSE of each epoch (hook function is GradientLARS).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/76aa2672-2c4d-a1b0-ad56-5d467c11fa71.png)
![MAE of each epoch (hook function is GradientLARS).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/d8013ef7-bcd5-27c9-d879-68cbfff312f6.png)

かなり順調に学習しており、最終的なトレーニング平均絶対誤差は2付近まで下がっています。

```
['WeightDecay', 'Lasso', 'GradientHardClipping', 'GradientNoise', 'GradientLARS']
MSE:  [variable(547.9877), variable(516.57294), variable(265.04657), variable(368.97327), variable(132.2816)]
MAE:  [variable(19.518631), variable(19.172485), variable(11.6672735), variable(15.090247), variable(7.1252656)]
```

テストデータでの誤差もGradientLARSがずば抜けて優秀でした。
平均二乗誤差が100代前半なのは非常にいいですね。

### GradientLARSの引数
次に、先ほどの実験で好成績を残したGradientLARSの引数を変更しながら最適なパラメータを探しました。

#### threashold
重みの上限のようなものです。デフォルトは0.01。

![MSE of each epoch (threashold is 0.000100).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/56ec2dbb-8dd3-6e51-b457-712039a2b7af.png)
![MSE of each epoch (threashold is 0.001000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/e549a7f0-dc5e-8fcb-190f-ebff28b9417e.png)
![MSE of each epoch (threashold is 0.005000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/200c73fd-bd62-66cf-f79a-f3210f367afa.png)
![MSE of each epoch (threashold is 0.010000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/9f8d06b8-1913-4cb5-7a93-dadd70357de1.png)
![MSE of each epoch (threashold is 0.050000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/2ebf9909-4235-2445-0561-8f25d2915320.png)
![MSE of each epoch (threashold is 0.100000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/acfe0096-8dea-4654-1426-80a33f252dde.png)

![MAE of each epoch (threashold is 0.000100).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/b413caa4-0fcf-c1e1-6d1a-a668a54af07d.png)
![MAE of each epoch (threashold is 0.001000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/a1c9d092-4f40-82f4-d24b-30858a20228b.png)
![MAE of each epoch (threashold is 0.005000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/7a52194a-5d8b-a33d-7d9b-74b339ce31b1.png)
![MAE of each epoch (threashold is 0.010000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/f3a417bb-1b51-7302-9593-20d093f7fcde.png)
![MAE of each epoch (threashold is 0.050000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/ec3ce8d8-8811-53ec-5ccb-1c66212fd2e2.png)
![MAE of each epoch (threashold is 0.100000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/cf95a126-c955-900b-09bd-1a508c3641ae.png)

```
threshold arr:  [0.0001, 0.001, 0.005, 0.01, 0.05, 0.1]
test MSE:  [variable(166.19632), variable(170.0784), variable(171.25908), variable(163.18517), variable(170.33223), variable(146.83133)]
test MAE:  [variable(8.09928), variable(8.408168), variable(8.693802), variable(8.035527), variable(8.495775), variable(7.6456904)]
```

以外にもどの値でもほとんど変わらない結果になりました。
10層でしかも説明変数が64x3=192個もあるため、そもそもあまり制限しなくても重みはあまり大きくならないのではないかと考えました。
デフォルト値を採用しようと思います。

#### weight_decay
重み減衰係数です。デフォルトは0.0。

![MSE of each epoch (weight_decay is 0.000000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/0459ab60-d7e6-c302-64df-e30a4ff6b3da.png)
![MSE of each epoch (weight_decay is 0.000010).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/36b5eaea-2ca1-8150-1918-f58d7b58a262.png)
![MSE of each epoch (weight_decay is 0.000100).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/68f1c1bb-a6f8-78f1-4a46-ccfd1eee1f08.png)
![MSE of each epoch (weight_decay is 0.001000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/abffa814-5bdd-6cb2-8055-404bacad64b8.png)

![MAE of each epoch (weight_decay is 0.000000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/3f2eaf91-1e36-0ca0-7c5c-0daf8e368b58.png)
![MAE of each epoch (weight_decay is 0.000010).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/9b23cc13-3ae6-b12b-5fa7-2c93e6ace190.png)
![MAE of each epoch (weight_decay is 0.000100).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/1d242476-ecda-5299-6419-d94775d70548.png)
![MAE of each epoch (weight_decay is 0.001000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/8d643ec6-59a6-e550-9c4f-b252c29c91a4.png)

```
weight_decay arr:  [0.0, 1e-05, 0.0001, 0.001]
test MSE:  [variable(150.91196), variable(148.27405), variable(147.56767), variable(157.84373)]
test MAE:  [variable(7.587319), variable(8.179049), variable(7.731195), variable(8.590252)]
```

最適な数字の時に誤差が最小になると予想していましたが、実際にはどれも大して変わらない結果となりました。
何が最適であるかわからない以上デフォルト値を使いたいと思います。

#### eps
デフォルトはe^(-9)、およそ0.0001234です。

![MSE of each epoch (eps is 0.000000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/990b9e17-84b8-0b02-d2ba-7800a503c5e2.png)
![MSE of each epoch (eps is 0.000050).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/429cb76e-3f3a-68de-02d2-4a10ae4e50c4.png)
![MSE of each epoch (eps is 0.000123).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/91673ae0-3004-50e9-d3b7-6e56aa07fe65.png)
![MSE of each epoch (eps is 0.000200).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/90654c0b-ce3c-22e6-3ee8-624ec40cbed7.png)
![MSE of each epoch (eps is 0.000500).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/9daa63ee-d055-844d-cd9b-d5847d4ab626.png)
![MAE of each epoch (eps is 0.000000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/34ce8d5f-fd90-8957-5eb3-909ddaa30854.png)
![MAE of each epoch (eps is 0.000050).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/667e0932-113d-f5fe-2258-ca8f241e677a.png)
![MAE of each epoch (eps is 0.000123).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/86134004-4f41-7e74-0007-26eb72d2a649.png)
![MAE of each epoch (eps is 0.000200).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/537ef378-b7af-c398-76e2-69b2faca3417.png)
![MAE of each epoch (eps is 0.000500).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/53248ebc-5d26-02db-3f42-262a0faaa753.png)

```
eps arr:  [0.0, 5e-05, 0.0001234, 0.0002, 0.0005]
test MSE:  [variable(170.8527), variable(145.1517), variable(144.97327), variable(148.69962), variable(156.80756)]
test MAE:  [variable(8.57553), variable(7.707429), variable(7.4129925), variable(7.4839306), variable(7.969676)]
```

どれも似たような結果になりました。
最小記録となったデフォルト値を採用したいと思います。

また全体を通して、平均絶対誤差では差が開いても平均二乗誤差ではあまり差が開かないことが数回あったことが気になりました。
安定して誤差が小さいのは平均二乗誤差が小さいほうなので、同じ平均絶対誤差ならそちらを見ていく必要がありそうです。

#### 更新回数
GradientHardClippingからGradientLARSに変更したので、エポック数を極端に増やした場合の挙動も変化するかもしれないと考え実験してみました。

その結果はこちら。

![MSE of each epoch (n_epoch is 1000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/6baf8aa6-faab-67b5-f4fe-45ebac9b4b96.png)
![MAE of each epoch (n_epoch is 1000).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925706/afbe2775-0d02-21eb-9e14-113a0e16f3a8.png)

```
n_epoch:  1000
test MSE:  variable(574.58624)
test MAE:  variable(20.3639)
```

GradientHardCLippingの時と同様、途中から誤差が大きくなり更新されなくなりました。
しかし誤差が急増するまでのエポック数は増えていました。
誤差がNanになっていないので勾配爆発ではないと思いますが、エポック数約500以降で特に改善も悪化もしていない理由は今の時点ではわかりません。

### 総合実験
今まで求めてきたパラメータを組み合わせたうえで、どの組み合わせが最も学習が進むかどうか調べたいと思います。

```py
import chainer.optimizers as opt
from chainer.optimizer_hooks.gradient_lars import GradientLARS
import pandas as pd

import Net

################################

bs_arr = [150, 200, 250]
multi_arr = [1.5, 2.0, 2.5]
opt_arr = [
    opt.Adam,
    opt.RMSpropGraves,
    opt.SMORMS3,
    opt.AMSGrad
]
opt_name = [
    "Adam",
    "RMSpropGraves",
    "SMORMS3",
    "AMSGrad"
]
bound_arr = [1, 2, 3, 4]

################################

data = {}

data["batch_size"] = []
data["multi"] = []
data["optimizer"] = []
data["bound"] = []
data["test_MSE"] = []
data["test_MAE"] = []

################################

run = deep_learn()
run.num = 2
run.set_data()
i, j = 1, 1

for bs in bs_arr:
    # print("\r%d/%d" % (i, len(bs_arr)), end="")
    run.batch_size = bs
    for multi in multi_arr:
        print("\r%d/%d" % (i, len(bs_arr)) + "." * j, end="")
        # print(".", end="")
        Net.n_multi = multi
        run.Net = Net.Net
        for opt_num in range(len(opt_arr)):
            run.optimizer = opt_arr[opt_num]()
            for bound in bound_arr:
                run.bound = bound
                run.hook_f = GradientLARS()
                run.fit()
                test_error = run.cal_test_error()
                data["batch_size"].append(bs)
                data["multi"].append(multi)
                data["optimizer"].append(opt_name[opt_num])
                data["bound"].append(bound)
                data["test_MSE"].append(test_error[0])
                data["test_MAE"].append(test_error[1])
        
        j += 1
    i += 1

################################

data_df = pd.DataFrame(data)
data_df.to_csv("data.csv")
```

本当はGradientLARSの引数についても変更しながら調査したかったですが、引数三つのパラメータをそれぞれ三つずつ(デフォルト値及びその前後の値)で検証すると実行時間が十倍近くになってしまうので取りやめました。
実行結果はanalysis.ipynbのほうで示します。

## analysis.ipynb

```py
import pandas as pd

data = pd.read_csv("data.csv")

################################

data_top = data["test_MAE"].min()
data_top
```

実行結果はこちら。

```
'variable(10.051524)'
```

最小で10程度という意外な結果になりました。
平均二乗誤差についても調べたところ、

```py
data_top = data["test_MSE"].min()
data_top
```

```
'variable(167.63565)'
```

あまりよくないですね。

# フルバージョン

https://github.com/TTaisei/osero/tree/main/deep_learn

# 参考資料
[深層学習の最適化アルゴリズム](https://qiita.com/ZoneTsuyoshi/items/8ef6fa1e154d176e25b8)
[chainer.optimizer_hooks.GradientHardClipping](https://docs.chainer.org/en/stable/reference/generated/chainer.optimizer_hooks.GradientHardClipping.html)
[chainer.optimizer_hooks.GradientNoise](https://docs.chainer.org/en/stable/reference/generated/chainer.optimizer_hooks.GradientNoise.html#chainer.optimizer_hooks.GradientNoise)
[chainer.optimizer_hooks.GradientLARS](https://docs.chainer.org/en/stable/reference/generated/chainer.optimizer_hooks.GradientLARS.html#chainer.optimizer_hooks.GradientLARS)

# 次回は
10層については潔くいったん諦め、[34](https://qiita.com/tt_and_tk/items/13be9077d3b136c20375)の結果から考えていることがありますのでそちらを試したいと思います。

[次回](https://qiita.com/tt_and_tk/items/753fe2fad62b9fad5aae)

https://qiita.com/tt_and_tk/items/068f2afde6db637e189f