学習率の変化による損失と精度への影響 (2)
はじめに
前回の記事で、勾配と学習率の関係において一度最小値に達した後、再び勾配は大きくなったため、勾配と学習率の関係に着目して何故このような減少が生じるのか調べた。
SGDのアルゴリズムの違いによる影響
- モーメンタムなし
- モーメンタムあり
- モーメンタム + nestrov
図1、図2、図3にepochと勾配の関係を示す。図2、図3においては、を勾配とした。いずれのSGDの手法においてもepochと勾配の関係に違いはなかった。
損失関数による影響
CIFAR100のような多クラス分類では、モデル出力値にLogSoftmax関数を適用した後、NLLLossにより推定値を求めている。これはCross Entropy Lossとほぼ同じである。
NLLLoss
NLLLossを次式に示す。
今回の話では、はモデルの出力値、はラベルのインデックスである。また、はバッチサイズ、は重みであり1である。NLLLossはで微分しても定数であり勾配に影響しない。
LogSoftmax
LogSoftmaxを次式に示す。
はモデルの出力値である。図4にこの関数への入力と出力の関係を示す。
図のようにLogSoftmaxは負の値であり、線形である。この関数の微分形を次式に示す。
図5に微分式への入力と出力の関係を示す。
図に示すように微分形の出力はほぼ一定である。従って、学習率と勾配の関係に影響しないと考えられる。
ついでに、順伝播と逆伝播の関係を調べた。これらは式(4)のように表され、LogSoftmaxの順伝播と逆伝播は図6のようになる。
はLogSoftmax関数である。
結論
参考[1]によると、高次元のニューラルネットワークのパラメータを最適化する時、局所解は事実上存在せず、全次元のうち数次元において極値をある鞍点が存在する。この鞍点からどのように脱出するかを突き止めるまで、鞍点への接近と脱出の状態が繰り返される。
というのが上記の実験で見られた勾配の振動であると思われる。
大域解ではない局所解である確率は損失関数が大域解に近づくほど高くなるため、学習がある程度進めば局所解である部分で止めても問題はないらしい。
参考
SGDについて
はじめに
SGD(Stochastic gradient decession)について、設定した目的関数に対してどのようにパラメータを更新しているのかシミュレーションを行い調べた。
実装環境
- Google Colaboratory
ついでにPytorchでのSGDの挙動を調べるためPytorch版とnumpy版を作成して、ステップの更新を調べた。
SGD
SGDは目的関数を最小化する手法。の導関数を求め、入力の勾配に応じて更新する度合を設定する。
モーメントを使用しない時、
momentumを使用するとき、
momentumを使用かつnestrovを適用する時、
結果
- パラメータ設定
SGD:momentum = 0.9, nesterov = True
初期点:
学習率:
- 目的関数:
図1に示す目的関数はで極小値を持つ。
目的関数の平面上におけるSGDのパラメータの軌跡を図2に示す。勾配が0となる点に向けて移動するため、の負の方向にパラメータが更新されている。
次に、iterationと勾配、および損失の関係を図3に示す。iterationが15の時、勾配は0となり損失は最小値をとった。その後の勾配は負であるため、目的関数の最小点を超えて坂道を駆け上っているような状態であると思われる。
- 目的関数:
図4に示すようにで鞍点を持つ関数である。
目的関数の平面上におけるSGDのパラメータの軌跡を図5に示す。勾配が0となる点に向けて移動するため、の負の方向にパラメータが更新されている。また、今回のような初期値の取り方では鞍点から抜け出せず、モデルに最適な最小値をとれていない。
次に、iterationと勾配、および損失の関係を図6に示す。鞍点にはまっているにも関わらず損失および勾配は図3と同様な傾向を示している。
従って、損失が0に近づいたとしても目的関数の最小値であるとは限らない。つまり、iterationにおける損失をみただけでは、目的関数が最小となる値を求められているかわからない。
- PytorchとnumpyのSGDの比較
パラメータの更新式はPytorchのReferenceを参考に構成したため、異なる点は勾配の計算方法であると思われる。Pytorchでは中心差分で計算してるのかな?うまく再現できなかったため不明である。
参考
学習率の変化による損失と精度への影響 (1)
はじめに
前回の記事において、epochの途中で学習率を変更すると精度が上昇する現象が確認できたため、エポックごとに学習率を変化させた時の損失と精度を調べてみた。
https://github.com/9mao9/changing-learning-rate
実装環境
バージョン情報
- torch 1.10.0+cu111
- torchvision 0.11.1+cu111
- numpy 1.19.5
- sklearn 1.0.2
訓練データはCIFAR-100を利用した。
ネットワークモデルはWideResNetを用いた。
実験条件
- 入力サイズ:[3, 32, 32]
- バッチサイズ:128
- 初期学習率:0.1
- weight decay:5e-4
- optimizer: SGD (momentum: 0.9, nestrov=True)
- transform: RandAugmentation (magnitude: 10)
- Drop out: 0.3
学習率の更新
epoch数が[0, 60, 120]の時、学習率は[0.1, 0.02, 0.04]となる点に対して近似を行い、関数を作成した。学習率の上限は0.1、下限は0.004とし、下限に達するまでepochを増加させた。従って、(i), (ii), (iii)は100 epoch、(iv)は120 epoch、(v)は147 epochまで行った。
(1) 一定:(i) , (ii)
(2) 線形:(iii) , (iv)
(3) 非線形:(v) , (vi)
epoch数をとおいた。各条件を図1に示す。
結果
(i)と(ii)のepochと損失の関係を図2に示す。学習率が高い時の方が早く損失が小さくなり学習が進んでいるように見える。また、精度も早くに高くなっている。
(iii)と(iv)のepochと損失の関係を図3に示す。(iii)では学習率の下限0.004となる74 epochで損失および精度が収束している。(iv)では50 epochで一度収束し、学習率が小さくなるにつれて再度損失が小さくなった。
(v)と(vi)のepochと損失の関係を図4に示す。(v)のように学習の始めで大きく減少し緩やかになる学習率の設定だと損失の変化も緩やかになった。対して、始めは緩やかで徐々に大きく減少していく学習率だと損失がより小さくなった。
学習率が一定の時のepochと損失勾配の関係、線形、非線形の時の学習率と損失勾配の関係を図5に示す。(i)では60 epochで勾配は収束した。(ii)は勾配の振動が大きく最小値に収束していないため、まだ学習の途中であると考えられる。(iii) - (vi)では一度最小値に達した後、再び勾配は大きくなっていった。
損失勾配は式(1)により導出したため、厳密には損失の勾配とは異なる。
は損失勾配、は損失コスト、は学習率である。
結論
本実験より、一般的に言われている「学習率は大きいほど学習が早く進む」ことを確認できた。また、今回用いたネットワークに限定されるかもしれないが、学習率を動的に変化させる方が損失が小さく精度は高くなる傾向にあることがわかった。その際、(iv)または(vi)のような徐々に学習率が小さくなる方法がよさげであった。
勾配と学習率の関係において、一度最小値に達した後、再び勾配は大きなったことについて、勾配の振動については(2)の記事を設けて調査する。
WideResNetを試してみた
はじめに
ディープラーニングについて学習する上で、WideResNetを実装して試行毎の損失、正解率をグラフ化してみた。
WideResNetについて
従来ではResNetの層の深さに対するアプローチが行われていたが、層の幅を広くすることで、浅い層でも高い精度を実現した手法[1]。モデルの作成において[2][3][4]を参考にした。
実装環境
バージョン情報
- torch 1.10.0+cu111
- torchvision 0.11.1+cu111
- numpy 1.19.5
- sklearn 1.0.2
訓練データはCIFAR-100を利用した。
実験条件
- 入力サイズ:[3, 32, 32]
- バッチサイズ:128
- 学習率:0.1 (60 epochからは0.2倍)
- Network width:2, 10
- weight decay:5e-4 (Network width: 10の時 1e-4)
- optimizer: SGD (momentum: 0.9, nesterov)
- transform: RandAugmentation (magnitude: 10)
- Drop out: 0.3
Network widthが10の時、初期学習率が0.1だと損失が発散してしまったため、0.01とした。ネットワークの深さは28層とし、100 epochで確かめた。
結果
精度は式(1)に示す正解率である。
wrn-28-2では実行時間は1時間ほどで、60 epochで学習率を0.2倍した際に精度は上昇した。50層のResNetと比較すると、50 epochまでであるため、1/4の時間でほぼ同様の精度となった。
wrn-28-10では3時間ほどであったが、精度はwrn-28-2よりも高くなった。また、wrn-28-10では30 epochからTrainよりもValの損失が大きくなり、過学習の傾向が見られた。
結論
ネットワークが広くなるほど(チャンネル数が大きくなるほど)実行時間は増加するが、精度は高くなり、ネットワークの深さだけでなく広さに対しても実行時間と精度はトレードオフの関係にあることが確認できた。
学習が進むほど損失は小さくなるため、損失に応じた学習率の設定が精度向上に有効? → 次回
参考
conv層のバイアスあり・なしの比較
はじめに
[1]を読むとバッチノルム層がある場合、畳み込み層のバイアスは必要ないっぽい?
なので、前回のプログラムを修正してResnet-RSのみバイアスあり・なしで実行してみました。
あと、細々したところも修正...
Githubに載せたコードも修正しました。
Batch Norm [2]
各層への入力はその前の入力に依存しているため、その入力のばらつきに偏りがある場合、層が深くなると小さな誤差が積み重なっていき目的関数が最小に達しないという問題がある。これを、入力のばらつきを標準化して同じスケールの整えることで、問題解決を図る手法。
(解釈がおかしければご指摘いただければ幸いです。)
実装環境
前回と同様
実験条件
畳み込み層のバイアス有り、無しの二通り。
他、前回と同様。
結果
ネットワークの深さは50層とし、50 epochで確かめた。
実線はバイアスあり、点線はバイアスなしである。精度は式(1)に示す評価データにおける正解率である。
畳み込み層のバイアスの有無で違いは見られなかった。結局バッチノルム層で標準化されるから畳み込み層のバイアスの有無は関係ないのかな。
参考
[1] Why does the resnet model given by pytorch omit biases from the convolutional layer?
Resnetを試してみた
はじめに
ディープラーニングについて学習する上で、Resnet、Resnet-RSを実装して試行毎の損失、正解率を比較してみた。
ColaboratoryでのコードをGithubに載せました。
Resnet: https://github.com/9mao9/Resnet-RS_CIFAR100
Resnet-RS: https://github.com/9mao9/Resnet-RS_CIFAR100
Resnetについて
Resnet [1]
図1に示す残差ブロックの導入により、層を深くすると生じる勾配消失を防ぎ、従来のモデルよりも高い精度を実現した手法。モデルの作成において[2][3]を参考にした。
Resnet-RS [4]
Resnetのネットワーク構造をResnet-D [5]に変更し、SEブロック [6]を追加したモデル。モデルの作成において[7][8]を参考にした。
実装環境
バージョン情報
- torch 1.10.0+cu111
- torchvision 0.11.1+cu111
- numpy 1.19.5
- sklearn 1.0.2
訓練データはCIFAR-100を利用した。
実験条件
両者とも入力サイズ、バッチサイズなどをResnet-RS [4]に準拠。
- 入力サイズ:[3, 160, 160]
- バッチサイズ:128
- 学習率:0.0078125 (Resnetは0.001)
- weight decay:4e-5
- optimizer: SGD (momentum: 0.9)
- transform: RandAugmentation (magnitude: 10)
- Drop out: 0.25 (Resnet-rsのみ)
Resnetの学習率を0.0078125とすると学習が進まなかったため0.001とした。また、ResnetのFC層の前にドロップアウトを追加しても学習が進まなかったため、除外した。
結果
ネットワークの深さは50層とし、論文の通り350 epochも行うと時間がかかりすぎるため、50 epochで確かめた。
精度は式(1)に示す正解率である。ResnetよりもResnet-RSの方が学習が進み、精度も高くなっている傾向がある。SEブロックおよびドロップアウトの影響が大きいと考えられる。
50 epochで精度が収束してるように見えるけど試行回数を増やすとあがるのかな。
参考
[1] K. He, et.al., "Deep Residual Learning for Image Recognition", 2015.
[2] Residual Network(ResNet)の理解とチューニングのベストプラクティス
[4] I. Bello, et.al, "Revisiting ResNets: Improved Training and Scaling Strategies", 2021
[5] T. He, et.al, "Bag of Tricks for Image Classification with Convolutional Neural Networks", 2018
[6] J. Hu, et.al, "Squeeze-and-Excitation Networks", 2017)