上一篇讲了数据。数据决定了模型的上限。这一篇讲:上限已经锁死了,怎么让模型尽量逼近它。
三个东西决定逼近的效率和质量:学习率调度、批归一化、迁移学习。不是调参技巧,是底层机制。
1. 学习率:训练过程中最重要的一个数字
整个训练循环里,只有一步是真正“改变”模型的:
```python
θ = θ - η * ∇L
```
η就是学习率。这个数字选错了,其他都白做。
太大了:参数每一步跨得太远。在高维非凸曲面上,大学习率等于在悬崖边跑步。loss不会收敛,直接发散成NaN。看到训练日志里loss变成inf或NaN,第一件事就是砍学习率。
太小了:每一步都在走,但走得太慢。loss曲线平得像死水。等到你算力耗尽,模型还没走到最优解的门口。而且小学习率容易卡在鞍点——梯度为零但不是极值点的地方——高维空间里鞍点远比局部最优多。
比较好的策略是“先大后小”。训练初期,参数还在随机状态,需要大步快走找到大致方向。训练后期,已经接近一个比较好的区域,需要小步微调避免跳过最优解。
实现上,常用三种调度器:
StepLR:每N个epoch,学习率乘以一个衰减因子(比如乘0.1)。简单粗暴。适合对训练进程有清晰预期的场景。缺点是衰减时机靠人工设定,没踩准就浪费了。
CosineAnnealing:学习率按照余弦曲线下降,从初始值平滑降到接近零。一个周期走完,从大步到小步,节奏均匀。目前多数视觉模型训练都默认这个。
ReduceLROnPlateau:监控验证loss。验证loss不降反升超过N个epoch,自动降低学习率。不需要预设衰减时机,靠数据自己触发。适合对训练进度没有先验判断的场景。缺点是验证loss本身有波动,可能触发假阳性。
三者可以组合。常见的做法:先CosineAnnealing跑完一轮,遇到瓶颈再ReduceLROnPlateau续一段。没有哪个调度器是绝对最优的,它取决于任务、数据、模型的组合。但有一个原则是通用的:不要用常数学习率从头训到尾。
2. 批归一化:它解决的根本问题不是你想的那个
Batch Normalization,2015年提出后成了标配。很多人对它的理解是“把每层输入标准化,让训练更稳定”。这个理解没错,但没说到根上。
BN做的操作:对当前batch的每个特征维度,减去均值,除以标准差,然后乘以可学习的γ,加上可学习的β。
```python
x_norm = (x - mean) / sqrt(var + eps)
output = γ * x_norm + β
```
表面效果是让每层输入保持均值0方差1的分布,缓解“内部协变量偏移”。但原论文提出的这个解释,后来被实验部分推翻了。MIT在2018年的实验证明:加了BN之后再给输入加随机偏移,BN照样有效。内部协变量偏移不是真正的原因。
真正的原因:BN让损失曲面变得平滑。
没有BN的时候,损失函数对某些参数的变化非常敏感,对另一些参数变化不敏感。曲面上到处是陡峭的悬崖和平坦的沟壑。梯度下降在这种地形上走,一个方向迈太大飞出悬崖,另一个方向迈太小走不出沟壑。学习率被迫设得很小,训练很慢。
加了BN之后,曲面的曲率在各方向上更均匀。原来的悬崖变缓,原来的沟壑变陡。梯度下降可以设更大学习率,走得更快。实验上,带BN的网络用大学习率训练,收敛速度可以快几倍甚至一个数量级。
另一个副作用:BN有轻微正则化效果。因为每个batch的统计量(均值、方差)都不一样,训练时加了随机噪声。这种噪声类似于Dropout,迫使每个神经元不能依赖特定batch的精确统计值。但这不是BN的主要作用,不能替代Dropout。
使用时需要注意两个地方:
训练和推理行为不同。 训练时用当前batch的均值和方差。推理时,batch=1,没法算统计量。所以在训练过程中,BN会维护一个全局的移动平均均值和方差,推理时用这个全局统计量。如果你看到训练精度和推理精度差异大,检查BN的moving average是否正确保存和加载。
batch太小的时候BN不稳定。 batch=2的时候,均值方差本身的误差就很大,标准化出来的值不可靠。这时考虑用LayerNorm(对每个样本的所有特征维度做归一化,不依赖batch统计量)或GroupNorm。LayerNorm是Transformer架构的标配,原因之一就是文本序列长度不一致,batch维度不好对齐。
3. 迁移学习:为什么别人的模型能给你用
一个ImageNet上预训练的ResNet,拿去微调猫狗分类,几百张图就能收敛到90%+准确率。从头训练,几万张图都不一定稳。
为什么不同任务之间能迁移?卷积网络的前几层学的是什么?
可视化实验已经反复验证:第一层学的是边缘和颜色斑点。第二层学的是简单纹理。第三层学的是局部形状。越往上,特征越抽象、越任务特定。底层的边缘检测不需要重新学。一个识别猫的卷积核和一个识别细胞的卷积核,第一层几乎一样。
所以迁移学习的标准做法:拿预训练模型的特征提取器(底层),换掉分类头(顶层)。 用新数据只训练分类头,或者以很小的学习率微调全部。
三类常用策略:
冻结特征提取器,只训练新分类头。 新数据极少(几百张)时用。不会破坏预训练权重。
全部微调,但用很小的学习率。 新数据足够(几千张以上)时用。让底层特征也稍微向新任务倾斜。
逐层解冻。 先训练顶层,逐层往下解冻。最精细也最麻烦。适合数据量中等、新任务和原任务差异大的场景。
迁移学习不限于图像。NLP领域,BERT/GPT的预训练+微调范式就是迁移学习。一个在万亿token上预训练的语言模型,已经学会了语法、常识和推理模式。你给它几百条客服对话,它就能做意图分类。给它几十篇行业报告,它就能做摘要。预训练学到的是“世界的结构”,微调是把结构适配到具体场景。
选择迁移学习的判断标准:源任务和目标任务的特征空间是否相近。 图像里都用卷积核提取空间特征,相近。文本里都用注意力机制提取上下文,相近。但一个训在传感器数据上的模型,拿去处理图像,特征空间完全不同,迁移不了。
另一个判断标准:源任务的数据量是否远大于目标任务。 迁移的本质是利用大数据的统计优势弥补小数据的不足。反过来就无意义。
4. 这一篇的要点
· 学习率是训练过程中唯一直接影响参数更新步长的数字。 不要用常数。选一个调度器:StepLR简单粗暴,Cosine平滑稳定,ReduceLROnPlateau自适应。
· 批归一化让损失曲面变平滑,允许用更大学习率加速收敛。 不是解决了“内部协变量偏移”,是解决了梯度下降的地形问题。训练和推理时的BN行为不同,小batch慎用。
· 迁移学习的本质是复用底层特征的统计规律。 预训练模型的特征提取器已经学会了检测边缘、纹理、语法结构,不需要每换一个任务都重头学。微调时用小学习率,新任务数据越少,冻结的层就越多。
下一篇写训练完成之后的事:评估指标。准确率为什么经常骗人,混淆矩阵怎么看,AUC到底在算什么。
夜雨聆风