Optimization Algorithm
最適化アルゴリズムは、学習中に損失を最小化するため、モデルの重みを更新します。勾配降下法、モーメンタム、Adam、AdamW、Muon、コードを解説します。
最適化アルゴリズム(オプティマイザー)とは、損失関数が減少するよう、学習プロセスがモデルのパラメーターを変更するための規則です。ディープラーニングでは、オプティマイザーは誤差逆伝播から、すべてのモデルの重みに対する損失の勾配を受け取り、それぞれをどれだけ、どの方向に動かすかを決定します。オプティマイザーは学習率とともに、学習の収束速度と安定性、必要なメモリ量、そして多くの場合、最終モデルの汎化性能を決定します。
オプティマイザーの仕組み#
ほぼすべてのディープラーニングオプティマイザーは勾配降下法の変種です。ミニバッチ上の損失の勾配gを計算し、重みをその逆方向に小さく移動させます(w ← w − η·g)。オプティマイザーによって、更新前にgをどのように処理するかが異なります。モメンタム法は勾配を時間方向に平均し、一貫している方向への速度を高めます。適応型手法は、勾配の大きさの移動平均で各パラメーターのステップ幅を割ります。Muonは各重み行列全体の更新を直交化します。2次手法は曲率も使用するため、各ステップの判断精度が上がりますが、計算コストが大幅に増えます。勾配を一切必要としない進化的アルゴリズムやランダムサーチなどの手法は、候補を試して最良のものを選ぶことで最適化します。
損失曲面の条件が悪く、ある方向では急峻に、別の方向では緩やかに湾曲している場合に、更新規則が特に重要になります。同じ開始点から狭い谷で3つのオプティマイザーを実行すると、その違いが分かります。
import torch
# A long, narrow valley: f(w) = w1^2 + 50 * w2^2, with its minimum at (0, 0)
scale = torch.tensor([1.0, 50.0])
optimizers = {
"SGD": lambda p: torch.optim.SGD(p, lr=0.015),
"SGD + momentum": lambda p: torch.optim.SGD(p, lr=0.015, momentum=0.9),
"Adam": lambda p: torch.optim.Adam(p, lr=0.1),
}
for name, make_optimizer in optimizers.items():
w = torch.tensor([5.0, 1.0], requires_grad=True)
optimizer = make_optimizer([w])
# Same loss and starting point for every optimizer; only the update rule differs
for step in range(100):
loss = (scale * w**2).sum()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"{name:15s} f(w) after 100 steps: {(scale * w**2).sum().item():.6f}")通常のSGDは0.056531で停止します。急峻なw2方向が学習率の上限を決めるためです。0.02を超える学習率では、ステップごとにw2のオーバーシュートが大きくなり、0.021では100ステップ以内に損失が約95億まで上昇します。この上限のもとでは、緩やかなw1方向への進みが遅くなります。モメンタムはw1方向の速度を高めて0.000216に到達し、Adamは座標ごとに異なるステップ幅を与えて0.001953に到達します。
代表的な最適化アルゴリズム#
- 確率的勾配降下法(SGD):ミニバッチの勾配と逆方向に更新します。モメンタム0.9を使い、多くの代表的な畳み込みネットワークの学習に用いられました。パラメーターごとに追加の値を1つ保存します。
- AdaGradとRMSProp:勾配の二乗の履歴に応じて、各パラメーターのステップ幅を調整します。AdaGradは勾配の二乗の累積和の平方根で割ります。この累積和は増加し続けるため、学習中にステップ幅が縮小します。RMSPropは代わりに指数減衰平均を使い、ステップ幅を状況に応じて調整しやすくします。
- Adam:モメンタムとRMSProp型のスケーリングを組み合わせ、どちらの移動平均についても初期値がゼロであることを補正します。学習率0.001、β1 = 0.9、β2 = 0.999というデフォルト値は、多くの問題で有効です。
- AdamW:分離型重み減衰を導入したAdamです。適応型の勾配スケーリングを介さず、重みを直接縮小します。Transformerと大規模言語モデル(LLM)の標準的なオプティマイザーです。
- Muon:Newton–Schulz反復を使って各2D重み行列のモメンタム更新を直交化し、パラメーターごとに状態バッファーを1つだけ保持します。Moonshot AIはLLMの事前学習に適用できる規模まで拡張しました。
- L-BFGS:最近の勾配から曲率の推定値を構築する準Newton法です。滑らかなフルバッチ問題では少ないステップで収束しますが、ノイズの多いミニバッチ勾配を使う大規模ネットワークには適していません。
PyTorchのオプティマイザーパッケージは、torch.optim.Muonを含むこれらすべての手法と、いずれの手法にも対応する学習率スケジューラーを実装しています。
オプティマイザーと関連用語の違い#
- 損失関数: オプティマイザーが最小化する目的関数です。分類では交差エントロピー、回帰では平均二乗誤差などが使われます。
- 学習率スケジューラー: ウォームアップ、ステップ減衰、コサインアニーリングなどを使って、オプティマイザーの種類を問わず、学習中にステップ幅ηを調整します。
- ハイパーパラメーター調整:オプティマイザー、学習率、バッチサイズなどの設定を外側から探索します。候補ごとに学習を全体または一部実行する必要があります。検証スコアはオプティマイザーなどの選択肢に対して微分できないため、ベイズ最適化や進化的探索などの勾配不要の手法を使います。
オプティマイザーの選び方#
オプティマイザーと学習率は、各オプティマイザーがそれぞれ異なる範囲で動作するため、組み合わせて選択します。モメンタム付きSGDは通常0.01~0.1、Adam系のオプティマイザーは約0.001から開始します。Ultralytics YOLOの学習では、この選択が自動的に行われます。デフォルトのoptimizer="auto"はlr0を無視し、最大10,000イテレーションの実行ではクラス数に合わせた学習率でAdamWを選びます。それより長いスケジュールでは、リリース済みのYOLO26チェックポイントの学習に使われたSGDとMuonのハイブリッドであるMuSGDを選びます。一方、オプティマイザー名を指定するとlr0が有効になります。
from ultralytics import YOLO
# 事前学習済みYOLO26nモデルを読み込みます
model = YOLO("yolo26n.pt")
# SGDを明示的に選択します。lr0はoptimizerが"auto"でない場合にのみ適用されます
results = model.train(data="coco8.yaml", epochs=5, optimizer="SGD", lr0=0.01)optimizer="SGD"を使うと、トレーナーはNesterovモメンタムも有効にします。係数にはmomentum引数を使い、デフォルトは0.937です。










