2. 参数调优基础:学习率、批量大小与优化器

各位同学,咱们今天聊点实在的。模型训练里什么最让人头疼?我个人的经验是——调参。尤其是学习率、批量大小和优化器这三个家伙,它们就像三驾马车,配合不好,模型就跑偏。

先别急着上代码,咱们先把底层逻辑理清楚。你想想看,一个模型从随机初始化到收敛,本质上就是在损失函数这个“地形图”上找最低点。而学习率,就是你每一步迈多大。

2.1 学习率:步子大了容易扯着蛋

学习率(Learning Rate, LR)控制着参数更新的步长。公式很简单:

θ_new = θ_old - η * ∇L(θ_old)

其中 η 就是学习率。η 太大,参数会在最优解附近震荡,甚至发散;η 太小,训练慢得像蜗牛爬,还容易陷入局部最优。

我在项目中遇到过最典型的案例:有一次训练一个图像分类模型,loss 死活降不下去。我盯着曲线看了半天,发现它在 0.8 到 1.2 之间来回跳。嗯,这就是典型的学习率过大。我把 η 从 0.01 降到 0.001,loss 立马乖乖收敛了。

核心结论:

  • 学习率过大 → 震荡、不收敛
  • 学习率过小 → 收敛慢、易陷入局部最优
  • 学习率适中 → 稳定下降、快速收敛

那怎么选初始学习率?我建议用 学习率范围测试(LR Range Test)。说白了,就是让学习率从小到大地跑几个 epoch,观察 loss 下降最快的那个区间。比如从 1e-6 到 1,画个曲线,找到 loss 下降最陡的地方,那就是你的“黄金学习率”。

我的小技巧: 实际项目中,我通常先用 0.001 作为初始值,然后配合学习率衰减策略。比如每 10 个 epoch 衰减为原来的 0.1 倍。这样既能快速下降,又能精细收敛。

2.2 批量大小:不是越大越好

批量大小(Batch Size)决定了每次更新参数时用多少样本计算梯度。这里有个常见的误区:很多人觉得 batch size 越大越好,因为可以利用 GPU 并行计算。

我曾经踩过这个坑。 有一次我把 batch size 从 32 调到 256,想着训练速度能翻倍。结果呢?速度确实快了,但模型精度掉了 2 个百分点。为什么?因为大 batch 会让梯度估计过于平滑,失去了随机梯度下降的“随机性”,反而容易收敛到尖锐的极小值。

来看个对比表格:

批量大小 优点 缺点 适用场景
小(16-64) 泛化性好、内存占用低 训练慢、梯度噪声大 小数据集、显存受限
中(64-256) 平衡速度和精度 需要调学习率 大多数通用场景
大(256-1024+) 训练速度快、GPU利用率高 泛化性下降、容易过拟合 大数据集、分布式训练

你想想看,为什么小 batch 泛化性好?因为每次梯度估计都有噪声,这个噪声反而像正则化一样,帮助模型跳出局部最优。我个人的习惯是:先试 64,不行再调 32 或 128。记住一个原则:batch size 翻倍,学习率也要跟着翻倍,这样才能保持梯度更新的幅度一致。

注意: 如果你的 GPU 显存不够,别硬上大 batch。用梯度累积(Gradient Accumulation)技术,模拟大 batch 的效果。比如 batch size=32,梯度累积步数=4,等效于 batch size=128。

2.3 优化器:各有各的脾气

优化器就是那个决定“怎么走”的算法。SGD、Adam、RMSprop……每个都有自己的一套逻辑。咱们来逐个分析。

SGD(随机梯度下降)

最原始的优化器。每次更新只用一个样本或一个小 batch 的梯度。优点是简单、稳定,缺点是收敛慢、容易震荡。

# PyTorch 示例
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

加上 momentum(动量)后,SGD 会考虑历史梯度的方向,像滚雪球一样加速。我一般把 momentum 设为 0.9,效果不错。

Adam(自适应矩估计)

Adam 是目前最流行的优化器。它结合了 Momentum 和 RMSprop 的优点,能自适应调整每个参数的学习率。说白了,就是给每个参数单独配一个“学习率调节器”。

optimizer = torch.optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999))

我记得有一次做 NLP 任务,用 SGD 训了 50 个 epoch 还没收敛,换成 Adam 后 10 个 epoch 就搞定了。Adam 对超参数不敏感,特别适合新手和快速实验。

RMSprop

RMSprop 是 Adam 的前身,主要解决梯度消失和爆炸问题。它通过指数移动平均来调整学习率,适合处理非平稳目标。

optimizer = torch.optim.RMSprop(model.parameters(), lr=0.001, alpha=0.99)

说实话,现在用 RMSprop 的人不多了,大部分场景都被 Adam 取代。但在某些 RNN 任务中,RMSprop 依然有它的优势。

优化器对比总结

优化器 收敛速度 泛化能力 调参难度 推荐场景
SGD+Momentum CV、需要精细调参
Adam NLP、快速实验
RMSprop RNN、序列模型

我个人建议:新手先用 Adam,等模型跑通了再换 SGD 精调。Adam 帮你快速找到“好区域”,SGD 帮你找到“最优解”。

2.4 知识体系总览

为了让你更直观地理解这三者的关系,我画了一张图:

参数调优基础 学习率 (LR) 控制步长大小 过大震荡 / 过小收敛慢 批量大小 (Batch) 影响梯度估计精度 小batch泛化好 / 大batch速度快 优化器 (Optimizer) 决定更新策略 SGD/Adam/RMSprop 三者协同工作 学习率决定步长 → 批量大小决定方向 → 优化器决定走法

这张图把三者的关系说得很清楚了。学习率决定“迈多大步”,批量大小决定“往哪个方向看”,优化器决定“怎么迈出这一步”。三者缺一不可。

2.5 实战建议

最后,给你一套我常用的调参流程:

  1. 先用 Adam,学习率 0.001,batch size 64,跑 10 个 epoch 看看 loss 下降趋势。
  2. 如果 loss 下降太慢,尝试增大学习率到 0.01;如果震荡,减小到 0.0001。
  3. 模型基本收敛后,换成 SGD+Momentum,学习率缩小 10 倍,精调 20-30 个 epoch。
  4. 如果显存够用,尝试增大 batch size 到 128 或 256,同时按比例增大学习率。

避坑指南: 我曾经在 batch size 从 64 调到 128 时忘了调学习率,结果模型直接炸了。记住:batch size 翻倍,学习率也要翻倍。这是经验之谈。

好了,这一章的内容就到这里。参数调优是个手艺活,多练才能找到感觉。下一章咱们聊聊更高级的调参技巧——学习率调度策略和权重初始化。


公众号:蓝海资料掘金营,微信deep3321