← 機械学習テキスト 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:勾配降下法

要点(BLUF)

1. なぜ素のSGDでは不十分か

勾配降下法 の更新 θθηL(θ)\theta \leftarrow \theta - \eta\,\nabla L(\theta) は、損失曲面が「等方的(どの方向も同じ曲率)」なら素直に底へ向かいます。問題は病的な曲率(ill-conditioning)、つまり方向によって曲率が極端に違う細長い谷です。

イメージは、左右の壁が急で前後がゆるやかな峡谷です。勾配は最も急な「壁を登る/降りる方向(左右)」を強く指すので、SGDは谷底に沿って進みたいのに壁を左右にジグザグ反射してしまい、本当に進みたい谷の方向(前後)にはなかなか進みません。

これを定量化するのが 条件数 κ=λmax/λmin\kappa = \lambda_{\max}/\lambda_{\min} です(損失をヘッセ行列 HH で2次近似したときの固有値の最大/最小比)。

L(θ)L(θ)+12(θθ)H(θθ)L(\theta) \approx L(\theta^*) + \tfrac{1}{2}(\theta-\theta^*)^\top H (\theta-\theta^*)

要するに:学習率 η\eta は「最も急な方向で発散しない」上限に縛られるのに、進みたいのは「最もゆるい方向」。κ\kappa が大きい(曲率の差が激しい)ほど、両者の板挟みで収束が遅くなります。素のSGDの最大の弱点はこれです。

graph LR
  SGD["素のSGD(θ ← θ − η∇L)"]
  MOM["モーメンタム(速度で慣性)"]
  NAG["Nesterov(先読み勾配)"]
  ADAG["AdaGrad(座標ごと適応)"]
  RMS["RMSProp(指数移動平均で枯れ回避)"]
  ADAM["Adam(モーメンタム+RMSProp+バイアス補正)"]
  ADAMW["AdamW(重み減衰を切り離し)"]

  SGD --> MOM
  MOM --> NAG
  SGD --> ADAG
  ADAG --> RMS
  MOM --> ADAM
  RMS --> ADAM
  ADAM --> ADAMW

ここから「振動を抑える方向(モーメンタム系)」と「座標ごとに学習率を変える方向(適応系)」の2系統に分かれ、最終的に Adam で合流します。

2. モーメンタム(Momentum)

過去の勾配を蓄えた速度 vtv_t を導入し、それで更新します:

vt=βvt1+L(θt1),θt=θt1ηvtv_t = \beta\, v_{t-1} + \nabla L(\theta_{t-1}), \qquad \theta_t = \theta_{t-1} - \eta\, v_t

β[0,1)\beta \in [0,1) はモーメンタム係数(典型的に 0.90.9)。v0=0v_0 = 0 から始めます。

漸化式を展開すると、速度は**過去の勾配の指数移動平均(EMA)**だとわかります:

vt=k=0t1βkL(θt1k)v_t = \sum_{k=0}^{t-1} \beta^{k}\, \nabla L(\theta_{t-1-k})

古い勾配ほど βk\beta^k で軽く重み付けされます。要するに:「これまで進んできた方向」をボールの慣性のように引き継ぎます。

なぜ振動が消えるのかが本質です。谷の壁方向では、勾配が一歩ごとに符号反転(右→左→右…)するので、和を取ると正負が打ち消し合って速度が小さくなります。逆に谷底方向では勾配が毎回同じ符号なので足し合わさって速度が育ちます。結果、ジグザグは抑制され、進みたい方向は加速されます。

実効ステップの上限も直観的です。同符号の勾配 gg が続くと速度は等比級数で

v=g1βv_\infty = \frac{g}{1-\beta}

に収束します。β=0.9\beta=0.9 なら 110.9=10\tfrac{1}{1-0.9}=10、つまり実質10倍の歩幅でゆるい方向を進めるイメージです。

β\beta が大きいほど加速は強いが慣性で行き過ぎ(オーバーシュート)やすい。β=0\beta=0 で素のSGDに戻ります。

3. Nesterov加速勾配(NAG)

モーメンタムの改良で、勾配を「先読み位置」で評価します。

通常のモーメンタムは「今いる場所 θt1\theta_{t-1}」で勾配を測ってから速度を足します。Nesterov は「速度の分だけ先に進んだ場所 θt1ηβvt1\theta_{t-1} - \eta\beta\, v_{t-1}」で勾配を測ります:

vt=βvt1+L(θt1ηβvt1),θt=θt1ηvtv_t = \beta\, v_{t-1} + \nabla L\big(\theta_{t-1} - \eta\,\beta\, v_{t-1}\big), \qquad \theta_t = \theta_{t-1} - \eta\, v_t

要するに:「どうせ慣性でそこまで進むのだから、進んだ先で勾配を測ろう」という先読み(lookahead)です。

利点はブレーキの早さです。谷底に近づいて行き過ぎそうなとき、通常モーメンタムは現在地で勾配を測るので反応が一歩遅れますが、Nesterov は「進んだ先」で坂の登り返しを先に感じ取り、早めに減速します。理論的にも、滑らかな凸関数で素の勾配法の収束レート O(1/t)O(1/t)O(1/t2)O(1/t^2) に改善する加速法として知られます(ただし確率的・非凸な深層学習で常に効くとは限らない)。

4. AdaGrad

ここから「座標ごとに学習率を変える」適応系です。AdaGrad は各パラメータごとに、過去の勾配の二乗を累積し、その平方根で学習率を割ります。

座標 ii について、勾配を gt,i=[L(θt1)]ig_{t,i} = [\nabla L(\theta_{t-1})]_i とすると:

Gt,i=Gt1,i+gt,i2,θt,i=θt1,iηGt,i+ϵgt,iG_{t,i} = G_{t-1,i} + g_{t,i}^2, \qquad \theta_{t,i} = \theta_{t-1,i} - \frac{\eta}{\sqrt{G_{t,i}} + \epsilon}\, g_{t,i}

ϵ\epsilon10810^{-8} 程度)はゼロ割防止。Gt,iG_{t,i} は座標ごとに別々に貯まります。

要するに:「これまでよく動いた(勾配が大きかった)方向は学習率を下げ、あまり動いていない方向は学習率を保つ」。これにより座標ごとに歩幅を自動調整し、ill-conditioning にも素のSGDより強くなります。

最大の長所は疎な特徴に強いこと。NLP のように、ほとんどゼロでたまにしか出ない特徴(レア単語)は Gt,iG_{t,i} がなかなか増えないので学習率が高く保たれ、出現したときにしっかり学習できます。頻出特徴は逆に抑えられます。

⚠️ ただし致命的な弱点があります。Gt,iG_{t,i}二乗和なので単調増加し、決して減りません。学習が進むほど分母 Gt,i\sqrt{G_{t,i}} が膨らみ続け、実効学習率がゼロへ向かって枯れる(学習が止まる)。深層学習のように長く回す問題では、底に着く前に動けなくなります。

5. RMSProp

AdaGrad の「枯れ」を、累積を指数移動平均(EMA)に変えるだけで解決します。和ではなく「直近の勾配二乗の平均」にします:

vt,i=ρvt1,i+(1ρ)gt,i2,θt,i=θt1,iηvt,i+ϵgt,iv_{t,i} = \rho\, v_{t-1,i} + (1-\rho)\, g_{t,i}^2, \qquad \theta_{t,i} = \theta_{t-1,i} - \frac{\eta}{\sqrt{v_{t,i}} + \epsilon}\, g_{t,i}

ρ\rho(典型的に 0.90.90.990.99)は減衰率。

要するに:AdaGrad が「学習開始からの全履歴」を貯めるのに対し、RMSProp は「最近どれくらい勾配が大きいか」だけを見ます。古い情報を ρ\rho で忘れていくので vt,iv_{t,i} は青天井に増えず、実効学習率が枯れません。曲率が変化する非定常な損失曲面(深層学習はまさにこれ)に適応し続けられます。

6. Adam(Adaptive Moment Estimation)

モーメンタム(1次モーメント)と RMSProp(2次モーメント)の合体に、後述のバイアス補正を加えたものです。現在の深層学習で最も使われるデフォルト。

2つのEMAを座標ごとに持ちます。mtm_t は勾配そのものの平均(向き=モーメンタム)、vtv_t は勾配二乗の平均(スケール=RMSProp):

mt=β1mt1+(1β1)gt,vt=β2vt1+(1β2)gt2m_t = \beta_1\, m_{t-1} + (1-\beta_1)\, g_t, \qquad v_t = \beta_2\, v_{t-1} + (1-\beta_2)\, g_t^2

ここで gt2g_t^2 は要素ごとの二乗。デフォルトは β1=0.9, β2=0.999, ϵ=108\beta_1=0.9,\ \beta_2=0.999,\ \epsilon=10^{-8}、学習率 η=0.001\eta=0.001 前後です。

バイアス補正

m0=v0=0m_0=v_0=0 から始めるため、学習初期の mt,vtm_t, v_t はゼロ側に偏ります(まだ履歴が貯まっていないので過小評価)。これを補正します:

m^t=mt1β1t,v^t=vt1β2t\hat m_t = \frac{m_t}{1-\beta_1^{\,t}}, \qquad \hat v_t = \frac{v_t}{1-\beta_2^{\,t}}

なぜ (1βt)(1-\beta^t) で割るのかを導出で示します。勾配が定常(期待値 E[g]\mathbb{E}[g] が一定)と仮定し、vtv_t を展開すると:

vt=(1β2)k=1tβ2tkgk2v_t = (1-\beta_2)\sum_{k=1}^{t} \beta_2^{\,t-k}\, g_k^2

両辺の期待値を取り、E[gk2]E[gt2]\mathbb{E}[g_k^2]\approx\mathbb{E}[g_t^2] を係数の外に出すと、等比和 k=1tβ2tk=1β2t1β2\sum_{k=1}^{t}\beta_2^{t-k}=\dfrac{1-\beta_2^{t}}{1-\beta_2} より:

E[vt]E[gt2](1β2t)\mathbb{E}[v_t] \approx \mathbb{E}[g_t^2]\,(1-\beta_2^{\,t})

つまり vtv_t は真の2次モーメントを (1β2t)(1-\beta_2^t) 倍に過小評価しています。だから (1β2t)(1-\beta_2^t) で割れば不偏に戻ります。m^t\hat m_t も同様です。

要するに:「履歴がまだ薄い初期だけ、薄まった分を割り戻して水増しする」補正です。tt が大きくなると βt0\beta^t\to 0 なので (1βt)1(1-\beta^t)\to 1、補正は自然に消えます。これが無いと初手の更新が極端に小さくなり、立ち上がりが遅れます。

Adam の更新式

補正済みモーメントで更新します:

 θt=θt1ηm^tv^t+ϵ \boxed{\ \theta_t = \theta_{t-1} - \eta\,\frac{\hat m_t}{\sqrt{\hat v_t} + \epsilon}\ }

分子 m^t\hat m_t が「どっちへ進むか(モーメンタムで均された向き)」、分母 v^t\sqrt{\hat v_t} が「どれくらいの歩幅か(座標ごとのスケール調整)」。向きと歩幅を別々に、座標ごとに自動制御するのが Adam の正体です。m^t/v^t\hat m_t/\sqrt{\hat v_t} は次元的に無次元に近く、初期の実効ステップが概ね η\eta のオーダーに収まる設計です。

7. 使い分けと AdamW(要最新確認)

手法強み弱み・注意
SGD + Momentum谷の振動を抑え加速、汎化が良いことが多い学習率の手調整が要る
AdaGrad疎な特徴に強い学習率が枯れる(長期学習に不向き)
RMSProp枯れない適応学習率、RNN等で安定モーメンタム成分が無い
Adam立ち上がりが速くチューニングが楽、デフォルト画像分類などで汎化がSGDに劣る報告
AdamWAdam の汎化問題を緩和、Transformer系の標準weight decay の値は別途調整

実務の目安:迷ったら Adam(W) で素早く立ち上げ、最終的な汎化を詰めたい画像分類などでは SGD + Momentum をよくチューニングする、という使い分けが定石です。実際、Adam で得た解はSGDより平坦でない(sharpな)極小に落ちやすく、これが汎化差の一因と説明されます(局所幾何の議論で、結論は問題依存・要最新確認)。

L2正則化 と AdamW の違い

これが Adam で特に間違えやすい点です。SGD では「損失にL2ペナルティを足す」ことと「更新時に係数を一定割合で縮める(weight decay)」は数学的に等価ですが、Adam では等価になりません

理由は Adam が勾配を v^t\sqrt{\hat v_t} で割るからです。L2ペナルティ由来の項 λθ\lambda\theta を勾配に混ぜ込むと、それも一緒に v^t\sqrt{\hat v_t} で割られてしまい、正則化の強さが座標ごとにバラバラになります。具体的には、勾配が小さい(=あまり更新されない)座標ほど分母が小さく \to 本来は強く効かせたいのに正則化が弱まる、という逆効果が起きます。weight decay は本来「全パラメータに一律に効く縮小」のはずなのに、その一律性が壊れます。

AdamW(Loshchilov & Hutter, 2017)はこれを解決します。weight decay を勾配から切り離し、適応スケールを通さずパラメータへ直接かけます:

θt=θt1η(m^tv^t+ϵ  +  λθt1)\theta_t = \theta_{t-1} - \eta\left(\frac{\hat m_t}{\sqrt{\hat v_t}+\epsilon}\;+\;\lambda\,\theta_{t-1}\right)

第2項 λθt1\lambda\theta_{t-1}v^t\sqrt{\hat v_t} を通っていないのがポイントです。これで縮小が全パラメータに一律にかかり、学習率と weight decay のチューニングも分離しやすくなります。要するに:「Adam で正則化したいなら、ペナルティを勾配に混ぜず、別ルートで一律に縮める」。Transformer・大規模モデルでは AdamW が事実上の標準です(実装・既定値はフレームワークで差があるため要最新確認)。

⚠️ よくある誤解・落とし穴

対応するシミュレーション

simulations/optimizer_comparison.py:細長い谷(悪条件)の二次関数で SGD・Momentum・RMSProp・Adam を手実装して比較します。素の SGD が急な方向にジグザグして遅いのに対し、Momentum は慣性で加速し、RMSProp は方向ごとに歩幅を調整し、Adam は両者の良いとこ取りで最も速く安定して収束することを、更新の軌跡と損失曲線(対数軸)で確認できます。

SGD・Momentum・RMSProp・Adam の収束比較

関連ノート


Sources(DeepResearchで参照):