SGD・Momentum・RMSprop・Adamを同じ谷で競走させてみた。Adamが一番強いというのは本当か
約9分で読めます

SGD・Momentum・RMSprop・Adamを同じ谷で競走させてみた。Adamが一番強いというのは本当か


ニューラルネットワークの学習では「とりあえずAdamを使っておけばいい」という話をよく聞く。実際、多くのフレームワークでもAdamがデフォルトの最適化アルゴリズムになっていることが多い。ただ、SGD・Momentum・RMSprop・Adamがそれぞれ何をしているのか、数式は知っていても、実際の挙動の違いを自分の目で見たことはなかった。

そこで、最適化アルゴリズムの難しさを試すために昔からよく使われるRosenbrock関数という「谷」の上で、この4つを同じ条件で競走させてみた。

Rosenbrock関数という意地悪な谷

f(x,y)=(1x)2+100(yx2)2f(x, y) = (1 - x)^2 + 100 (y - x^2)^2

この関数は、(1,1)(1, 1) に唯一の最小値を持つが、そこに至るまでが細長く湾曲したバナナ型の谷になっている。谷の壁は急峻なのに、谷底に沿った方向の勾配はとても緩やか。「どちらの方向にどれだけ進むべきか」の見積もりを誤りやすい、最適化アルゴリズムの試金石としてよく使われる関数だ。

同じ開始地点 (1.5,2.5)(-1.5, 2.5) から、学習率などのハイパーパラメータだけをそれぞれの手法に合わせてある程度チューニングしたうえで、800ステップ競走させた。

def grad(x, y):
    dx = -2 * (1 - x) - 400 * x * (y - x ** 2)
    dy = 200 * (y - x ** 2)
    return np.array([dx, dy])

def run_momentum(lr=0.0011, beta=0.9):
    p = start.copy(); v = np.zeros(2)
    for _ in range(n_steps):
        g = grad(*p)
        v = beta * v + g        # 勾配を「速度」として蓄積する
        p = p - lr * v
    ...

def run_adam(lr=0.05, b1=0.9, b2=0.999, eps=1e-8):
    p = start.copy(); m = np.zeros(2); v = np.zeros(2)
    for t in range(1, n_steps + 1):
        g = grad(*p)
        m = b1 * m + (1 - b1) * g          # 勾配の移動平均(向き)
        v = b2 * v + (1 - b2) * g ** 2      # 勾配2乗の移動平均(大きさ)
        p = p - lr * (m / (1 - b1**t)) / (np.sqrt(v / (1 - b2**t)) + eps)
    ...

結果1: 800ステップ後、どこまで辿り着けたか

start=[-1.5  2.5], target=[1. 1.], steps=800

SGD        final=(-0.78,+0.62)  dist_to_min=1.8208  final_loss=3.174918  到達せず
Momentum   final=(+0.99,+0.97)  dist_to_min=0.0314  final_loss=0.000199  701ステップ目に到達
RMSprop    final=(+0.66,+0.45)  dist_to_min=0.6452  final_loss=0.167762  到達せず
Adam       final=(+0.93,+0.87)  dist_to_min=0.1484  final_loss=0.004646  到達せず

800ステップという同じ予算の中で、目的地(距離0.05以内)にたどり着けたのはMomentumだけだった。「Adamが一番強い」というよくある印象とは違う結果になったので、経路を3Dで可視化してみた。

Rosenbrock関数の谷を4つの最適化アルゴリズムが降りていく3D可視化。灰色の曲面が損失地形(対数スケール)で、谷の入口付近に灰色(SGD)のジグザグした短い軌跡が密集しており、そこから青(Momentum)・赤(Adam)・緑(RMSprop)の順に谷底へ長く伸びる軌跡が描かれている。青が最も奥、星印の最小値の近くまで到達している

灰色のSGDだけが、谷の入口付近でジグザグした短い軌跡のまま止まっているのが一目で分かる。マウスでドラッグして色々な角度から見られるインタラクティブ版も置いておく。

結果2: 等高線の上でのレース

3D曲面だと奥行きで経路が重なって見づらい部分もあるので、真上から見た等高線図の上で、実際に4つの点が動いていく様子をアニメーションにした。

Rosenbrock関数の等高線図の上で、SGD(灰)・Momentum(青)・RMSprop(緑)・Adam(赤)の4点が同時にスタート地点から動いていくレースのアニメーション。SGDはスタート地点付近で細かく振動して先に進まず、Momentumが最も早く谷に沿って最小値まで到達し、Adamがそれに続き、RMSpropはゆっくりと進む

SGD(灰)は、スタート地点のすぐ近くで小刻みに振動し続けるだけで、ほとんど前に進めていない。 谷の壁が急なせいで少し進むたびに勾配の向きが大きく変わり、同じ学習率のままだと壁を挟んで行ったり来たりを繰り返してしまう。壁を乗り越えて壊れないように学習率を小さく抑えた結果、谷底方向への前進もほとんど止まってしまっている。一方Momentum(青)は、序盤にある程度の速度(勢い)を蓄積したあと、その勢いのおかげで谷に沿ってスムーズに滑るように進んでいく。

結果3: 損失の下がり方を数値で比較する

イテレーション   SGD      Momentum   RMSprop   Adam
     0          156.25     156.25     156.25    156.25
   100            4.66       2.60       6.29      4.63
   300            3.85       0.020      5.44      0.75
   500            3.35       0.0011     3.32      0.081
   800            3.17       0.0002     0.168     0.0046

損失(縦軸、対数スケール)がイテレーションとともにどう下がっていくかを示す折れ線グラフ。SGD(灰)は序盤で急上昇したあとほぼ横ばいで下げ止まる。Momentum(青)は序盤で沈んだあと最も急な傾きで下がり続け、最終的に他を大きく引き離す。Adam(赤)はなだらかに下がり続けるがMomentumには及ばない。RMSprop(緑)はしばらく横ばいのあと600ステップ付近で階段状に急落する

この対数グラフが今回一番面白かった部分だ。SGDは最初のスパイクのあとほぼ横ばいになってしまう。RMSprop(緑)は600ステップ付近まで停滞したあと、階段状にストンと落ちている場面があり、蓄積した勾配2乗の移動平均がある時点で急に効き始めるような、非線形な挙動が見える。Momentum(青)は終始一貫して最も急な傾きを保ち、最終的に他の3つを1〜4桁差で引き離した。

Adamが常に最強、ではなかった

正直、実験前は「Adamが一番速く収束するんだろう」と予想していた。実際には、このRosenbrock谷・この予算(800ステップ)・このハイパーパラメータの組み合わせでは、シンプルなMomentumが一番早く目的地に到達した。調べてみると、これは知られている話で、Adamのような適応的な学習率は「汎用的に扱いやすい」という利点はあるものの、特定の地形やタスクでは、素直なMomentumやSGDの方が最終的な収束の質で上回ることがあるらしい。「Adamにしておけば安心」という判断は、少なくとも万能ではない。

これは物事への取り組み方にも通じる話だと思った。SGDのように、目の前の情報だけを頼りに細かく方向修正を繰り返すやり方は、地形が入り組んでいると同じ場所で足踏みし続けてしまう。逆にMomentumのように、直近の勢い(それまでの積み重ね)を活かして進む方が、多少ノイズがあっても大きな流れに逆らわず前進し続けられる。Adamのように状況に応じて細かく調整する賢さは、多くの場面で便利ではあるものの、それが常に一番良い結果を生むとは限らない。慎重な調整より、勢いに乗って押し切る方が結果的に速いことも、実際にはある。

まとめ

  • Rosenbrock関数という「谷底の勾配は緩やか、壁は急峻」な意地悪な地形の上で、SGD・Momentum・RMSprop・Adamを同じ開始地点から800ステップ競走させた
  • SGDは壁のあいだで小刻みに振動するだけでほとんど前進できず、800ステップ後も損失3.17と目的地から大きく取り残された
  • 一番早く目的地(距離0.05以内)に到達したのはMomentumで、701ステップ目に到達。最終損失も0.0002と他を1〜4桁引き離した
  • Adam(0.0046)・RMSprop(0.168)はMomentumほど収束しきらず、「Adamが常に最強」というよくある印象は、少なくともこの実験条件では成り立たなかった
  • RMSpropの損失曲線には600ステップ付近で階段状に急落する非線形な挙動が見られ、蓄積された勾配2乗の移動平均がある時点から急に効き始めるような振る舞いが確認できた