动手学深度学习第十一章—————优化算法

11.1优化和深度学习

11.1.1. 优化的目标

尽管优化提供了一种最大限度地减少深度学习损失函数的方法,但本质上,优化和深度学习的目标是根本不同的。前者主要关注的是最小化目标,后者则关注在给定有限数据量的情况下寻找合适的模型。在 4.4节中,我们详细讨论了这两个目标之间的区别。例如,训练误差和泛化误差通常不同:由于优化算法的目标函数通常是基于训练数据集的损失函数,因此优化的目标是减少训练误差。但是,深度学习(或更广义地说,统计推断)的目标是减少泛化误差。为了实现后者,除了使用优化算法来减少训练误差之外,我们还需要注意过拟合。

2.2 高维空间的挑战维度灾难:

高维空间中,参数数量呈指数级增长,优化难度急剧上升;梯度消失 / 爆炸:深层网络中,梯度在反向传播时可能趋近于 0 或无穷大;参数冗余:大量参数高度相关,优化方向易受噪声干扰。

2.3 训练数据的噪声标注误差:

训练数据的标签可能错误,导致损失函数包含噪声;批量采样:随机梯度下降(SGD)使用小批量数据计算梯度,梯度估计存在偏差;过拟合:模型过度拟合训练数据的噪声,泛化能力下降。三、优化算法的核心评价指标

3.1 收敛速度收敛:

优化算法的目标函数值随迭代次数增加逐渐稳定;收敛速度:常用 “迭代次数” 或 “时间” 衡量,如 SGD 收敛慢但内存占用低,Adam 收敛快但计算复杂。

3.2 解的质量优化算法最终找到的解的泛化能力(而非训练误差);

示例:SGD 通常能找到泛化能力更好的解,而批量梯度下降易过拟合。

3.3 计算效率时间复杂度:

每次迭代的计算量(如 Adam 比 SGD 多计算动量和二阶矩);空间复杂度:内存占用(如二阶优化算法需存储海森矩阵,内存消耗大)。四、深度学习优化的核心策略

4.1 梯度下降的变体

  1. 批量梯度下降(BGD)计算全量训练数据的梯度,更新参数:\(\(\theta = \theta - \eta \cdot \nabla_\theta L(\theta; X_{all}, y_{all})\)\)优点:梯度估计准确,收敛稳定;缺点:计算量大,无法处理大数据集,易过拟合。
  2. 随机梯度下降(SGD)计算单个样本的梯度,更新参数:\(\(\theta = \theta - \eta \cdot \nabla_\theta L(\theta; X_i, y_i)\)\)优点:计算快,内存占用低,噪声有助于跳出局部最优;缺点:梯度波动大,收敛慢。
  3. 小批量梯度下降(Mini-batch SGD)计算小批量样本的梯度,平衡 BGD 和 SGD:\(\(\theta = \theta - \eta \cdot \nabla_\theta L(\theta; X_{batch}, y_{batch})\)\)深度学习的默认选择(批量大小通常为 32/64/128)。
    4.2 动量(Momentum)模拟物理中的 “惯性”,加速收敛并减少震荡:\(\(v_t = \gamma v_{t-1} + \eta \nabla_\theta L(\theta)\)\(\theta = \theta - v_t\)\(\gamma\)\) 为动量系数(通常取 0.9),(v_t) 为速度项。
    4.3 自适应学习率AdaGrad:对频繁更新的参数使用小学习率,稀疏参数使用大学习率;RMSProp:解决 AdaGrad 学习率单调下降的问题;Adam:结合动量和 RMSProp,当前最常用的优化器。
    4.4 正则化(平衡优化与泛化)L2 正则化(权重衰减):在损失函数中加入参数的 L2 范数,防止过拟合:\(\(L_{reg} = L + \frac{\lambda}{2} \|\theta\|^2\)\)Dropout:训练时随机丢弃部分神经元,降低参数冗余;早停(Early Stopping):验证集损失不再下降时停止训练,避免过拟合。

代码

%matplotlib inline
import numpy as np
import torch
from mpl_toolkits import mplot3d
from d2l import torch as d2l
def f(x):
    return x * torch.cos(np.pi * x)

def g(x):
    return f(x) + 0.2 * torch.cos(5 * np.pi * x)
def annotate(text, xy, xytext):  #@save
    d2l.plt.gca().annotate(text, xy=xy, xytext=xytext,
                           arrowprops=dict(arrowstyle='->'))

x = torch.arange(0.5, 1.5, 0.01)
d2l.set_figsize((4.5, 2.5))
d2l.plot(x, [f(x), g(x)], 'x', 'risk')
annotate('min of\nempirical risk', (1.0, -1.2), (0.5, -1.1))
annotate('min of risk', (1.1, -1.05), (0.95, -0.5))
x = torch.arange(-1.0, 2.0, 0.01)
d2l.plot(x, [f(x), ], 'x', 'f(x)')
annotate('local minimum', (-0.3, -0.25), (-0.77, -1.0))
annotate('global minimum', (1.1, -0.95), (0.6, 0.8))
x = torch.arange(-2.0, 2.0, 0.01)
d2l.plot(x, [x**3], 'x', 'f(x)')
annotate('saddle point', (0, -0.2), (-0.52, -5.0))
x, y = torch.meshgrid(
    torch.linspace(-1.0, 1.0, 101), torch.linspace(-1.0, 1.0, 101))
z = x**2 - y**2

ax = d2l.plt.figure().add_subplot(111, projection='3d')
ax.plot_wireframe(x, y, z, **{'rstride': 10, 'cstride': 10})
ax.plot([0], [0], [0], 'rx')
ticks = [-1, 0, 1]
d2l.plt.xticks(ticks)
d2l.plt.yticks(ticks)
ax.set_zticks(ticks)
d2l.plt.xlabel('x')
d2l.plt.ylabel('y');
x = torch.arange(-2.0, 5.0, 0.01)
d2l.plot(x, [torch.tanh(x)], 'x', 'f(x)')
annotate('vanishing gradient', (4, 1), (2, 0.0))

11.2凸性

凸性(convexity)在优化算法的设计中起到至关重要的作用, 这主要是由于在这种情况下对算法进行分析和测试要容易。 换言之,如果算法在凸性条件设定下的效果很差, 那通常我们很难在其他条件下看到好的结果。 此外,即使深度学习中的优化问题通常是非凸的, 它们也经常在局部极小值附近表现出一些凸性。 这可能会产生一些像 (Izmailov et al., 2018)这样比较有意思的新优化变体
image

二、凸优化的核心性质(为什么凸性重要?)

凸优化问题的定义:目标函数是凸函数,约束集合是凸集 的优化问题,即:\(\(\min_{x \in S} f(x)\)\)其中 f 是凸函数,S 是凸集。凸优化问题有三个关键性质,使其成为 “易解” 的优化问题:
2.1 局部最优 = 全局最优定理:凸函数的任意局部最小值都是全局最小值。证明思路:假设 \(\(x^*\)\) 是局部最小值但非全局最小值,则存在 \(\(x'\)\) 使得 \(\(f(x') < f(x^*)\)\)。根据凸函数定义,两点连线上的点 (\lambda x^* + (1-\lambda)x') 满足:\(\(f(\lambda x^* + (1-\lambda)x') \leq \lambda f(x^*) + (1-\lambda)f(x') < f(x^*)\)当 \(\lambda\) \)足够接近 1 时,该点在 \(\(x^*\)\) 的邻域内,与 “局部最小值” 矛盾。
2.2 梯度为 0 → 全局最优定理:对于可微的凸函数 f,(\nabla f(x^) = 0) 的充要条件是 (x^) 是全局最小值。这意味着:在凸优化中,只要找到梯度为 0 的点,就一定是全局最优解(无需担心局部最优)。2.3 优化算法收敛到全局最优凸优化问题中,梯度下降等简单算法能保证收敛到全局最优解,且收敛速度可量化(如线性收敛、二次收敛)。三、凸性在深度学习中的应用虽然深度学习的损失函数大多是非凸的,但凸性的思想仍有重要应用:
3.1 基础模型的凸性线性回归:损失函数(MSE)是凸函数,可通过闭式解(正规方程)找到全局最优;逻辑回归:交叉熵损失是凸函数,梯度下降可收敛到全局最优;支持向量机(SVM):目标函数是凸函数,可通过凸优化算法求解。
3.2 非凸优化的 “凸近似”局部凸性:神经网络损失函数在局部区域可能近似凸,梯度下降能找到较好的局部最优;正则化:L2 正则化使损失函数更 “凸”(增加海森矩阵的最小特征值),减少局部最优的数量;批量归一化:使每层的输入分布更稳定,提升局部凸性,加速收敛。
3.3 优化算法的设计凸优化的收敛分析为深度学习优化算法提供理论基础(如 SGD 的收敛速率分析);自适应学习率算法(如 Adam)的设计借鉴了凸优化中的二阶信息(海森矩阵近似)。

代码

%matplotlib inline
import numpy as np
import torch
from mpl_toolkits import mplot3d
from d2l import torch as d2l
f = lambda x: 0.5 * x**2  # 凸函数
g = lambda x: torch.cos(np.pi * x)  # 非凸函数
h = lambda x: torch.exp(0.5 * x)  # 凸函数

x, segment = torch.arange(-2, 2, 0.01), torch.tensor([-1.5, 1])
d2l.use_svg_display()
_, axes = d2l.plt.subplots(1, 3, figsize=(9, 3))
for ax, func in zip(axes, [f, g, h]):
    d2l.plot([x, segment], [func(x), func(segment)], axes=ax)
f = lambda x: (x - 1) ** 2
d2l.set_figsize()
d2l.plot([x, segment], [f(x), f(segment)], 'x', 'f(x)')

小结

在深度学习的背景下,凸函数的主要目的是帮助我们详细了解优化算法。 我们由此得出梯度下降法和随机梯度下降法是如何相应推导出来的。

凸集的交点是凸的,并集不是。

根据詹森不等式,“一个多变量凸函数的总期望值”大于或等于“用每个变量的期望值计算这个函数的总值“。

一个二次可微函数是凸函数,当且仅当其Hessian(二阶导数矩阵)是半正定的。

凸约束可以通过拉格朗日函数来添加。在实践中,只需在目标函数中加上一个惩罚就可以了。

投影映射到凸集中最接近原始点的点。

11.3,11.4,11.5

11.3-11.5 聚焦深度学习优化的核心算法细节,从梯度下降的基础变体、自适应学习率优化器,到梯度消失 / 爆炸的解决方案,层层递进讲解 “如何高效、稳定地优化深度模型”。

11.3 梯度下降(Gradient Descent)

其变体核心是 “如何利用梯度更新参数”,不同变体的核心差异的是梯度计算的样本范围,平衡收敛速度、计算效率和泛化能力。三种核心变体变体类型梯度计算方式核心公式(参数更新:(\theta)为参数,(\eta)为学习率,L为损失)优点缺点批量梯度下降(BGD)全量训练数据$(\theta = \theta - \eta \cdot \nabla_\theta L(\theta; X_{all}, y_{all}))\(梯度估计准确,收敛稳定,无震荡计算量大,无法处理大数据集,内存占用高随机梯度下降(SGD)单个随机样本\$(\theta = \theta - \eta \cdot \nabla_\theta L(\theta; X_i, y_i)\)\)计算快,内存占用低,噪声助于跳出局部最优梯度波动大,收敛慢,易震荡小批量梯度下降(Mini-batch SGD)随机抽取小批量样本(常用 32/64/128)$(\theta = \theta - \eta \cdot \nabla_\theta L(\theta; X_{batch}, y_{batch})$)平衡 BGD 和 SGD,深度学习默认选择需调优批量大小,存在一定梯度噪声关键细节小批量大小选择:过小(如 1)→ 震荡剧烈;过大(如 1024)→ 梯度稳定但泛化能力下降,易过拟合;SGD 的改进:引入动量(Momentum),模拟物理惯性,减少震荡,加速收敛(后续 11.4 展开)。

11.4 动量法(Momentum)与自适应学习率优化器核心是 “解决 SGD 收敛慢、震荡的问题”,通过引入 “惯性” 或 “自适应学习率”,让优化更高效、稳定。

  1. 动量法(Momentum)核心思想:模拟物体运动的惯性,积累之前的梯度方向,减少当前梯度的随机波动。核心公式:速度项(积累梯度):$(v_t = \gamma v_{t-1} + \eta \nabla_\theta L(\theta_t))((\gamma)$为动量系数,常用 0.9)参数更新:(\theta_{t+1} = \theta_t - v_t)优势:在沟壑状损失函数中,沿梯度方向加速,垂直梯度方向减速,减少震荡。
  2. 自适应学习率优化器针对 “不同参数需要不同学习率” 的问题,自动调整每个参数的学习率,无需手动调优。优化器核心思想关键公式适用场景AdaGrad频繁更新的参数用小学习率,稀疏参数用大学习率累计梯度平方:\(\(G_t = G_{t-1} + (\nabla_\theta L)^2\);更新:\(\theta = \theta - \frac{\eta}{\sqrt{G_t + \epsilon}} \nabla_\theta L\)\)稀疏数据(如文本分类)RMSProp解决 AdaGrad 学习率单调下降问题,引入指数移动平均累计梯度平方(指数移动平均):$(E[g^2]t = 0.9 E[g^2] + 0.1 (\nabla_\theta L)^2)\(;更新:\$(\theta = \theta - \frac{\eta}{\sqrt{E[g^2]_t + \epsilon}} \nabla_\theta L\)\)非平稳目标(如深度学习),通用Adam结合动量法和 RMSProp,同时利用一阶矩和二阶矩一阶矩(动量):\(\(m_t = \beta_1 m_{t-1} + (1-\beta_1) \nabla_\theta L\)\);二阶矩:\(\(v_t = \beta_2 v_{t-1} + (1-\beta_2) (\nabla_\theta L)^2\)\);偏差修正后更新参数绝大多数深度学习场景,收敛快且稳定优化器对比总结新手优先用 Adam:无需复杂调优,收敛速度快;追求泛化能力用 SGD+Momentum:噪声有助于泛化,适合最终模型训练;处理稀疏数据用 AdaGrad/RMSProp:自适应学习率适配稀疏参数更新。

11.5

梯度消失、梯度爆炸与参数初始化核心是 “解决深度模型训练中梯度传播不稳定的问题”,包括现象原因、解决方案和关键的参数初始化技巧。

  1. 梯度消失与梯度爆炸的定义梯度消失:深层网络中,梯度反向传播时趋近于 0,导致浅层参数几乎不更新;梯度爆炸:梯度反向传播时趋近于无穷大,导致参数更新幅度过大,模型发散。
  2. 核心原因网络过深:梯度通过矩阵乘法传播,多层乘积导致梯度衰减或放大;激活函数不当:如 Sigmoid 函数的梯度在输入绝对值较大时趋近于 0,多层叠加后梯度消失;参数初始化不当:初始参数过大→梯度爆炸,过小→梯度消失。
  3. 解决方案
    (1)激活函数改进替换 Sigmoid/Tanh:使用 ReLU((f(x)=\max(0,x)))及其变体(Leaky ReLU、ELU),ReLU 梯度在正区间恒为
    1,避免梯度消失;优势:计算简单,缓解梯度消失,加速收敛。
    (2)参数初始化核心原则:让各层输入输出的方差一致,避免梯度传播时衰减 / 放大。Xavier 初始化:适用于 Tanh/Sigmoid 激活函数,初始化参数满足:(W \sim \mathcal{U}[-\frac{\sqrt{6}}{\sqrt{n_{in}+n_{out}}}, \frac{\sqrt{6}}{\sqrt{n_{in}+n_{out}}}])((n_{in})为输入维度,(n_{out})为输出维度);He 初始化:适用于 ReLU 激活函数,初始化参数满足:(W \sim \mathcal{N}(0, \frac{2}{n_{in}})),考虑 ReLU 会丢弃负区间值,放大方差。
    (3)批量归一化(Batch Normalization, BN)核心思想:对每层输入进行归一化(均值为 0、方差为 1),减少梯度传播的不稳定性;操作:(x_{norm} = \frac{x - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}),再通过可学习参数(\gamma)(缩放)和(\beta)(偏移)调整分布;优势:缓解梯度消失 / 爆炸,加速收敛,降低参数初始化敏感度,一定程度防止过拟合。
    (4)其他技巧梯度裁剪(Gradient Clipping):对梯度设置阈值,当梯度 norm 超过阈值时缩放梯度,防止梯度爆炸;简化网络结构:减少网络层数或神经元数量,降低梯度传播难度。
  4. 参数初始化的关键原则避免初始参数过大 / 过小:保证各层输入输出方差一致;适配激活函数:Xavier 对应 Tanh/Sigmoid,He 对应 ReLU;随机初始化:避免所有参数初始值相同,导致对称权重问题(各神经元输出一致,梯度相同,无法学习)。三小节核心逻辑串联深度模型优化的核心矛盾是 “高效收敛” 与 “稳定传播”:
    11.3 提供了梯度更新的基础框架(小批量 SGD);
    11.4 通过动量法和自适应优化器提升收敛效率,解决 SGD 震荡问题;
    11.5 解决深度模型的梯度传播稳定性问题,通过激活函数、参数初始化、批量归一化等保障梯度有效传播,让前两小节的优化算法能在深层网络中生效。

代码

%matplotlib inline
import numpy as np
import torch
from d2l import torch as d2l

def f(x):  # 目标函数
    return x ** 2

def f_grad(x):  # 目标函数的梯度(导数)
    return 2 * x
def gd(eta, f_grad):
    x = 10.0
    results = [x]
    for i in range(10):
        x -= eta * f_grad(x)
        results.append(float(x))
    print(f'epoch 10, x: {x:f}')
    return results

results = gd(0.2, f_grad)
def show_trace(results, f):
    n = max(abs(min(results)), abs(max(results)))
    f_line = torch.arange(-n, n, 0.01)
    d2l.set_figsize()
    d2l.plot([f_line, results], [[f(x) for x in f_line], [
        f(x) for x in results]], 'x', 'f(x)', fmts=['-', '-o'])

show_trace(results, f)
show_trace(gd(0.05, f_grad), f)
show_trace(gd(1.1, f_grad), f)
c = torch.tensor(0.15 * np.pi)

def f(x):  # 目标函数
    return x * torch.cos(c * x)

def f_grad(x):  # 目标函数的梯度
    return torch.cos(c * x) - c * x * torch.sin(c * x)

show_trace(gd(2, f_grad), f)
c = torch.tensor(0.15 * np.pi)

def f(x):  # 目标函数
    return x * torch.cos(c * x)

def f_grad(x):  # 目标函数的梯度
    return torch.cos(c * x) - c * x * torch.sin(c * x)

show_trace(gd(2, f_grad), f)
def train_2d(trainer, steps=20, f_grad=None):  #@save
    """用定制的训练机优化2D目标函数"""
    # s1和s2是稍后将使用的内部状态变量
    x1, x2, s1, s2 = -5, -2, 0, 0
    results = [(x1, x2)]
    for i in range(steps):
        if f_grad:
            x1, x2, s1, s2 = trainer(x1, x2, s1, s2, f_grad)
        else:
            x1, x2, s1, s2 = trainer(x1, x2, s1, s2)
        results.append((x1, x2))
    print(f'epoch {i + 1}, x1: {float(x1):f}, x2: {float(x2):f}')
    return results

def show_trace_2d(f, results):  #@save
    """显示优化过程中2D变量的轨迹"""
    d2l.set_figsize()
    d2l.plt.plot(*zip(*results), '-o', color='#ff7f0e')
    x1, x2 = torch.meshgrid(torch.arange(-5.5, 1.0, 0.1),
                          torch.arange(-3.0, 1.0, 0.1), indexing='ij')
    d2l.plt.contour(x1, x2, f(x1, x2), colors='#1f77b4')
    d2l.plt.xlabel('x1')
    d2l.plt.ylabel('x2')
    def f_2d(x1, x2):  # 目标函数
    return x1 ** 2 + 2 * x2 ** 2

def f_2d_grad(x1, x2):  # 目标函数的梯度
    return (2 * x1, 4 * x2)

def gd_2d(x1, x2, s1, s2, f_grad):
    g1, g2 = f_grad(x1, x2)
    return (x1 - eta * g1, x2 - eta * g2, 0, 0)

eta = 0.1
show_trace_2d(f_2d, train_2d(gd_2d, f_grad=f_2d_grad))
c = torch.tensor(0.5)

def f(x):  # O目标函数
    return torch.cosh(c * x)

def f_grad(x):  # 目标函数的梯度
    return c * torch.sinh(c * x)

def f_hess(x):  # 目标函数的Hessian
    return c**2 * torch.cosh(c * x)

def newton(eta=1):
    x = 10.0
    results = [x]
    for i in range(10):
        x -= eta * f_grad(x) / f_hess(x)
        results.append(float(x))
    print('epoch 10, x:', x)
    return results

show_trace(newton(), f)
c = torch.tensor(0.15 * np.pi)

def f(x):  # 目标函数
    return x * torch.cos(c * x)

def f_grad(x):  # 目标函数的梯度
    return torch.cos(c * x) - c * x * torch.sin(c * x)

def f_hess(x):  # 目标函数的Hessian
    return - 2 * c * torch.sin(c * x) - x * c**2 * torch.cos(c * x)

show_trace(newton(), f)
show_trace(newton(0.5), f)

11.6动量法

我们详述了如何执行随机梯度下降,即在只有嘈杂的梯度可用的情况下执行优化时会发生什么。 对于嘈杂的梯度,我们在选择学习率需要格外谨慎。 如果衰减速度太快,收敛就会停滞。 相反,如果太宽松,我们可能无法收敛到最优解。
image

代码

%matplotlib inline
import torch
from d2l import torch as d2l

eta = 0.4
def f_2d(x1, x2):
    return 0.1 * x1 ** 2 + 2 * x2 ** 2
def gd_2d(x1, x2, s1, s2):
    return (x1 - eta * 0.2 * x1, x2 - eta * 4 * x2, 0, 0)

d2l.show_trace_2d(f_2d, d2l.train_2d(gd_2d))
eta = 0.6
d2l.show_trace_2d(f_2d, d2l.train_2d(gd_2d))
def momentum_2d(x1, x2, v1, v2):
    v1 = beta * v1 + 0.2 * x1
    v2 = beta * v2 + 4 * x2
    return x1 - eta * v1, x2 - eta * v2, v1, v2

eta, beta = 0.6, 0.5
d2l.show_trace_2d(f_2d, d2l.train_2d(momentum_2d))
eta, beta = 0.6, 0.25
d2l.show_trace_2d(f_2d, d2l.train_2d(momentum_2d))
d2l.set_figsize()
betas = [0.95, 0.9, 0.6, 0]
for beta in betas:
    x = torch.arange(40).detach().numpy()
    d2l.plt.plot(x, beta ** x, label=f'beta = {beta:.2f}')
d2l.plt.xlabel('time')
d2l.plt.legend();
def init_momentum_states(feature_dim):
    v_w = torch.zeros((feature_dim, 1))
    v_b = torch.zeros(1)
    return (v_w, v_b)

def sgd_momentum(params, states, hyperparams):
    for p, v in zip(params, states):
        with torch.no_grad():
            v[:] = hyperparams['momentum'] * v + p.grad
            p[:] -= hyperparams['lr'] * v
        p.grad.data.zero_()
def init_momentum_states(feature_dim):
    v_w = torch.zeros((feature_dim, 1))
    v_b = torch.zeros(1)
    return (v_w, v_b)

def sgd_momentum(params, states, hyperparams):
    for p, v in zip(params, states):
        with torch.no_grad():
            v[:] = hyperparams['momentum'] * v + p.grad
            p[:] -= hyperparams['lr'] * v
        p.grad.data.zero_()
train_momentum(0.01, 0.9)
train_momentum(0.005, 0.9)
trainer = torch.optim.SGD
d2l.train_concise_ch11(trainer, {'lr': 0.005, 'momentum': 0.9}, data_iter)
lambdas = [0.1, 1, 10, 19]
eta = 0.1
d2l.set_figsize((6, 4))
for lam in lambdas:
    t = torch.arange(20).detach().numpy()
    d2l.plt.plot(t, (1 - eta * lam) ** t, label=f'lambda = {lam:.2f}')
d2l.plt.xlabel('time')
d2l.plt.legend();

小结

动量法用过去梯度的平均值来替换梯度,这大大加快了收敛速度。

对于无噪声梯度下降和嘈杂随机梯度下降,动量法都是可取的。

动量法可以防止在随机梯度下降的优化过程停滞的问题。

由于对过去的数据进行了指数降权,有效梯度数为

在凸二次问题中,可以对动量法进行明确而详细的分析。

动量法的实现非常简单,但它需要我们存储额外的状态向量(动量
)。

后面的优化算法

AdaGrad算法
image

RMSProp算法
image
Adadelta
image
Adam算法
image
11.7 AdaGrad 算法核心思想:为每个参数自适应调整学习率 —— 频繁更新的参数用较小学习率,稀疏参数用较大学习率。实现逻辑:累积所有历史梯度的平方和,用其平方根作为分母缩放当前梯度;
公式:\(\(s_t = s_{t-1} + g_t^2\),\(\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{s_t+\epsilon}} g_t\)\)((\eta)为初始学习率,(\epsilon)防止除零)。优势:适配稀疏数据(如文本特征),无需手动调参;缺陷:梯度平方和持续累积,后期学习率衰减过快,易导致训练停滞。
11.8 RMSProp 算法核心思想:改进 AdaGrad 的 “学习率过度衰减” 问题,用指数移动平均替代梯度平方的累积和。实现逻辑:对梯度平方做泄漏平均(只保留近期梯度的影响);公式:\(\(s_t = \gamma s_{t-1} + (1-\gamma) g_t^2\)\)((\gamma)为衰减系数,常用 0.9),参数更新同 AdaGrad。优势:学习率衰减更平滑,避免后期停滞;适用场景:非凸优化(如深度学习),是 Adagrad 的常用替代方案。
11.9 Adadelta 算法核心思想:进一步改进 RMSProp,完全移除学习率超参数,用 “参数更新的历史幅度” 动态替代学习率。实现逻辑:同时维护梯度平方的移动平均和参数更新量的移动平均;公式:\(\(s_t = \gamma s_{t-1} + (1-\gamma) g_t^2\),\(\Delta x_t = \frac{\sqrt{\Delta x_{t-1}+\epsilon}}{\sqrt{s_t+\epsilon}} g_t\),\(\theta_{t+1} = \theta_t - \Delta x_t\)\)。优势:无需手动设置学习率,对超参数不敏感;特点:通过 “双历史(梯度 + 更新量)” 实现自洽的步长调节。
11.10 Adam 算法核心思想:结合动量法(利用梯度方向惯性)和自适应学习率(利用梯度幅度),是目前最常用的优化器之一。实现逻辑:维护梯度的一阶矩(动量):\(\(m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t\)\);维护梯度的二阶矩(自适应学习率):\(\(v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2\)\);对一阶 / 二阶矩做偏差校正(解决初始阶段估计偏差);参数更新:\(\(\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t}+\epsilon} \hat{m}_t\)\)。超参数:\(\(\beta_1=0.9\)(动量衰减)、\(\beta_2=0.999\)\)(二阶矩衰减)、\(\(\eta=0.001\)\)(基础学习率);优势:收敛快、鲁棒性强,适配绝大多数深度学习场景。
11.11 学习率调度器核心思想:不固定学习率,随训练过程动态调整(如衰减、预热、周期变化),提升收敛效率。常见策略:阶梯衰减:训练到指定轮数后按比例降低学习率;余弦退火:学习率按余弦函数周期性波动,兼顾探索与收敛;预热:初始阶段缓慢提升学习率,避免训练初期震荡;自适应调度:结合验证集性能动态调整(如早停)。作用:弥补优化器的不足,平衡 “探索(大学习率)” 与 “收敛(小学习率)”。

posted @ 2025-12-14 16:46  Morphis‘  阅读(20)  评论(0)    收藏  举报