4. 训练过程可视化:Loss曲线分析、Accuracy曲线分析、学习率调度可视化、过拟合与欠拟合诊断
训练一个模型,就像看着一个孩子长大。你得盯着他的成绩单,看他是不是在进步,有没有走偏。我个人习惯,训练时必开可视化面板。没有曲线,我根本不敢说自己了解模型的状态。
这一章,咱们就聊聊怎么从曲线里读出模型的「心事」。说白了,就是通过Loss、Accuracy、学习率这些曲线,诊断模型到底是欠拟合、过拟合,还是刚刚好。
4.1 Loss曲线:模型的学习日记
Loss曲线是最直接的反馈。它告诉你,模型在训练集上犯的错是不是越来越小。
核心原则:Loss下降,说明模型在学习。Loss震荡或上升,说明出问题了。
4.1.1 正常的Loss曲线长什么样?
一个健康的训练过程,Loss曲线应该是这样的:
- 快速下降期:训练刚开始,模型啥都不懂,Loss从高位快速下降。这很正常。
- 缓慢收敛期:过了几百步,下降速度变慢,曲线趋于平滑。模型开始精调参数了。
- 平稳期:最后Loss在一个小范围内波动,不再明显下降。说明模型已经收敛。
我在项目中遇到过,有个同事看到Loss下降慢了,就急着调学习率。其实没必要,只要曲线还在下降,哪怕很慢,也是好事。
4.1.2 异常Loss曲线诊断
| 曲线形态 | 可能原因 | 我的建议 |
|---|---|---|
| Loss 不下降,一直很高 | 学习率太小、模型容量不够、数据没归一化 | 先调大学习率试试,不行就换大模型 |
| Loss 突然飙升 | 梯度爆炸、数据出现异常值、学习率太大 | 赶紧暂停,检查梯度范数,考虑梯度裁剪 |
| Loss 剧烈震荡 | batch size 太小、学习率太大、数据噪声多 | 增大 batch size,或者用学习率预热 |
| Loss 先降后升 | 过拟合开始、学习率调度不当 | 加入正则化,或者降低学习率 |
注意:千万不要只看训练Loss。训练Loss低不代表模型好。你得结合验证集Loss一起看。
4.2 Accuracy曲线:模型的实际表现
Loss是内部指标,Accuracy是外部表现。有时候Loss降了,Accuracy没涨,那可能是模型在「死记硬背」。
4.2.1 训练集 vs 验证集 Accuracy
我建议你同时画两条Accuracy曲线:训练集和验证集。对比着看,信息量很大。
- 两条曲线同步上升:理想状态。模型在学真本事。
- 训练集高,验证集低:典型的过拟合。模型把训练数据背下来了,但没理解规律。
- 两条曲线都低:欠拟合。模型太简单,学不动。
- 验证集突然下降:可能数据分布变了,或者模型开始「遗忘」之前学的东西。
小技巧:如果验证集Accuracy在某个epoch后开始下降,而训练集还在上升,这就是「早停」的信号。我曾经因为这个判断失误,多训了50个epoch,结果模型反而变差了。
4.3 学习率调度可视化
学习率是训练过程中最敏感的超参数。调得好,事半功倍;调不好,事倍功半。
4.3.1 常见的学习率调度策略
| 策略 | 特点 | 适用场景 |
|---|---|---|
| 固定学习率 | 简单,但容易陷入局部最优 | 小数据集、简单任务 |
| Step Decay | 每隔N个epoch减半 | 分类任务,效果稳定 |
| Cosine Annealing | 余弦下降,带重启 | 大规模训练,能跳出局部最优 |
| ReduceLROnPlateau | Loss不降了,就降低学习率 | 自适应,省心 |
我个人习惯用Cosine Annealing加预热。前期学习率小,让模型稳定起步;中期大学习率快速探索;后期再降下来精细调整。效果比固定学习率好不少。
4.3.2 可视化学习率变化
把学习率的变化画出来,和Loss曲线放在一起看。你会发现,学习率下降时,Loss往往会跟着波动一下。这是正常的。但如果波动太大,说明学习率降得太快了。
经验之谈:学习率调度不是越复杂越好。我见过有人用10种策略组合,结果调参调了两个月。先试试ReduceLROnPlateau,简单有效。
4.4 过拟合与欠拟合诊断
这是训练过程中最常遇到的问题。怎么判断?看曲线对比。
4.4.1 过拟合的典型特征
- 训练Loss持续下降,验证Loss先降后升
- 训练Accuracy接近100%,验证Accuracy停滞或下降
- 模型在训练集上表现完美,但测试集上表现差
我曾经在一个图像分类项目里,模型在训练集上达到了99%的准确率,但验证集只有72%。一看曲线,训练Loss都快到0了,验证Loss却在上升。典型的过拟合。后来加了Dropout和数据增强,才把差距缩小到5%以内。
4.4.2 欠拟合的典型特征
- 训练Loss和验证Loss都高,且不再下降
- 训练Accuracy和验证Accuracy都低
- 模型在训练集上就表现不好
欠拟合相对好解决。加层数、加宽度、减少正则化、增大学习率,总有一款适合你。
4.4.3 诊断流程图
下面这张图,是我自己总结的诊断流程。每次训练出问题,我就按这个走一遍。
4.5 实战:用TensorBoard可视化训练过程
说了这么多理论,咱们来点实际的。TensorBoard是我最常用的可视化工具。怎么用?
4.5.1 记录Loss和Accuracy
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter('runs/experiment_1')
for epoch in range(num_epochs):
train_loss = train_one_epoch(model, train_loader)
val_loss, val_acc = evaluate(model, val_loader)
writer.add_scalar('Loss/train', train_loss, epoch)
writer.add_scalar('Loss/val', val_loss, epoch)
writer.add_scalar('Accuracy/val', val_acc, epoch)
writer.close()
4.5.2 记录学习率
for epoch in range(num_epochs):
current_lr = scheduler.get_last_lr()[0]
writer.add_scalar('Learning_rate', current_lr, epoch)
# 训练代码...
scheduler.step()
我的习惯:每次实验都新建一个文件夹,把超参数、模型结构、训练曲线都存进去。这样回头复盘时,一眼就能看出哪个实验跑偏了。
4.6 总结:可视化诊断清单
每次训练完,我都会对照这个清单检查一遍:
- Loss曲线:是否平滑下降?有没有异常震荡或上升?
- Accuracy曲线:训练集和验证集是否同步?差距大不大?
- 学习率曲线:变化是否合理?有没有导致Loss剧烈波动?
- 过拟合判断:验证Loss是否先降后升?
- 欠拟合判断:两条Loss曲线是否都居高不下?
嗯,这套流程我用了好几年,基本没出过大错。你试试看,肯定能帮你省下不少调试时间。