CNN文本二分类训练5轮后训练与验证损失骤升,请问可能原因是什么?
仇恨言论二分类CNN损失突然暴涨的可能原因
- 损失函数与输入维度不匹配:你当前任务是二分类,使用了
nn.CrossEntropyLoss()作为损失函数,该损失要求模型输出维度为2(对应两个类别),且标签输入是形状为[batch_size]的一维张量。但你在训练代码中用torch.unsqueeze(batch.labels, 1)将标签转为了[batch_size, 1]的二维张量,前几个epoch可能因为模型输出分布较散没触发异常,训练到一定阶段后维度不匹配导致损失计算逻辑出错,直接出现异常大值。如果你的模型最终输出维度是1,应该改用nn.BCEWithLogitsLoss()作为损失函数,此时加维度的操作才是匹配的。 - 梯度裁剪失效导致梯度爆炸:虽然你加入了
torch.nn.utils.clip_grad_norm_梯度裁剪逻辑,但如果配置文件中clip参数设置过大(比如远大于1),裁剪操作几乎不会生效。训练到第5个epoch后,梯度过大直接冲爆模型参数,参数变为无穷大或NaN,后续损失计算就会出现异常高值。 - 学习率未设置衰减,后期参数更新幅度过大:你使用的Adam优化器默认学习率为1e-3,且代码中没有加入学习率衰减策略。模型前期收敛顺利,到第5个epoch后进入损失曲面的不稳定区域,过大的学习率会导致单步参数更新直接跳出收敛区间,参数漂移到损失极高的位置。
- 数据迭代器读取到脏数据:前5个epoch迭代器读取的都是正常的标注数据,第6个epoch开始可能读取到了异常样本:比如标签值不是0/1而是极大的数值、文本token id超出词表范围导致embedding查询返回异常值、文本序列长度异常大导致中间计算溢出,都会直接拉高整体epoch损失。
- 数值计算溢出:模型训练到一定阶段后,输出层的logits数值过大,
CrossEntropyLoss内部计算softmax时做exp操作会直接溢出为无穷大,后续对数计算就会得到异常高的损失值。 - 配置读取逻辑错误:你在读取配置时强制所有值先转float,小于1的保留float否则转int,如果配置文件中
clip、学习率这类本该是小于1的浮点值被误存为错误格式,会导致参数转换后变为异常大的数值,触发梯度爆炸或者更新异常。
内容的提问来源于stack exchange,提问作者Ankan Sharma
相关产品推荐
相关产品推荐

