复现论文深度卷积神经网络时交叉熵损失突增为无穷的问题排查
解决CNN训练中交叉熵Loss突增为无穷的问题
我之前复现论文里的CNN模型时,也碰到过几乎一模一样的情况——训练到中途Loss突然蹦到无穷大,准确率却没什么变化。结合你的推测和我的踩坑经验,先给你梳理下可能的原因,再附上你提到的解决方案:
排查方向拆解
1. Adam优化器的数值不稳定问题
Adam虽好用,但参数没调好很容易出问题:
- 学习率过高:如果初始学习率设得太大,训练到第10epoch左右时,参数更新的幅度会越来越夸张,模型输出的logits会出现极端值,经过softmax后要么趋近于0要么趋近于1,这时候计算交叉熵的
log(0)直接就会溢出成无穷大 - epsilon参数过小:Adam里的epsilon是用来防分母为0的,默认的
1e-8在有些场景下不够用,要是你的模型输出数值范围很小,把epsilon调到1e-6左右能避免数值溢出 - 梯度爆炸:可以在训练循环里加个梯度范数的监控,如果某一步梯度的L2范数突然飙升,那就是梯度爆炸导致参数更新异常,进而引发Loss崩了
2. ReLU激活的潜在影响
ReLU本身一般不会直接让Loss变无穷,但可能间接搞事情:
- 神经元死亡:要是大量ReLU神经元一直输出0,模型的表达能力会直接垮掉,后续层的输出可能出现奇怪的数值,最后导致Loss计算溢出
- 可以临时换成LeakyReLU或者GELU试试,看看能不能稳住数值
其他要检查的细节
- 数据异常:确认第10epoch的输入数据是不是出问题了,比如归一化失效、样本损坏,数据炸了模型输出肯定也会炸
- 损失函数实现:如果是自己手写交叉熵,一定要加数值稳定的处理(比如对输出做截断),尽量用框架官方的CrossEntropyLoss实现,它们内部已经做了稳定处理
- 数值监控:在训练时加个打印,看看模型输出的logits有没有NaN或者无穷大,定位是哪一层开始出问题
补充解决方案
最终排查出来的问题是Adam的学习率设置过高,同时交叉熵计算时没做数值截断。具体解决步骤:
- 把Adam的初始学习率从
1e-3降到1e-4,还加了学习率衰减——每5个epoch把学习率降到原来的0.8- 在计算Loss前,对模型输出的logits做截断:
logits = torch.clamp(logits, min=1e-8, max=1-1e-8)(用TensorFlow的话就是tf.clip_by_value)
调整完重新训练,第10epoch后Loss再也没突增,模型稳定收敛,准确率也正常涨起来了
内容的提问来源于stack exchange,提问作者Devin Haslam
相关产品推荐
相关产品推荐

