训练参数基础:学习率、批量大小、迭代次数

说到空间模型的训练,这三个参数就像发动机的油门、载重和里程。调好了,车跑得又快又稳;调不好,要么原地打转,要么直接翻车。我刚开始接触大规模点云训练时,就吃过不少亏——学习率设太大,loss 直接炸到 NaN;批量大小设太小,GPU 利用率只有 10%,训一个 epoch 够喝三杯咖啡。今天咱们就把这三个基础参数掰开揉碎讲清楚。

学习率(Learning Rate)

学习率决定了模型参数每次更新的步长。说白了,就是告诉模型“你该往梯度方向跳多远”。

  • 太大:参数振荡发散,loss 不降反升。我曾经在一个三维语义分割模型上将 lr 设为 0.1,结果前几个 batch loss 冲到了 1e5,直接放弃治疗。
  • 太小:收敛极慢,可能卡在局部极小点。你想想看,每次只挪一小步,训几天都出不来。
  • 合适:loss 平滑下降,验证精度稳步提升。

常见的初始学习率范围:

任务类型推荐初始 lr常用优化器
点云分类(PointNet++ 类)1e-3 ~ 1e-2Adam / SGD + momentum
三维目标检测(VoxelNet 类)1e-4 ~ 1e-3AdamW
场景流估计1e-4 ~ 5e-4Adam
NeRF 类空间表示5e-4 ~ 5e-3Adam

这里有个小技巧:先跑几个 batch 做学习率范围测试。找个很小的 lr(比如 1e-6),逐渐增大,观察 loss 变化。选择 loss 下降最快且不震荡的那个区间。

我的习惯:先设 lr=1e-3,配合 cosine 退火调度,让学习率在训练后期自动衰减。省得手动调。

批量大小(Batch Size)

批量大小指每次更新参数时使用的样本数量。它影响三件事:梯度稳定性、内存占用、泛化能力。

  • 小批量(16~64):梯度噪声大,但能跳出现阱。适合内存受限的场景,比如点云数据量很大时。
  • 大批量(128~512+):梯度估计更准,训练速度快,但容易过拟合。嗯,这里要注意——批量大小翻倍时,学习率通常也要跟着线性增大(线性 scaling rule)。
  • 极限大批量(1024+):需要特殊策略,比如 LARS 优化器,否则泛化性能会明显下降。我在一次点云分割比赛中试过 batch size=1024,结果验证集精度比 batch size=64 低了 2 个点。

内存与批量大小的关系也很直接:

# 假设输入点云为 (B, N, C),每点 16 字节,N=4096, C=3
# batch size=32 时,显存占用约:
# 32 * 4096 * 3 * 16 ≈ 6.3 MB(仅输入)
# 加上特征图、梯度、优化器状态,实际翻 5~10 倍
# 所以 batch size=32 往往需要 12~24 GB 显存

我建议:先用 GPU 能容纳的最大 batch size 开始,然后逐步减小,观察验证集上的表现。通常小一点反而泛化更好。

迭代次数(Epoch / Iteration)

迭代次数分为两种:epoch(完整遍历一次训练集)和 iteration(一个 batch 更新一次)。两者关系很简单:iterations_per_epoch = 样本总数 / batch size。

那到底要训多少个 epoch?这取决于模型大小和数据量。我的经验是:

  • 小数据集(<1k 样本):50~200 epoch,配合早停(early stopping)。
  • 中等数据集(1k~10k 样本):100~500 epoch。
  • 大型数据集(>100k 样本):20~100 epoch。
千万不要固定 epoch 数就开跑。我吃过一次亏:设了 300 epoch,结果第 50 epoch 就过拟合了,后面 250 个 epoch 完全是浪费电。一定要加验证集监控,设置早停 patience=10~20。

另外,迭代次数与学习率调度强相关。比如 step decay:每 N 个 epoch 将 lr 乘以 0.1。我常用的调度策略:

# PyTorch 示例:余弦退火 + 线性 warmup
import torch.optim as optim
from torch.optim.lr_scheduler import CosineAnnealingLR, LinearLR

optimizer = optim.AdamW(model.parameters(), lr=1e-3)
warmup = LinearLR(optimizer, start_factor=0.1, total_iters=5)
cosine = CosineAnnealingLR(optimizer, T_max=95)
scheduler = torch.optim.lr_scheduler.SequentialLR(
    optimizer, schedulers=[warmup, cosine], milestones=[5])

三者之间的微妙关系

这三个参数不是孤立的。调整一个,往往需要连带调整另外两个。下面这张图我画了多次才理清思路:

训练参数核心关系 学习率 lr 步长大小 批量大小 B 每次样本数 迭代数 Epoch 训练总轮次 梯度噪声 收敛速度 泛化能力 最优验证精度 稳定且高效的训练 调参提示:批量大小增大 → 学习率应线性增大;迭代次数增加需配合学习率衰减; 小批量 + 大学习率 → 梯度噪声大但可能跳过鞍点,适合前期快速探索。

实战调参 checklist

我自己总结了一套快速调参流程,用起来挺顺手的:

  1. 固定 batch size:先设为 GPU 能承受的最大值,比如 64。
  2. 找合适 lr:用学习率范围测试,找到 loss 下降最快的区间,选中间值。
  3. 调节 batch size:在 16~128 之间尝试,观察验证精度。通常小 batch 泛化更好,但别忘了同步调 lr。
  4. 定迭代次数:不加早停,先看 loss 曲线什么时候平缓,之后再加 20% 作为安全余量。
  5. 联合微调:比如将 lr 减半、batch 加倍,看效果是否更好。

核心原则:学习率是“油门”,批量大小是“载重”,迭代次数是“里程”。油门踩大了载重不够会飘,载重太重了油门得跟上。三者平衡,才能又快又稳到终点。

嗯,基本就是这些。下次你在训练空间模型时,先别急着改网络结构,花半小时把这仨参数摸一遍,往往能省下几天的时间。我当年要是早懂这个道理,也不至于对着 NaN 的 loss 发呆一整天了。