深度学习问题检查——训练出现nan, loss不降

本文深入探讨了深度学习训练过程中常见的两大难题:训练出现nan的原因及解决方案,包括数据检查、参数调整、梯度截断等;以及训练loss不降的原因分析,如学习率不当、数据集问题、网络结构设计等,并提供了详细的排查步骤和调整建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、训练出现nan的原因

https://blog.csdn.net/ch07013224/article/details/80324373

1,检查数据。数据的label有无错误。 制作lst修改过标签

2,检查参数。保存的网络层和损失层所有的参数

3,检查是否有分母为0,或者log里为负数或者0,softmax里的exp是否太大,

根号是否有负数

 

1.如果在迭代的100轮以内,出现NaN,一般情况下的原因是因为你的学习率过高,需要降低学习率。可以不断降低学习率直至不出现NaN为止,一般来说低于现有学习率1-10倍即可。

2.如果当前的网络是类似于RNN的循环神经网络的话,出现NaN可能是因为梯度爆炸的原因,一个有效的方式是增加“gradient clipping”(梯度截断来解决)

3.可能用0作为了除数;

4.可能0或者负数作为自然对数

5.需要计算loss的数组越界(尤其是自己,自定义了一个新的网络,可能出现这种情况)

6.在某些涉及指数计算,可能最后算得值为INF(无穷)(比如不做其他处理的softmax中分子分母需要计算exp(x),值过大,最后可能为INF/INF,得到NaN,此时你要确认你使用的softmax中在计算exp(x)做了相关处理(比如减去最大值等等))

 

1,是否有脏数据

可能有,因为大的数据集还没有训练完成一遍.

2,log出现负数

 

 

二、训练loss不降得原因

https://blog.csdn.net/liuweiyuxiang/article/details/80856991

train loss 不断下降,test loss不断下降,说明网络仍在学习; 

train loss 不断下降,test loss趋于不变,说明网络过拟合; 

train loss 趋于不变,test loss不断下降,说明数据集100%有问题; 

train loss 趋于不变,test loss趋于不变,说明学习遇到瓶颈,需要减小学习率或批量数目; 

train loss 不断上升,test loss不断上升,说明网络结构设计不当,训练超参数设置不当,数据集经过清洗等问题。

 

loss不降,不收敛问题检查过程:

  • 静态检查:

1,输入数据检查

1)是否输入有脏数据

2)是否输入数据label有错误

2,网络模型检测、损失检查

1)模型和损失是否合理,是否符合论文中公式

2)模型和损失初始化是否合理

  • 动态检查

1,是否梯度有更新

1)学习率是否过大或者过小,不合适——》选择合适的学习率和学习算法

2)打印网络,观察网络中各个层的参数是否变化

  • 迁移框架检查

1,不同框架,输入数据、模型框架、损失、参数是否一致——》参考旧框架参数

1)同一个训练集、验证集

2)同一个框架LResnet50e-IR

3) 损失 cosface/

4) 参数:优化算法,batch-norm等参数

2,不同框架,模型优化流程等是否有问题

1)sgd是如何同时更新损失中的参数和网路中的参数

3,迁移框架版本问题——》参考新框架官网文档

1)pytorch0.4~1.0问题

不同版本是否有问题

2)参考官网代码,修改官方代码

亲身实验:pytorch上LResnet50E-IR + cosface 训练不收敛原因

1,数据集问题:训练数据集没有正确检测和对齐

2,没有将loss的优化加入优化器里

3,model验证完之后忘了转回训练模式(模型里有batchnorm和dropout会出问题),model.train和model.eval相互转化,——可以解释每次eval结果会不稳定的原因

4,cosface的尺度参数s传入为1,所以开始优化下降到10就不变化,因为8万label半径为1很难训练啊!!!

 

### 深度学习模型中 `RuntimeWarning: Mean of empty slice` 和 `invalid value encountered in divide` 的解决方法 在深度学习项目中,经常会遇到由 NumPy 或 PyTorch 提供的警告消息,例如 `RuntimeWarning: Mean of empty slice` 和 `invalid value encountered in divide`。这类问题通常是由数据质量问题、张量操作不当或模型设计缺陷引起的。 #### 一、问题的根本原因 1. **`Mean of empty slice`** 当尝试对一个空数组或张量求均值,NumPy 或 PyTorch 将触发此警告。这可能发生在以下场景: - 数据集中某些类别的标注缺失。 - 预测结果为空集合(即没有任何检测到的目标)[^1]。 2. **`invalid value encountered in divide`** 此警告表明在执行除法运算遇到了无效值(如零或 NaN)。常见原因是分母为零,尤其是在计算 Precision、Recall 或其他基于比率的指标[^4]。 --- #### 二、解决方案 ##### 方法 1:修改代码以安全处理潜在错误 为了防止这些警告中断程序运行,可以在关键位置引入保护机制。 ###### (1)对于 `Mean of empty slice` 在调用 `.mean()` 前检查输入是否为空: ```python import numpy as np def safe_mean(tensor): if isinstance(tensor, np.ndarray): # 如果是 NumPy 数组 if tensor.size == 0: return 0 # 返回默认值 elif isinstance(tensor, torch.Tensor): # 如果是 PyTorch 张量 if tensor.numel() == 0: return torch.tensor(0, dtype=tensor.dtype, device=tensor.device) return tensor.mean() ``` ###### (2)对于 `invalid value encountered in divide` 在执行除法前确保分母不为零: ```python epsilon = 1e-8 # 添加一个小常数避免除零 precision = numerator / (denominator + epsilon) recall = true_positive / (true_positive + false_negative + epsilon) ``` --- ##### 方法 2:全局禁用特定警告 如果不希望看到这些警告信息,可以临屏蔽它们。但这只是治标之策,应谨慎使用。 ```python np.seterr(divide='ignore', invalid='ignore') # 屏蔽 NumPy 警告 torch.set_num_threads(1) # 对于 PyTorch 可能需要额外配置线程优化 ``` --- ##### 方法 3:清理和验证数据质量 许多警告来源于不良数据。因此,在训练之前应对数据进行全面检查和预处理。 ###### (1)移除无效样本 如果发现某些样本存在问题(如标注丢失或特征维度异常),可以直接将其剔除。参考如下实现: ```python self.x_train_temp = x_train.numpy() self.y_train_temp = y_train.numpy() del_list = [idx for idx, sample in enumerate(self.x_train_temp) if sample.shape != target_shape] self.x_train_temp = np.delete(self.x_train_temp, del_list, axis=0) self.y_train_temp = np.delete(self.y_train_temp, del_list, axis=0) self.x_train = torch.from_numpy(self.x_train_temp).float() self.y_train = torch.from_numpy(self.y_train_temp).long() ``` ###### (2)填充缺失值 另一种选择是对缺失值进行插补而非简单删除: ```python from sklearn.impute import SimpleImputer imputer = SimpleImputer(strategy="mean") # 使用均值填补 data_cleaned = imputer.fit_transform(data_raw) ``` --- ##### 方法 4:监控模型中间状态 即使解决了上述警告,仍需进一步确认模型是否按预期工作。为此可定期打印重要变量的状态: ```python if epoch % log_interval == 0: print(f"Epoch {epoch}: Loss={loss.item()}, Accuracy={accuracy}") # 打印梯度范数以防爆炸或消失现象 for name, param in model.named_parameters(): if param.grad is not None: grad_norm = param.grad.norm().item() print(f"{name} gradient norm: {grad_norm}") ``` --- ### 结论 通过以上措施能够有效消除大部分与 `RuntimeWarning` 相关的问题,并保障模型平稳运行。然而需要注意的是,单纯压制警告并不能彻底根除隐患——只有从根本上改善数据质量和算法逻辑才能达到最佳效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eva_Hua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值