TensorFlowを使って学習率による動きの違いを確認する

学習率とは、機械学習の最適化においてどのくらい値を動かすかというパラメーター。学習率を大きくしすぎると発散し、小さくしすぎると収束まで遅くなる。
（参考）
[確率的勾配降下法 - Wikipedia](https://ja.wikipedia.org/wiki/%E7%A2%BA%E7%8E%87%E7%9A%84%E5%8B%BE%E9%85%8D%E9%99%8D%E4%B8%8B%E6%B3%95)


学習率を変えると、実際にどのような変化がおきるのかを確認してみます。

コードはこちらのスライドシェア資料を参考というかほぼそのままお借りしました。ありがとうございます。
[TensorFlow を使った 機械学習ことはじめ (GDG京都 機械学習勉強会)](http://www.slideshare.net/ToruUenoyama/tensorflow-gdg#)


学習回数は100で実施。

まずは0.02で。学習回数が増えるに従って、誤差(loss)が少なくなっている。

```py:学習率0.02
step= 10, a1= 70.35, a2= 46.23, loss=2189.06
step= 20, a1= 83.06, a2= 36.70, loss=771.90
step= 30, a1= 90.13, a2= 31.41, loss=334.34
step= 40, a1= 94.05, a2= 28.47, loss=199.24
step= 50, a1= 96.23, a2= 26.84, loss=157.52
step= 60, a1= 97.44, a2= 25.93, loss=144.64
step= 70, a1= 98.12, a2= 25.42, loss=140.67
step= 80, a1= 98.49, a2= 25.14, loss=139.44
step= 90, a1= 98.70, a2= 24.99, loss=139.06
step=100, a1= 98.81, a2= 24.90, loss=138.94 #<-大体収束したかんじ？
Estimated: a1= 98.81, a2= 24.90
```

学習率を大きくしてみる（0.02→0.03）。

```py:学習率0.03
step= 10, a1= 73.17, a2= 34.21, loss=4294.48
step= 20, a1= 89.89, a2= 30.60, loss=365.64
step= 30, a1= 95.40, a2= 27.36, loss=172.08
step= 40, a1= 97.52, a2= 25.86, loss=144.38
step= 50, a1= 98.37, a2= 25.23, loss=139.81
step= 60, a1= 98.72, a2= 24.97, loss=139.04
step= 70, a1= 98.86, a2= 24.87, loss=138.91
step= 80, a1= 98.92, a2= 24.82, loss=138.89 #<-学習率0.02のときより早く学習が進んだ
step= 90, a1= 98.94, a2= 24.80, loss=138.89
step=100, a1= 98.95, a2= 24.80, loss=138.89
Estimated: a1= 98.95, a2= 24.80
```

step=80のあたりから0.02の時と同じくらいの値になり、だいたい収束。
0.02の時よりも早く学習が進んだ、といえそう。

更に大きくしてみる（0.03→0.04）。

```py:学習率0.04
step= 10, a1=-1218.16, a2=-1701.15, loss=72692296.00
step= 20, a1=-35600.09, a2=-47610.88, loss=54651076608.00
step= 30, a1=-978623.00, a2=-1306208.75, loss=41087909494784.00
step= 40, a1=-26835814.00, a2=-35816112.00, loss=30890815689588736.00
step= 50, a1=-735823872.00, a2=-982056064.00, loss=23224392576256704512.00
step= 60, a1=-20175843328.00, a2=-26927374336.00, loss=17460625766201346228224.00
step= 70, a1=-553209167872.00, a2=-738332180480.00, loss=13127297990348094062985216.00
step= 80, a1=-15168652181504.00, a2=-20244609368064.00, loss=9869395903782015784173174784.00
step= 90, a1=-415914935713792.00, a2=-555094592454656.00, loss=7420028838751987944110795259904.00
step=100, a1=-11404128160841728.00, a2=-15220346189774848.00, loss=5578544673282200200031359729664000.00
Estimated: a1=-11404128160841728.00, a2=-15220346189774848.00
#誤差が爆発＝学習失敗
```

誤差が爆発して、学習失敗。step10の時点（step1からstep10になるあいだ）で、学習率0.02とかのときと全然違う値になっている（増えている）。

少し小さくしてみる（0.035）。

```py:学習率0.035
step= 10, a1=-35.04, a2=-116.59, loss=937473.94
step= 20, a1=-190.85, a2=-348.92, loss=5592642.50
step= 30, a1=-596.11, a2=-898.31, loss=33397594.00
step= 40, a1=-1595.04, a2=-2234.48, loss=199447504.00
step= 50, a1=-4039.15, a2=-5497.51, loss=1191086208.00
step= 60, a1=-10012.99, a2=-13470.78, loss=7113093120.00
step= 70, a1=-24611.98, a2=-32955.22, loss=42478956544.00
step= 80, a1=-60288.40, a2=-80570.26, loss=253681385472.00
step= 90, a1=-147472.94, a2=-196929.75, loss=1514969104384.00
step=100, a1=-360530.53, a2=-481283.75, loss=9047301423104.00
Estimated: a1=-360530.53, a2=-481283.75
#0.035でもNG
```

やはりNG。もう少し小さくしてみる（0.032）。

```py:学習率0.032
step= 10, a1= 59.87, a2= 13.81, loss=38366.82
step= 20, a1= 83.51, a2= 19.98, loss=6451.94
step= 30, a1= 92.85, a2= 22.70, loss=1181.79
step= 40, a1= 96.54, a2= 23.89, loss=311.22
step= 50, a1= 98.00, a2= 24.41, loss=167.37
step= 60, a1= 98.58, a2= 24.63, loss=143.60
step= 70, a1= 98.81, a2= 24.72, loss=139.67
step= 80, a1= 98.90, a2= 24.76, loss=139.02
step= 90, a1= 98.93, a2= 24.78, loss=138.91
step=100, a1= 98.95, a2= 24.79, loss=138.89 #<-0.03のときより遅くなってる
Estimated: a1= 98.95, a2= 24.79
```

爆発はしなくなったが、step10の時点のlossが0.02や0.03のときと比べて大きく、その分なのかlossが0.03と同様の138.89に達したのがstep100となっており、0.03の場合（step80）よりも遅くなっている。

では逆に0.02よりも小さくしてみる（0.02→0.01）。

```py:学習率0.01
step= 10, a1= 60.41, a2= 53.66, loss=3645.08
step= 20, a1= 70.10, a2= 46.41, loss=2104.03
step= 30, a1= 77.36, a2= 40.98, loss=1240.31
step= 40, a1= 82.79, a2= 36.91, loss=756.21
step= 50, a1= 86.85, a2= 33.86, loss=484.88
step= 60, a1= 89.89, a2= 31.58, loss=332.81
step= 70, a1= 92.17, a2= 29.88, loss=247.58
step= 80, a1= 93.88, a2= 28.60, loss=199.81
step= 90, a1= 95.16, a2= 27.64, loss=173.03
step=100, a1= 96.11, a2= 26.93, loss=158.03
Estimated: a1= 96.11, a2= 26.93
```

step100の時点で、lossが158.03。これは学習率0.02でやったときのstep50くらいの値。
つまり学習が進むのが遅く、現在の学習回数では十分ではない状態。

では学習回数を200回にしてみる。

```py:学習率0.01　学習回数200
step= 10, a1= 60.41, a2= 53.66, loss=3645.08
step= 20, a1= 70.10, a2= 46.41, loss=2104.03
step= 30, a1= 77.36, a2= 40.98, loss=1240.31
step= 40, a1= 82.79, a2= 36.91, loss=756.21
step= 50, a1= 86.85, a2= 33.86, loss=484.88
step= 60, a1= 89.89, a2= 31.58, loss=332.81
step= 70, a1= 92.17, a2= 29.88, loss=247.58
step= 80, a1= 93.88, a2= 28.60, loss=199.81
step= 90, a1= 95.16, a2= 27.64, loss=173.03
step=100, a1= 96.11, a2= 26.93, loss=158.03
step=110, a1= 96.83, a2= 26.39, loss=149.61
step=120, a1= 97.36, a2= 25.99, loss=144.90
step=130, a1= 97.76, a2= 25.69, loss=142.26
step=140, a1= 98.06, a2= 25.46, loss=140.78
step=150, a1= 98.29, a2= 25.29, loss=139.95
step=160, a1= 98.46, a2= 25.17, loss=139.48
step=170, a1= 98.58, a2= 25.07, loss=139.22
step=180, a1= 98.68, a2= 25.00, loss=139.08
step=190, a1= 98.75, a2= 24.95, loss=138.99
step=200, a1= 98.80, a2= 24.91, loss=138.95
Estimated: a1= 98.80, a2= 24.91
```

step200で、学習率0.02のときと同等のloss＝138.9ぐらいとなった。学習の進みが遅く2倍の学習回数が必要という状態。

学習率が小さいということは、最適化関数のパラメーターを小さく動かすということで精度が上がる可能性がある。更に学習が進むか、もう少し回数を増やしてみる（200→300）。

```py:学習率0.01　学習回数300
step= 10, a1= 60.41, a2= 53.66, loss=3645.08
step= 20, a1= 70.10, a2= 46.41, loss=2104.03
step= 30, a1= 77.36, a2= 40.98, loss=1240.31
step= 40, a1= 82.79, a2= 36.91, loss=756.21
step= 50, a1= 86.85, a2= 33.86, loss=484.88
step= 60, a1= 89.89, a2= 31.58, loss=332.81
step= 70, a1= 92.17, a2= 29.88, loss=247.58
step= 80, a1= 93.88, a2= 28.60, loss=199.81
step= 90, a1= 95.16, a2= 27.64, loss=173.03
step=100, a1= 96.11, a2= 26.93, loss=158.03
step=110, a1= 96.83, a2= 26.39, loss=149.61
step=120, a1= 97.36, a2= 25.99, loss=144.90
step=130, a1= 97.76, a2= 25.69, loss=142.26
step=140, a1= 98.06, a2= 25.46, loss=140.78
step=150, a1= 98.29, a2= 25.29, loss=139.95
step=160, a1= 98.46, a2= 25.17, loss=139.48
step=170, a1= 98.58, a2= 25.07, loss=139.22
step=180, a1= 98.68, a2= 25.00, loss=139.08
step=190, a1= 98.75, a2= 24.95, loss=138.99
step=200, a1= 98.80, a2= 24.91, loss=138.95
step=210, a1= 98.84, a2= 24.88, loss=138.92
step=220, a1= 98.87, a2= 24.86, loss=138.91
step=230, a1= 98.89, a2= 24.84, loss=138.90
step=240, a1= 98.91, a2= 24.83, loss=138.89 #<-ここからloss変わらず
step=250, a1= 98.92, a2= 24.82, loss=138.89
step=260, a1= 98.93, a2= 24.81, loss=138.89
step=270, a1= 98.94, a2= 24.81, loss=138.89
step=280, a1= 98.94, a2= 24.80, loss=138.89
step=290, a1= 98.95, a2= 24.80, loss=138.89
step=300, a1= 98.95, a2= 24.80, loss=138.89
Estimated: a1= 98.95, a2= 24.80
```

step240でloss=138.89となり、以降は変わらず。つまり、200回時点の138.95よりは誤差が小さくなった（138.95→138.89）が、その分余分に学習した100回（実質40回）との兼ね合いをどう考えるか、というところ。


実際には、学習率は固定ではなく、最初は少し大きめの値から初めて徐々に小さくしていくなどの調整が行われることが多い。
例）イテレーション毎に0.9倍していく
（参考）
[第20回　ロジスティック回帰の実装：機械学習 はじめよう｜gihyo.jp … 技術評論社](https://gihyo.jp/dev/serial/01/machine-learning/0020)

上述したWikipedia記事にも学習率の調整方法がいくつか記載されている。


「学習率をXX変更すると、誤差がXXX変わる」みたいなものは、当然モデル式によって変わってくるので今後の課題（着手未定）とします。