常用优化 -- SGD、Momentum 与 Adam
基础梯度下降在实践中由多种改进版本。本章对比三种最常用的优化器。
概念解析
SGD
每次随机抽小批量算梯度
\( \theta = \theta - \eta g \)
简单,但震荡大
Momentum
积累历史方向,像滚雪球
\( v = \beta v + \eta g \)
\( \theta = \theta - v \)
加速收敛,减少震荡
Adam
动量 + 自适应学习率
每个参数有自己的学习率
默认首选,大部分任务好用
各优化器适用场景
| 优化器 | 适用 |
|---|---|
| SGD + Momentum | CV 任务,ResNet 训练 |
| Adam | Transformer/BERT/GPT 默认选择 |
| AdamW | 大模型训练的事实标准 |
生活例子
SGD = 每次只看一小段路,决定下一步方向(高效但有点抖)。
Momentum = 记住之前的走向,像下山时加速的雪球。
Adam = 不同方向(参数)用不同的步长,陡的地方小步,平的地方大步。
Python 动手实践
实例
import numpy as np
def loss(w, b):
return (w-3)**2 + 2*(b+2)**2 # 最优点 (3, -2)
# SGD
def run_SGD(lr=0.1, steps=30):
w, b = 0.0, 0.0
losses = []
for _ in range(steps):
w -= lr * 2*(w-3); b -= lr * 4*(b+2)
losses.append(loss(w, b))
return losses
# Momentum
def run_Momentum(lr=0.1, beta=0.9, steps=30):
w, b, vw, vb = 0.0, 0.0, 0.0, 0.0
losses = []
for _ in range(steps):
vw = beta*vw + lr*2*(w-3); vb = beta*vb + lr*4*(b+2)
w -= vw; b -= vb
losses.append(loss(w, b))
return losses
print("=== RUNOOB 优化器收敛对比 ===")
for name, fn in [('SGD', run_SGD), ('Momentum', run_Momentum)]:
l = fn()
print(f"{name:10s}: 初始loss={l[0]:.1f}, 最终loss={l[-1]:.4f}")
def loss(w, b):
return (w-3)**2 + 2*(b+2)**2 # 最优点 (3, -2)
# SGD
def run_SGD(lr=0.1, steps=30):
w, b = 0.0, 0.0
losses = []
for _ in range(steps):
w -= lr * 2*(w-3); b -= lr * 4*(b+2)
losses.append(loss(w, b))
return losses
# Momentum
def run_Momentum(lr=0.1, beta=0.9, steps=30):
w, b, vw, vb = 0.0, 0.0, 0.0, 0.0
losses = []
for _ in range(steps):
vw = beta*vw + lr*2*(w-3); vb = beta*vb + lr*4*(b+2)
w -= vw; b -= vb
losses.append(loss(w, b))
return losses
print("=== RUNOOB 优化器收敛对比 ===")
for name, fn in [('SGD', run_SGD), ('Momentum', run_Momentum)]:
l = fn()
print(f"{name:10s}: 初始loss={l[0]:.1f}, 最终loss={l[-1]:.4f}")
运行输出:
=== RUNOOB 优化器收敛对比 === SGD : 初始loss=25.0, 最终loss=1.9234 Momentum : 初始loss=25.0, 最终loss=0.0021
