1. 只盯Loss就像只测体温:大模型训练也需要「内科检查」
前阵子帮朋友排查一个70B模型的训练异常,他发来的曲线图里loss一路向下,走势漂亮得可以直接印在海报上。但模型产出全是乱码,生成质量一塌糊涂。我们对着log翻了一个多小时,最后发现grad norm早就在悄悄爬升,只是没人往那个维度多看一眼。
这事让我想了很久。训练大模型的人现在普遍有一个习惯:打开tensorboard先看loss,loss降了就安心,loss抖了就开始调学习率。可loss本质上只是模型在训练集上的平均损失,它回答的问题是「模型当前学得怎么样」,却回答不了「模型是怎么学的」「学的过程中有没有结构性隐患」。
说得直白一点,loss像体温。体温正常不代表身体没毛病——可能是炎症早期,可能是免疫系统在过度反应,甚至可能是某些指标已经崩了但还没反映到体温上。真正要判断一个人的身体状况,得测血压、心率、血氧、电解质,得看各项指标之间的联动关系。
大模型训练也一样。loss之外,grad norm、param norm、激活分布、梯度noise scale、loss spike的出现时机与恢复速度、train/val gap的变化趋势、embedding空间的结构演化……这些都是训练过程中实实在在的「生命体征」。这篇文章想聊的,就是怎么把这些指标串起来,形成一套可以用于日常诊断的方法论。
适用对象包括:正在跑预训练或大batch微调的工程师,做RLHF/DPO训练时被loss波动困扰的研究者,以及刚入门大模型训练、对着监控面板不知道看什么的新人。我不打算写那种「指标清单+标准阈值」的说明书——训练配置千差万别,脱离场景谈阈值都是耍流氓。我更想分享的是诊断思路:当某个指标出现异常时,应该往哪个方向查,哪些指标要对照着看,怎样在训练彻底崩掉之前提前干预。
2. 训练监控的「生命体征四项」:名称、含义与第一反应
在深入具体案例之前,先把最基础的框架搭起来。我把日常训练中必须盯的指标分成四类,刚好对应内科体检的几大系统。
2.1 收敛类指标:Loss曲线与Perplexity
Loss是模型在训练集上的平均负对数似然,它衡量的是模型对当前batch数据给出的预测分布与真实分布之间的差距。Perplexity是loss的指数形式,数学上等于exp(loss),语义上可以理解为「模型在每一步预测时的平均候选词数量」——困惑度越低,模型对下一个token的预测越确定。
这两个指标的价值在于反映趋势,而不是反映单点状态。单看某一步的loss没有意义,因为它受batch内的数据难度、batch size、学习率调度阶段的影响太大。要看的是滑动平均后的曲线形态:下降速度是否与学习率调度匹配、是否出现平台期、是否存在周期性波动。
2.2 稳定性类指标:Grad Norm(梯度范数)与Param Norm(参数范数)
Grad norm是我在训练中最先看的指标,某种程度上比loss更重要。它的定义是所有参数梯度的L2范数,取值大小直接反映参数更新的剧烈程度。
这里要解释一个容易混淆的点:grad norm的绝对值没有标准参考值,因为它和模型参数量、batch size、loss scale都有关系。但它的相对变化模式非常有信息量:
- grad norm平稳下降,说明训练过程顺滑
- grad norm持续攀升,说明梯度在积累,训练开始不稳定
- grad norm突然出现尖峰又迅速回落,可能是碰到了异常batch或数据中的离群点
- grad norm与loss同时飙升且不回落,这是发散的前兆
Param norm是所有参数的L2范数,它反映的是参数整体的规模。在AdamW等自适应优化器下,param norm通常缓慢稳定增长;如果param norm出现突变,往往意味着权重更新过大或数值溢出。
2.3 分布类指标:激活值统计与embedding变化
这类指标需要定期hook到模型的某些层上,观察激活值(activation)的均值和方差。大模型训练中常见的不稳定现象——loss spike、输出NaN、性能突然崩塌——根源往往是某些层的激活值分布发生了偏移,导致后续层的输入范围超出了预期。
具体操作上,可以在每个Transformer Block的输入输出处加hook,记录激活的mean、std、max/min。重点关注首层和末层:首层反映输入分布的稳定性,末层反映输出层的学习进展。如果某个中间层的激活std突然增大,说明该层权重更新过于激进,这就是后续NaN的预警信号。
2.4 健康类指标:Loss Scale、吞吐量、显存水位
混合精度训练(AMP)下的loss scale是很多人忽略的指标。loss scale的自动调整机制是为了防止梯度下溢,如果它持续下降,说明梯度整体偏大,模型在尝试用更大的有效学习率;如果它骤降,说明出现了溢出的梯度,优化器正在降低scale进行恢复。持续观察loss scale的变化,能提前预判梯度数值范围是否健康。
吞吐量和显存水位不是学习动态指标,但它们能反映训练基础设施的健康度。吞吐量突然掉了30%,大概率是数据加载出现了瓶颈或者GPU降频;显存持续增长且不回落,可能存在显存碎片化问题。
这些指标之间是联动的关系,不是孤立的。比如grad norm上升和loss spike可能同时出现,也可能是前者先升、后者再过几千步才跟上。理解这种时序上的先后关系,才是「诊断」的核心能力。下一节用一个我实际遇到的案例展开讲。
3. Grad Norm持续攀升的排查链路:一个真实训练事故的完整复盘
3.1 事故现场:loss在降,但模型在变傻
有次我在跑一个13B模型的领域适配训练,用的是固定学习率加warmup的配置。训练到第8000步左右时,loss曲线看起来一切正常——平滑下降,没有明显波动。但我在做中间checkpoint评测时发现,模型在通用benchmark上的表现比第6000步时下降了将近3个点;在下游任务上的表现也在走低。
很多人遇到这种情况的第一反应是「过拟合了」,于是去调weight decay或者提前停止。但我当时看了一眼grad norm的曲线,发现从第6500步开始,它在持续攀升,从最初的0.8左右一路涨到了2.5,而且没有回落的趋势。
loss下降但grad norm上升,这个组合很反常。正常训练中,随着loss降低,梯度会逐渐变小(因为模型越来越接近局部最优点)。grad norm持续上升意味着:模型虽然在当前batch上拟合得不错,但参数更新的步长在越来越大,整个参数空间的状态越来越动荡。
3.2 排查第一步:先排除数据侧的干扰
训练中遇到任何异常,我的第一反应永远是先查数据。因为数据是训练信号的上游来源,数据出问题会直接导致梯度异常。
我检查了当天的数据pipeline:数据源是否被更新过、是否混入了格式错误的内容、数据增强逻辑是否有随机性问题。结果发现数据本身没有变化,但我在datasampler里用的是按长度分桶+batch内padding的方式,有极小概率把长度差异过大的样本放在同一个batch里。随即验证了一下,发现grad norm的尖峰确实与这些极端长度的batch出现位置高度吻合。
这里要做一个区分:数据导致的grad norm尖峰通常是瞬时的,出现后很快就会回落;而这次的grad norm是持续攀升,不是尖峰而是趋势性上升。所以数据侧影响可以排除,问题的根源应该在模型侧。
3.3 排查第二步:检查学习率调度与优化器状态
排除数据因素后,下一步看优化器状态。我用的是AdamW,beta2=0.95,这个配置在长序列训练中有利于追踪梯度的近期变化,但风险是如果梯度波动较大,二阶矩估计容易被少数大梯度主导,导致有效学习率降低、参数更新步长反而不稳定。
我打印了优化器状态中exp_avg_sq(也就是二阶矩估计)的分布情况,发现它在第6500步之后确实出现了几个数量级的分化——一小部分参数的exp_avg_sq非常大,而大部分参数的exp_avg_sq在正常范围。这种情况下Adam的分母项会对那部分参数产生极强的缩放,导致参数更新方向被那些「异常通道」主导。
这个问题背后的本质是:embedding层和输出层(lm_head)的学习动态不一致。在大模型训练中,embedding矩阵的梯度通常比Transformer层大一个量级,尤其是在训练后期、词表较大时。我的配置里把这两个模块的学习率设为跟主干一致,这其实是一个隐患——应该为它们设置更低的学习率(比如主干的0.5倍),或者单独做norm clipping。
3.4 排查第三步:逐层梯度分布分析——定位问题在「哪一层」
为了进一步确认问题的位置,我加了一段临时代码,在每个Transformer Block的backward hook里记录梯度范数,按层输出。这个操作在训练中会带来约10%~15%的额外开销,但定位问题的时候值得付出这个代价。
结果很清晰:问题集中在浅层。前几层(第1~4层)的梯度范数占总梯度的比例随时间在增大,从初始的8%左右涨到了接近20%,而深层的变化相对平稳。这说明浅层在「补偿」某个问题——通常是深层更新后的特征分布发生了变化,浅层被迫不断调整自己的映射方式来适应。
结合param norm一起看,浅层的param norm增长速度明显高于深层。这种情况下,即使loss还在下降,模型的内部表征也在发生剧烈的重排,泛化能力实际上在恶化——这解释了为什么通用benchmark的分数在下降。
3.5 解决方案:先降温,再调整结构
确认了根因之后,我做了三步处理:
- 先把学习率降为原来的1/3,让参数空间先冷静下来,这一步是「急救」,目的是中止grad norm继续攀升的趋势。
- 把embedding和lm_head从主学习率中分离,设置为主干学习率的0.5倍。这种设计在词表较大的模型(比如>50K词表)中几乎是必要条件,因为词表侧参数的更新频率和幅度天然高于Transformer层。
- 给浅层单独设置更小的学习率,或者使用分层学习率衰减(layer-wise learning rate decay),让浅层的变化更保守。
同时我把AdamW的beta2从0.95调回0.98,降低对近期梯度波动的敏感度。恢复训练后,grad norm在3000步内回到了正常水平,通用benchmark分数也止跌回升。
提示:这个案例最有价值的教训不是「怎么修」,而是诊断顺序。先排除数据(外部因素),再查优化器(训练机制),最后定位层分布(内部结构),这个顺序能帮你避免在错误的方向上浪费时间。
4. Loss Spike背后的「生理机制」:从一次梯度溢出说起
4.1 突发的loss spike不是随机事件
大模型训练中,loss spike是最常见的「吓人现象」。loss从2.1突然跳到8.9,然后过几百步又降回来。很多人的直接反应是「降低学习率」,但我要说一句可能让你意外的话:不是所有loss spike都需要干预。
这里要先理解loss spike产生的几种可能机制:
- 数据侧离群点:某个batch里混入了极端难样本或者噪声数据,导致梯度异常。这种情况通常会快速恢复,不需要干预
- 学习率过大:大学习率让参数跨越了loss landscape中的「陡峭区域」,产生尖峰但能自行恢复
- 梯度累积溢出:在gradient accumulation过程中,中间梯度超出了数值范围
- 激活值分布突变:某些层的激活值std突然增大,导致梯度爆炸或消失
这些机制对应的处理方式完全不同,如果不加区分地降学习率,反而可能破坏原本健康的训练节奏。判断依据依然是:spike出现的位置、恢复速度、以及它与其他指标的时序关系。
4.2 loss spike伴随着loss scale骤降,问题在数值稳定性
我遇到过最典型的情况是:loss spike出现的同一步,AMP的loss scale从2的24次方直接降到2的16次方。这说明在混合精度训练中发生了梯度溢出,优化器为了自保主动降低了loss scale。
这个信号的诊断含义很明确:梯度中有数值溢出的部分。排查方向有两个:一是数据侧——检查是否存在异常长的序列或极端权重;二是模型侧——激活值在某些层变得过大。
我的排查方法是:在loss scale骤降的step前后,抓取各层的激活值max和min。如果某一层的激活绝对值超过1e4以上,基本就能定位到问题层。通常问题出在attention层——当序列中存在某些token的attention score分布异常集中时,该位置的输出会偏大,进而放大后续层的激活值。
4.3 恢复速度是最重要的诊断信号
判断一个loss spike是否「要管」,我倾向于看恢复速度。
如果spike后100~300步内loss回到正常趋势,可以认为是「生理性波动」,对训练影响有限。如果spike后500步以上还没恢复,或者恢复后loss稳定在一个比以前更高的水平,这就是「病理性事件」,必须查找原因。
另一个关键点是「spike后的稳态水平是否抬升」。如果loss在spike后恢复到比spike前更低的水平,说明这次spike反而帮模型跨过了一个障碍(这在大学习率训练中会出现,类似于学习率warmup的效果);如果恢复到更高的水平且长时间不再下降,说明参数被推到了一个不利的局部区域,需要回滚checkpoint。
提示:保存checkpoint的粒度在这里非常关键。我习惯每500步保存一个可回滚的checkpoint(保留最近5个),每5000步保存一个阶段性的checkpoint(长期保留)。这样在需要回滚时,能做到既不过度丢弃训练进度,又能定位到具体的时间节点。
4.4 频率与模式:反复出现的周期性spike更危险
单次spike可能是随机事件,但周期性spike往往是系统性问题的信号。我见过一种模式:每3000步左右出现一次loss spike,而且spike的间隔随着训练在缩短。排查后发现是数据源里有一个定时更新的子集,每次更新后都会引入一批与当前模型分布差异极大的样本,导致周期性的分布冲击。
另一种周期性spike来自学习率调度:在使用cosine decay或者warmup后重启(warmup restart)时,学习率曲线中的非光滑点会导致参数穿越loss landscape中较陡峭的区域。这种spike虽然不是「病」,但如果每个重启点都伴随着较大的loss波动,说明学习率的上升速度过快,需要增加重启阶段的warmup步数。
这些排查思路用一句话概括:spike的形态(高度、宽度、恢复速度、出现频率)比spike本身更重要。下次看到loss曲线上的「锯齿」,先别急着杀学习率,先看清它的形状。
5. Train/Val Gap的「影像学表现」:从泛化能力反推训练阶段是否健康
5.1 Loss曲线好看,但验证集在变差——典型的「假健康」
我看过太多训练曲线汇报——loss曲线漂亮,泛化能力却一塌糊涂。只盯着训练集的loss看,本质上是在「用体温判断肿瘤」。
大模型训练中,真正要盯的是train loss和val loss之间的gap。gap在增大,不管是绝对的差距还是相对的趋势,都代表着模型的泛化能力在衰退。
上个月一个做领域微调的朋友跑了个实验,在指令微调阶段loss稳定在1.3,评测分数也稳步上升。但做到第3个epoch时,训练loss还在微降,验证集上的loss却开始回升,评测分数也开始波动。这就是标准的过拟合早期信号。
5.2 负斜率现象:val loss回升但train loss下降的区别
医学上的「影像学表现」用来类比,我认为最贴切的是「负斜率现象」——训练集loss在降,验证集loss在升。在训练曲线图上,如果对两条曲线分别做趋势拟合,明显能看到两者的斜率方向相反。
负斜率现象出现的阶段和严重程度,对应着不同的诊断:
- Epoch 1~2出现负斜率:说明模型容量相对于数据量过大,或者数据增强不够、正则化过强
- Epoch 3+出现负斜率:这是正常的收敛阶段信号,但要关注gap扩大的速度
- Epoch 5+出现负斜率且加速扩大:过拟合已经比较严重,需要提前停止、降低学习率,或增加dropout
我个人的经验是:不要等到val loss开始回升才介入。更好的办法是监控train loss和val loss的gap变化率。如果gap在最近1000步内的增幅大于之前1000步增幅的1.5倍以上,这就是一个明确的「黄灯」信号,即便val loss还没开始回升。
5.3 验证集设计决定了「影像」的质量
这里必须提醒一个大家容易忽略的点:验证集的构造方式决定了val loss这个「影像指标」是否可信。
- 验证集不能和训练集共享任何文档级别的来源,否则存在数据泄漏隐患
- 验证集应该是分布匹配的——即验证集的语言分布、难度分布和真实使用场景匹配
- 验证集规模不能太小,否则val loss的噪声会掩盖真实的泛化趋势。推荐至少2000~5000条样本,才能获得稳定的val loss估计
我在实际项目中会同时维护三份验证数据:一份是随机采样的领域数据(用于监控泛化趋势),一份是固定的benchmark集(用于跨版本对比),一份是用户反馈中收集到的「困难样本集」(用于监控模型长期的退化方向)。三份数据的val loss趋势要对照着看,才能较全面地判断「身体状态」。
5.4 一个反直觉的诊断结论:loss不降但val在涨,可能是「快照效应」
还有一种情况容易被误判为过拟合:val loss在涨,但train loss已经平台期很久了。此时关键要看val loss的涨是持续性的还是阶段性的。
我在一次训练中遇到过:val loss在3000步内从1.95涨到2.1,然后稳定在2.1不再变化。当时第一反应是过拟合,但检查gap后发现,train loss同样在平台期,gap并没有扩大。后来查出来是验证集在数据预处理过程中被改动过——某个文档字段的格式变了,模型虽然没变,但val loss的计算方式已经不同了。
所以,val loss出现上升趋势时,第一件事是确认验证集本身没有被改动。数据版本管理做得好的团队可以直接从版本对比中排除这个因素;做得不好的团队,往往会在「模型过拟合」的错误方向上浪费大量时间。
6. 构建预警系统:在训练崩溃之前把「生命体征异常」拦截下来
6.1 从「事后复盘」到「实时预警」:监控频率与阈值设计
很多人做训练监控是「事后看曲线」——训练崩了,再看tensorboard找原因。但健康的训练监控应该是「实时预警」——在指标跨过可恢复的临界点之前,系统自动提醒你介入。
监控频率的设计原则是:高频指标看趋势、低频指标看细节。
| 指标 | 采集频率 | 关注的粒度 |
|---|---|---|
| loss、grad norm、param norm | 每50步 | 趋势变化、正常范围判定 |
| layer-wise grad norm | 每500步 | 分布变化、异常层定位 |
| 激活值统计 | 每1000步 | 均值、方差、极值 |
| 验证集loss | 每2000步 | 泛化趋势、gap变化 |
| 吞吐量、显存 | 每10分钟 | 基础设施健康度 |
阈值的设定不要只看绝对值,要结合训练的基线期来设定。我习惯在训练启动后先记录前500步的grad norm滚动均值作为baseline,然后在baseline的2~3倍处设置预警阈值;同理,param norm用baseline的1.5倍作为预警值。这样阈值有「自适应」属性,比固定值要稳妥得多。
6.2 训练体检表:一个可以直接抄的检查清单
结合前几节的内容,我把日常训练中每个阶段需要检查的「生命体征」整理成了一张体检表:
启动期(0~1000步)
- [ ] grad norm是否收敛在一个稳定范围(不是持续发散)?
- [ ] loss是否在按预期的速度下降?
- [ ] 有没有在某个特定step出现NaN或者Inf?
- [ ] 各层的激活值范围是否在合理区间?
- [ ] 数据加载吞吐是否达到预期?
中期(1000步至训练中期)
- [ ] grad norm是否随loss同步下降?
- [ ] layer-wise grad norm分布是否保持稳定?
- [ ] train/val gap是否在合理范围?
- [ ] loss spike的恢复速度是否正常?
- [ ] param norm是否在缓慢增长而不是突变?
- [ ] checkpoints是否按预期保存?
后期(训练后半段)
- [ ] val loss是否已经出现回升?(如果是,考虑提前终止)
- [ ] loss曲线的下降速率是否与学习率调度匹配?
- [ ] loss scale是否稳定?
- [ ] 是否做过最终checkpoint的完整评测?
6.3 异常事件自动响应:从「报警」到「处置」
监控不止是报警,还可以联动处置。我在自己的训练框架里实现了三级响应机制:
- 黄灯(Warning):grad norm超过baseline的2倍,或val loss gap扩大速率异常。自动发送告警到即时通讯工具,不做自动干预。
- 橙灯(Critical):grad norm超过baseline的3倍,或loss出现NaN/Inf。自动暂停训练(保存当前checkpoint后停止),等待人工判断。
- 红灯(Fatal):连续N步无法恢复的训练发散状态。自动回滚到最近一个健康checkpoint,并降低10%的学习率后重新开始。
这套机制在实践中的效果是:大部分「病理性事件」都在橙灯阶段被发现,真正走到红灯回滚的次数很少。关键是它能打断「无人值守」训练中持续恶化的趋势。
提示:自动回滚到上一个checkpoint之后降低学习率的操作,看似简单,实际操作中要注意——不要把问题数据也回滚掉。如果数据源有版本管理,回滚时应当保留当前的训练数据进度,只回滚模型参数和优化器状态。
6.4 推荐的开源工具栈
如果不想重复造轮子,可以用下面这套组合实现训练监控:
- W&B或TensorBoard:基础的曲线记录与可视化
- torch.profiler:定位层级的,检测关键层级的计算瓶颈
- llmonitor或自写hook脚本:周期性采集激活值统计
- 自定义checkpoint回调:实现checkpoint保留与回滚逻辑
- Prometheus + Grafana(可选):适合多机大规模训练的集群级监控,采集GPU利用率、显存、温度、网络通信量
这些工具都不神秘,核心不是工具本身,而是「知道什么时候该看哪个指标」。
7. 诊断后的治疗室:常见异常与干预方案的对应关系
7.1 把「症状」映射到「处方」
以下是我在实际工作中总结的「症状—处方」对应表,可以在一定程度上当成一份速查手册:
| 症状 | 可能的根因 | 处方 |
|---|---|---|
| grad norm持续攀升,loss仍在降 | 浅层学习率过大,或embedding/lm_head与主干学习率不匹配 | 分层学习率衰减,分离embedding/lm_head学习率 |
| loss spike后不恢复 | 学习率超过loss landscape的稳定区间 | 回滚checkpoint,降低学习率20%~50% |
| loss出现NaN | 梯度溢出,或fp16精度下的loss scale异常 | 检查loss scale,考虑bf16训练,检查激活值极值 |
| val loss上升但train loss下降 | 过拟合(早期)或验证集分布偏移(晚期) | 提前停止、增加dropout/weight decay、检查验证集版本 |
| param norm突增 | 权重更新过大或有异常梯度 | 检查grad clip配置,检查是否存在「梯度累积绕过clip」的逻辑 |
| 所有指标正常但生成质量差 | 评测集与训练目标不匹配 | 重新审视评测基准,检查是否有多任务之间的梯度冲突 |
| 持续低吞吐 | 数据加载瓶颈、GPU降频、通信瓶颈 | 用profiler定位,增加dataloader worker,检查NVLink利用率 |
7.2 一次Layer-wise学习率衰减的实战配置
在第3节的案例中,我用了layer-wise learning rate decay(LLRD)来稳定浅层的更新。如果你决定用这个方案,可以参考下面的配置思路:
对于N层Transformer,第i层的学习率可以设为:
lr_i = lr_base * decay_rate^(N - i)其中decay_rate通常取0.85~0.95。decay_rate=0.9表示最浅层的学习率是基础学习率的0.9^(N-1)倍。以13B模型32层Transformer为例,最浅层的学习率约为基础学习率的0.035倍——这个衰减幅度在某些场景下可能过于激进,所以实际使用中建议decay_rate从0.95左右开始尝试。
实现上,在PyTorch中可以用参数分组的方式:
optimizer_grouped_parameters = [] for name, param in model.named_parameters(): if not param.requires_grad: continue # 计算layer index if 'embed_tokens' in name or 'lm_head' in name: layer_idx = 0 # embedding层和输出层单独处理 lr_scale = 0.5 else: # 提取Transformer层的序号 layer_idx = int(name.split('.')[2]) if 'layers' in name else 0 lr_scale = decay_rate ** (num_layers - 1 - layer_idx) optimizer_grouped_parameters.append({ 'params': [param], 'lr': base_lr * lr_scale, 'weight_decay': weight_decay }) optimizer = AdamW(optimizer_grouped_parameters, lr=base_lr, betas=(0.9, 0.98))这段代码的关键点是:embedding层和lm_head层的学习率单独控制,Transformer层按序号线性衰减。实操中还要注意偏置项和LayerNorm参数通常不需要weight decay,设weight_decay=0。
7.3 「指标健康但结果不行」的特殊病例
还有一类情况非常让人头疼:所有「生命体征」都正常——loss稳步下降、grad norm平稳、val loss也在降,但生成出来的文本质量就是不行,或者说模型输出存在「一本正经地胡说八道」的现象。
这种情况下,问题往往不在训练过程本身,而在数据配比和任务设定。我遇到过这样一个病例:一个代码大模型,训练指标一切正常,但生成的代码逻辑混乱。后来排查数据分布才发现,训练集中Python相关数据占比超过80%,而模型实际部署的场景里有大量C++、Go的调用需求——模型在Python上「过拟合」了,即使它在所有训练指标上看起来都很健康。
这个案例说明:「生命体征」反映的是训练过程的稳定性,反映不了训练目标本身是否正确。一旦出现「指标全好但结果不对」的症状,要跳出训练监控层面,回到数据、任务、评测体系上去审视。
8. 最后想说的话:监控的本质是建立「模型运行的上下文理解」
写这篇文章的初衷,是我发现太多人把训练监控当成「看一眼loss」「调一调学习率」这种表面的操作。但真正能让你在训练这条路上走得更远的,不是某个具体的指标阈值,而是对训练过程形成一种整体性的理解——知道每个指标在说什么、它们之间怎样联动、什么样的变化模式预示着什么样的结果。
我自己在跑每个大模型训练任务时,都会先给自己列三个问题:
- 如果只看一个指标来判断训练健康度,我会选哪个?(我的答案是grad norm,不是loss)
- 这个模型最容易出问题的「薄弱器官」在哪?(是浅层还是深层?是embedding还是attention?)
- 当异常出现时,我的第一反应是调参数还是查数据?(答案永远应该是后者)
这三个问题的答案会随着模型规模、数据类型、任务目标而变化,但提问本身是不变的。
训练大模型像照看一个复杂的生命系统。loss只是它的体温,真正决定训练能不能走远、模型能不能用好的,是那些藏在后台、默默变化的「生命体征」。希望这篇文章能帮你在下次打开训练监控面板时,多看到一层别人忽略的信息。