深度学习Day05 梯度下降优化
基础梯度下降算法(Gradient Descent, GD)的核心思想:
通过计算损失函数 $J(\theta)$ 关于模型参数 $\theta$ 的梯度 $\nabla_{\theta} J(\theta)$,并沿着梯度的反方向更新参数 $\theta \leftarrow \theta - \eta \cdot \nabla_{\theta} J(\theta)$(其中 $\eta$ 是学习率),以逐步逼近损失函数的最小值点,从而优化模型性能。
然而,在实际应用中,基础的梯度下降算法(尤其是批量梯度下降)常常面临收敛速度慢、易陷入局部极小点、对学习率选择敏感等问题,尤其是在处理大规模数据集或复杂模型时。
为了克服这些挑战,研究者们提出了多种改进的梯度下降算法,统称为梯度下降优化算法,常见的梯度下降优化算法有Momentum、Adagrad、RMSprop、Adam等方法。
下面选择用同一个一维二次函数(如下)作为损失函数,来对比 不同梯度下降优化算法对参数更新的影响。
$$ L(w) = \frac{1}{2}w^2 $$
-
梯度 = w
-
当前 w 越大,梯度越大
一、Momentum(动量法):优化“梯度方向”
将 Momentum 之前,先介绍一下SGD(随机梯度下降)。
SGD解决的是最基础的优化问题:
沿着损失函数下降最快的方向,不断更新参数
SGD 的核心思想是每一步都只做一件事:
$$ w_{t+1} = w_t - \eta \nabla L(w_t) $$
当前梯度指向哪里,就往哪里走
学习率 $\eta$ 决定步子有多大
SGD 优缺点
优点
思想极其简单
计算开销小,易于分析
缺点
在“峡谷型”或“鞍点”区域容易左右震荡
收敛速度慢
对学习率非常敏感
SGD 可以直观类比为蒙着眼睛下山:只看脚下坡度,每一步都重新判断,没有“惯性”。
为了解决SGD带来的“梯度方向来回变化”、“参数更新不够平滑”等问题,引入了Momentum。
Momentum 核心思想
不仅看当前梯度,还考虑历史梯度的“惯性”
引入一个“速度”变量:
$$
\begin{aligned}
v_t &= \beta v_{t-1} + \nabla L(w_t) \\
w_{t+1} &= w_t - \eta v_t
\end{aligned}
$$
Momentum 优缺点
优点
减少震荡
在一致方向上加速收敛
对鞍点更友好
缺点
学习率仍然是固定的
超参数(momentum)需要调
Momentum 直观类比推着一个有惯性的球下山:坡度方向一致时,球会越滚越快;小的反向坡度,不容易立刻改变方向。
def momentum_demo():
# 初始化权重值
w = torch.tensor([1.0],requires_grad=True,dtype=torch.float32)
# 自定义损失函数
criterion = (w**2)/2
# 创建优化器对象,作用:1- 计算梯度;2- 自动更新权重
# 创建随机梯度下降优化器,用于更新模型参数
# 参数说明:
# [w] - 需要优化的参数列表,这里是对变量w进行优化
# lr=0.1 - 学习率,控制参数更新的步长大小
# momentum=0.9 - 动量参数,用于加速收敛并减少震荡
optimizer = torch.optim.SGD([w],lr=0.1,momentum=0.9)
# 反向传播计算梯度
# 梯度清零
optimizer.zero_grad()
# 反向传播
criterion.sum().backward()
# 更新权重
optimizer.step()
print(f"第1次,梯度的结果{w.grad},更新后的w权重值{w.detach()}")
print(f"第一次criterion值为{criterion.sum().detach()}")
# 第二次
criterion = (w ** 2) / 2
# 反向传播计算梯度
# 梯度清零
optimizer.zero_grad()
# 反向传播
criterion.sum().backward()
# 更新权重
optimizer.step()
print(f"第2次,梯度的结果{w.grad},更新后的w权重值{w.detach()}")
print(f"第二次criterion值为{criterion.sum().detach()}")
对应优化器为:
optimizer = torch.optim.SGD([w], lr=0.1, momentum=0.9)
1)
[w]:要被优化/更新的参数列表
这里传的是一个 list:[w]
含义:告诉优化器“我只更新这个张量 w”
重要前提:w 必须 requires_grad=True,这样 backward() 才会把梯度写到 w.grad 里,然后 optimizer.step() 才能更新它。
在这个 demo 里只有一个标量参数w,所以用 [w] 很直观;真实模型里通常model.parameters()。
2)
lr=0.1:学习率(步长)3) momentum=0.9:动量系数(“惯性”有多强)
动量系数就是上面公式里的$\beta$
输出如下:
第1次,梯度的结果tensor([1.]),更新后的w权重值tensor([0.9000])
第一次criterion值为0.5
第2次,梯度的结果tensor([0.9000]),更新后的w权重值tensor([0.7200])
第二次criterion值为0.4049999713897705
二、Adagrad:只优化学习率
Adagrad 核心思想
对“频繁出现的大梯度”自动降低学习率
它会给每个参数一个自己的有效学习率(会随训练变化):
$$\theta_{t+1, i} = \theta_{t, i} - \frac{\eta}{\sqrt{G_{t, i} + \epsilon}} g_{t, i}$$
其中 $$G_{t, i} = \sum_{k=1}^{t} g_{k, i}^2$$
关键点:
Adagrad 不改变梯度 $$g_t$$ 本身(不像 Momentum 会引入速度 vvv 去平滑方向)
它改变的是前面的系数:η/G+ϵ\eta / \sqrt{G+\epsilon}η/G+ϵ
也就是“走多大步”这件事(学习率/步长)
所以说“只优化学习率”更准确的表述是:
只在“步长策略”上做自适应,不在“方向/动量”上做改造。
Adagrad 优缺点
优点
自动调节学习率
对稀疏特征非常友好
前期下降很快
缺点
梯度平方是“无限累加”的
学习率后期可能小到几乎不动
Adagrad 可直观类比为常走的路越走越慢,生路走得更快:出现频率高的方向会被“重点刹车”。
对应优化器为:
optimizer = torch.optim.Adagrad([w],lr=0.1)
小总结:
Adagrad 的核心贡献是“按参数自适应学习率”,但它的致命问题是学习率会单调衰减,后期可能衰减到几乎停止学习;RMSprop/Adam 的改进就是想办法避免这种‘越学越慢’。
三、RMSprop
由前面可知Adagrad 的致命问题是:
学习率衰减过头,训练提前停滞
RMSprop 就是解决这个问题的。
RMSprop 核心思想
不累加所有历史梯度,而是关注“最近一段时间”
使用梯度平方的指数移动平均:
$$ E[g^2]_t = \alpha E[g^2]_{t-1} + (1 - \alpha)g_t^2 $$
RMSprop 优缺点
优点
学习率不会无限减小
对非平稳目标函数更稳定
实践效果好
缺点
仍然没有利用梯度方向的“动量”
RMSprop 可以直观类比为 只记住最近的路况,而不是一辈子的历史。
对应优化器为:
optimizer = torch.optim.RMSprop([w],lr=0.1,alpha=0.9)
四、Adam(Adaptive Moment Estimation)
为了能够同时解决震荡问题和学习率自适应问题,Adam 应运而生。
Adam 核心思想:
Adam = Momentum + RMSprop
它在每一步都会维护两个统计量:
一阶矩 $m_t$:梯度的平均(方向)
二阶矩 $v_t$:梯度平方的平均(尺度)
Adam 内部的计算过程:
首先计算当前梯度:
$$ g_t = \nabla_{\theta} J(\theta_t) $$
接着,Adam 会对梯度做指数移动平均:
$$ m_t = \beta_1 m_{t-1} + (1 - \beta_1)g_t $$
$m_t$:梯度的“动量方向”
$\beta_1$:控制历史梯度保留比例,一般取 0.9
✅ 这一步就是动量法:
梯度方向不会剧烈波动,而是更平滑。
同时,Adam 也会对梯度平方做指数平均:
$$ v_t = \beta_2 v_{t-1} + (1 - \beta_2)g_t^2 $$
$v_t$:梯度尺度的估计
$\beta_2$:通常取 0.999 或 0.99
✅ 这一步就是 RMSprop:
梯度大 ⇒ 学习率自动变小
梯度小 ⇒ 学习率相对变大
由于初始时:
$$m_0=0$$
$$v_0=0$$
所以刚开始 $m_t,v_t$ 会偏小。
Adam 进行偏置修正:
$$
\begin{aligned}
\hat{m}_t &= \frac{m_t}{1 - \beta_1^t} \\
\hat{v}_t &= \frac{v_t}{1 - \beta_2^t}
\end{aligned}
$$
偏置修正,让前期更稳定。
Adam 最终的更新是:
$$ \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} $$
其中:
$\eta$:学习率
$\epsilon$:防止除零(通常 $10^{-8}$ )
Adam 优缺点
优点
收敛快
对超参数不敏感
工程中表现稳定
适合大多数深度学习任务
缺点
理论收敛性曾有争议
有时泛化不如 SGD + Momentum
Adam 可以直观类比为 又有方向感,又能自动调节步长的智能下山者。
对应优化器为:
optimizer = torch.optim.Adam([w],lr=0.1,betas=(0.9,0.99))
五、总结
| 优化器 | 优化对象 | 核心优势 | 主要问题 |
|---|---|---|---|
| SGD | 梯度 | 简单直观 | 收敛慢、震荡 |
| Momentum | 梯度方向 | 加速、平滑 | 学习率固定 |
| Adagrad | 学习率 | 稀疏友好 | 学习率衰减过快 |
| RMSprop | 学习率 | 更稳定 | 无动量 |
| Adam | 梯度 + 学习率 | 快且稳 | 理论收敛性争议 |
优化器的本质不是“谁更高级”,而是它们在不同场景下,对梯度信息的使用方式不同。
更多推荐
所有评论(0)