PyTorch中LSTM训练循环反向传播时MSELoss出现NaN问题
LSTM训练出现NaN Loss的问题分析与解决方案
可能原因及对应解决方法
1. 梯度爆炸
LSTM训练时易出现梯度爆炸,即便做了数据归一化,反向传播中梯度仍可能急剧放大,导致参数变为NaN。
解决方法:
- 添加梯度裁剪:在反向传播后限制梯度的最大范数,训练循环中加入:
可根据实际情况调整torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)max_norm(如0.5、2.0)。 - 初始化LSTM权重:手动对LSTM权重做正交初始化,避免初始权重过大:
for name, param in model.lstm.named_parameters(): if 'weight' in name: nn.init.orthogonal_(param)
2. 学习率过高
Adam默认学习率0.001可能适配性差,参数更新幅度过大直接跳到NaN区域。
解决方法:
- 降低学习率:初始化优化器时设置更小的学习率:
可尝试1e-4、5e-5等,逐步调整到合适值。optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
3. 数据残留异常值
即便做了归一化,原始数据中的NaN、无穷大或极端值仍可能导致计算溢出。
解决方法:
- 检查并清理数据:转换张量前先排查异常值:
删除含异常值的样本,或用中位数/均值填充。print(traindf.isna().sum()) print(traindf.describe())
4. 训练循环细节疏漏
比如忘记清零梯度导致梯度累积过大,或计算流程有误。
解决方法:
- 规范训练循环流程:确保每次迭代先清零梯度,流程如下:
model.train() for x, y in train_loader: optimizer.zero_grad() # 必须在迭代开始时清零梯度 outputs = model(x) loss = loss_fn(outputs, y) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) optimizer.step() print(loss.item())
5. 模型输出数值溢出
可验证前向传播的输出范围,确认是否出现极端值:
outputs = model(x) print("Output min:", outputs.min().item(), "Output max:", outputs.max().item())
若输出存在极大值,结合梯度裁剪与学习率调整解决。
内容的提问来源于stack exchange,提问作者user17515752
相关产品推荐
相关产品推荐

