Optimizer(最適化)の種類について
-
Optimizer(最適化)
- 損失関数の最小値(とその時のパラメータ)を求めるアルゴリズム
- パラメータの値を変更して、lossの値を出来る限り小さくする
- Optimizerが使うことのできる情報は、パラメータの勾配とこれまでにパラメータを動かした記録のみ(関数の中身の構造などは見れない)
-
SGD(確率的勾配降下法)
for i in range(steps):
parameter = parameter - lr * grad
パラメータを勾配×学習率だけ減らす。
学習率が小さすぎると学習が全然進まず、大きすぎるとパラメータが最適値を通り過ぎてしまいうまく学習できない
学習率:一度のパラメータの更新でどのぐらい学習を進めるかを調整する
SGDはもっとも簡単で基本的なアルゴリズムで、 これ以降に紹介する最適化アルゴリズムは基本的にこれを改良していったもの
- momentumSGD
v=0 #gradと同じサイズの行列
for i in range(steps):
v = v * momentum - lr * grad
parameter = parameter + v
vは速度を表し、momentumSGDでは、速度を勾配×学習率だけ減らす。
momentumは、速度の減衰であり(摩擦のようなもの)、一定の割合で速度を減らしていきます。
速度の概念を導入することで、
何回も勾配が一定の方向を指す(=最適値はまだ遠い)場合は、パラメータの更新量が大きくなり、
勾配が+になったりーになったりを繰り返す(=最適値付近で行ったり来たりしている)場合は、パラメータの更新量が小さくなるという効果があり、SGDと比較してパラメータの振動が減り学習が速く進みます。
パラメータとロスの関係が複雑な問題では、ロスの小さい点を慣性で生きすぎることによって探索の範囲が広がる→局所最適解に陥りにくくなる
SGDでは勾配が0になってしまい学習が止まってしまう点でも、momentumSGDでは、その点を通り過ぎてさらにlossが小さくなるポイントまで進むことができる。
- AdaGrad
h=0 #gradと同じサイズの行列
for i in range(steps):
h = h + grad * grad
parameter = parameter - lr * grad / (sqrt(h) + epsilon)
パラメータごとに固有の値hを持ち、学習のたびに勾配の2乗ずつ増加していく。
そして、hの平方根でパラメータ更新量を割っているので、hが大きいほどパラメータ更新量は小さくなる。
パラメータが最適値までまだまだ遠い時(学習初期)は大きくパラメータを更新したいが、パラメータが最適値に近づいた時(学習終盤)は最適値を通り過ぎないようにパラメータの更新量を小さくしたい、という意図で学習が進むほど学習率を小さくしていくテクニックがある。
これをパラメータごとに独立して行っているのがAdaGradである。
Adagradでは、今までの更新量の大きいパラメータ(正確には今までの勾配が大きいパラメータ)ほど、更新量が小さくなります。
- Adam
m=0 #gradと同じサイズの行列
v=0 #gradと同じサイズの行列
for i in range(steps):
m = beta_1 * m + (1 - beta_1) * grad
v = beta_2 * v + (1 - beta_2) * grad^2
om = m / (1 - beta_1)
ov = v / (1 - beta_2)
parameter = parameter - lr * om / sqrt(ov + epsilon)
mによってmomentumSGDのようにこれまでの勾配の情報をため込む。
また、vによって勾配の2乗の情報をため込む。
それぞれ指数移動平均で昔の情報は少しずつ影響が小さくなっていく。
mでは勾配の情報をため込む前に、(1 – beta_1)がかけられてしまう(デフォルトパラメータなら0.1倍)
そこで、omでは、mを(1 – beta_1)で割ることで勾配の影響の大きさをもとに戻す。(ovも同様)
最適化アルゴリズムの中でも性能が良いので、まず最初に試す手法として良い。
参考サイト
https://tech-lab.sios.jp/archives/21823画像の出典
[https://www.acceluniverse.com/blog/developers/2019/10/deep-learningparameter-update.html]