linear 是 momentum 优化器中的一个学习率调度策略,它指的是学习率随着训练轮数的增加而线性衰减。

下面我们从几个方面来深入理解它。
什么是 momentum 优化器?
回顾一下 momentum(动量)优化器的基本原理,它不仅仅考虑当前梯度,还考虑了历史梯度的指数移动平均(可以理解为“惯性”),从而帮助优化过程更稳定、更快地收敛。
其更新公式如下: $$ vt = \gamma \cdot v{t-1} + \eta \cdot \nabla J(\theta_{t-1}) \ \thetat = \theta{t-1} - v_t $$
- $v_t$ 是当前时刻的动量项(速度)。
- $v_{t-1}$ 是上一时刻的动量项。
- $\gamma$ (gamma) 是动量系数,通常接近1(如0.9),它决定了历史梯度的影响程度。
- $\eta$ (eta) 是学习率,它控制了每一步更新的步长。
- $\nabla J(\theta{t-1})$ 是在参数 $\theta{t-1}$ 处的梯度。
- $\theta_t$ 是更新后的参数。
在标准的 momentum 优化器中,学习率 $\eta$ 是一个固定的常数。

linear 参数的作用:学习率线性衰减
在深度学习中,一个固定不变的学习率往往不是最优的,训练初期,较大的学习率可以加速收敛;但在训练后期,较大的学习率可能导致在最优解附近震荡,甚至无法收敛。
我们需要一种策略来动态调整学习率。linear 就是其中一种最简单、最直观的策略。
linear 调度策略的公式如下:
$$ \eta_t = \text{initial_lr} \times (1 - \frac{t}{\text{max_epochs}}) $$

或者,在一些实现中(如 TensorFlow/Keras),它会衰减到一个最小值:
$$ \eta_t = \text{max}(\text{min_lr}, \text{initial_lr} \times (1 - \frac{t}{\text{max_epochs}})) $$
- $\eta_t$ 是在第 $t$ 个 epoch(训练轮数)时的学习率。
initial_lr是初始学习率。max_epochs是总训练轮数。min_lr是学习率的最小值(可选,防止学习率过小)。
直观理解:
学习率从 initial_lr 开始,随着训练轮数 t 的增加,线性地、平滑地下降,当训练到 max_epochs 时,学习率理论上会降为0(或 min_lr),这就像一辆汽车在接近目的地时,逐渐踩下刹车,平稳地停下来。
linear 参数的优缺点
优点:
- 简单直观:实现和理解都非常简单,公式直接明了。
- 防止后期震荡:随着训练接近尾声,学习率逐渐减小,使得模型能够在损失函数的最小值附近进行更精细的调整,避免因学习率过大而“冲过”最优解。
- 经验有效:在很多经典任务和模型中,线性衰减是一种非常有效且常用的学习率衰减策略,是很多研究的基准选择。
缺点:
- 衰减速率固定:衰减的速率是预先设定好的(由
max_epochs决定),它无法根据训练过程中的实际情况(如损失下降的快慢)进行自适应调整。 - 依赖超参数:性能的好坏依赖于对
max_epochs的准确估计。max_epochs设定得过大,学习率会过早地变得过小,导致训练后期收敛缓慢;如果设定得过小,学习率可能衰减不足,无法起到稳定收敛的作用。 - 可能过于激进:对于某些复杂任务,线性的衰减方式可能过于“暴力”,不如更平滑的衰减策略(如余弦退火)效果好。
在不同框架中的实现
linear 参数通常不会直接作为 momentum 优化器的一个内部参数,而是作为学习率调度器与优化器配合使用。
PyTorch 示例
在 PyTorch 中,你不会直接在 torch.optim.SGD 中设置 linear,而是创建一个 SGD 优化器,然后配合一个 LambdaLR 或 LinearLR 调度器。
import torch
import torch.optim as optim
# 1. 定义模型和数据
model = ...
train_loader = ...
# 2. 设置超参数
initial_lr = 0.1
max_epochs = 100
momentum_gamma = 0.9
# 3. 定义优化器
optimizer = optim.SGD(model.parameters(), lr=initial_lr, momentum=momentum_gamma)
# 4. 定义 LinearLR 学习率调度器
# 第一个参数是优化器,第二个参数是 lr_lambda 函数
# lambda epoch: 1 - epoch / max_epochs linear 的公式
scheduler = optim.lr_scheduler.LinearLR(
optimizer,
start_factor=1.0, # 初始因子,即 initial_lr
end_factor=0.0, # 结束因子,当 epoch=max_epochs 时,lr = initial_lr * end_factor
total_iters=max_epochs # 总迭代次数(这里是按 epoch 计)
)
# 5. 在训练循环中使用
for epoch in range(max_epochs):
# 训练代码...
# ...
# 在每个 epoch 结束后,更新学习率
scheduler.step()
# 可以打印当前学习率
current_lr = optimizer.param_groups[0]['lr']
print(f"Epoch {epoch}, LR: {current_lr:.6f}")
TensorFlow/Keras 示例
在 Keras 中,通常在 compile 时通过 learning_rate_schedule 参数来指定。
import tensorflow as tf
# 1. 定义模型
model = tf.keras.models.Sequential([...])
# 2. 定义学习率调度器
# initial_learning_rate 是初始值,decay_steps 是衰减步数,decay_rate 是衰减因子
# 对于 linear decay,decay_rate = 1 / (total_epochs / decay_steps)
# 但更简单的方式是使用 PolynomialDecay 并设置 power=1
initial_learning_rate = 0.1
decay_steps = 100 # 通常等于总训练步数或 epoch 数
lr_schedule = tf.keras.optimizers.schedules.PolynomialDecay(
initial_learning_rate,
decay_steps=decay_steps,
end_learning_rate=0.0, # 结束时的学习率
power=1.0 # power=1 表示线性衰减
)
# 3. 定义优化器并传入学习率调度器
optimizer = tf.keras.optimizers.SGD(
learning_rate=lr_schedule,
momentum=0.9
)
# 4. 编译模型
model.compile(optimizer=optimizer, loss='...')
# 5. 训练模型
model.fit(...)
与其他学习率调度策略的比较
| 策略名称 | 公式/特点 | 适用场景 |
|---|---|---|
linear (线性衰减) |
lr = initial_lr * (1 - t/max_epochs) |
简单有效,适用于大多数标准任务。 |
| Step Decay (阶梯衰减) | 每隔 N 个 epoch,学习率乘以一个小于1的因子(如0.1)。 | 在某些需要明确“降温”的场合有效,但不如平滑衰减稳定。 |
| Exponential Decay (指数衰减) | lr = initial_lr * decay_rate ^ t |
衰减更平滑,前期衰减快,后期衰减慢。 |
| Cosine Annealing (余弦退火) | lr = min_lr + 0.5 * (max_lr - min_lr) * (1 + cos(t / T * π)) |
学习率呈余弦曲线变化,能跳出局部最优,常用于迁移学习和竞赛。 |
| ReduceLROnPlateau | 当验证损失不再下降时,自动减少学习率。 | 自适应策略,不依赖训练轮数,非常实用,能根据模型性能动态调整。 |
momentum 优化器中的 linear 参数(或称策略)是一种将学习率随训练轮数线性降低的方法,它通过在训练后期减小更新步长,帮助模型更稳定地收敛到最优解,虽然简单,但它是一种非常经典且有效的学习率调整技术,是深度学习工具箱中不可或缺的一部分,在实际应用中,你可以根据任务的特点选择 linear 或其他更复杂的调度策略。
