【深度学习】Loss为Nan的可能原因

1. 问题情境

在某个网络架构下,我为某个数据项引入了一个损失函数。
这个数据项是nn.Embedding类型的,我加入的损失函数是对nn.Embedding空间做约束。
因为我在没加入优化loss前,我的nn.Embedding的数据不在同一条直线上,希望通过下面这样一个loss,约束它们在同一条直线上:
在这里插入图片描述
我的变量计算是这么写的:

embedding = self.latent_codes(idx) # 通过nn.Embedding,根据idx获得对应的latent codes
vecs = self.latent_codes.weight.data # 获得所有的latent codes
d1 = torch.sum((vecs[0].unsqueeze(0) - embedding) ** 2, dim=1).sqrt() # 计算第i个latent codes到0的距离
d2 = torch.sum((vecs[len(vecs) - 1].unsqueeze(0) - embedding) ** 2, dim=1).sqrt() # 计算第i个latent codes到-1的距离
standard_distance = torch.dist(vecs[0], vecs[len(vecs) - 1], p=2) # 计算0-(-1)的标准距离

然后loss是这么写的:

latent_space_constraint = torch.abs(d1 + d2 - standard_distance) # 约束三点在一条直线上

结果导致了loss为Nan的情况

2. 原因分析

一开始没啥头绪,然后问了一下通义千问,loss为Nan的可能原因,给出的回答是:
------------------------------------
可能是数值稳定性问题:
新损失项的计算可能导致数值下溢或上溢,特别是在涉及指数函数、对数函数或其他可能导致极端值的数学运算时。
解决方案包括添加一个小的正偏移量(例如 1e-8)来避免除以零或对零取对数,或者使用数值稳定的损失函数实现。
------------------------------------
因为上述代码中,idx=0idx=-1(此处用-1表示最后一个变量)得到的d1/d2可能为0,然后导致latent_space_constraint中对应计算结果为0,这可能是导致Nan的结果

于是我直接在loss上加了一个 λ \lambda λ

latent_space_constraint = torch.abs(d1 + d2 - standard_distance) + 1e-8

但是完全没用,还是会出现Nan的问题,于是我问的第二个问题是:解决方案包括添加一个小的正偏移量(例如 1e-8)来避免除以零或对零取对数,或者使用数值稳定的损失函数实现。这个小的正偏移量是在loss上直接加吗?,给出的回答是:
------------------------------------
在深度学习中,为了避免数值不稳定的情况,比如在损失函数中对非常接近零的数取对数或除以接近零的数,我们确实会添加一个小的正偏移量(常被称为 epsilon)。但是,这个偏移量不是直接加到整个损失函数上,而是加到可能会引起数值不稳定的部分上。

------------------------------------
那么我可能引起数值不稳定的地方实际上是d1/d2/standard_distance,所以把代码修改成在数值计算的时候加小的偏移量

embedding = self.latent_codes(idx) # 通过nn.Embedding,根据idx获得对应的latent codes
vecs = self.latent_codes.weight.data # 获得所有的latent codes
d1 = torch.sum((vecs[0].unsqueeze(0) - embedding) ** 2 + 1e-8, dim=1).sqrt() # 计算第i个latent codes到0的距离
d2 = torch.sum((vecs[len(vecs) - 1].unsqueeze(0) - embedding) ** 2 + 1e-8, dim=1).sqrt() # 计算第i个latent codes到-1的距离
standard_distance = torch.dist(vecs[0], vecs[len(vecs) - 1] + 1e-8, p=2) # 计算0-(-1)的标准距离

解决上述问题,loss计算正常,但是还要考虑的是这个loss会不会导致所有embedding趋向同一个点的情况,还要约束0和-1的latent codes不能过于相似

3. 导致Loss为Nan的其他可能原因

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
当在深度学习模型中加入新的损失项后,特定的权重或参数变为 NaN,这通常指向几个关键的问题区域。对于您的情况,pose_latent_codes 中的特定条目(索引为 0 和 5)在一轮优化后变为 NaN,可能的原因如下:

  1. 特定输入导致的数值不稳定

    • 加入的新损失项可能对某些输入特别敏感,导致计算中出现极大的数值或数值下溢,最终产生 NaN。这可能是因为输入数据中的异常值或不适当的数据预处理。
  2. 梯度爆炸

    • 特定输入或损失计算可能导致针对 pose_latent_codes 的梯度变得非常大,特别是对于索引 0 和 5 的条目。这通常发生在深度神经网络中,尤其是当网络层深且梯度在反向传播过程中累积时。
  3. 正则化或惩罚项

    • 如果新加入的损失项包含正则化项(如 L1 或 L2 正则化),并且正则化强度设置得过高,这可能对某些参数造成过度惩罚,导致 NaN。
  4. 数值计算错误

    • 在新损失项的计算中,可能有某些操作(如除以接近零的数、对负数取对数等)导致了数值不稳定,进而产生 NaN。
  5. 代码错误或实现问题

    • 实现新损失项时可能有代码错误,比如数组索引错误、维度不匹配、数据类型不一致等,这些问题在特定情况下才显现出来,例如针对 pose_latent_codes 的特定条目。

排查和解决方案:

  • 检查输入数据:确认数据预处理步骤,确保没有异常值或不合理的数据点进入模型,特别是在索引 0 和 5 的位置。

  • 梯度裁剪:在优化器中使用梯度裁剪技术,限制梯度的大小,防止梯度爆炸。

  • 降低学习率:尝试降低学习率,以减少每一步更新的幅度,使训练更加稳定。

  • 检查正则化项:如果新损失项包含正则化,尝试降低正则化系数,或检查正则化项的实现是否正确。

  • 数值稳定性改进:在损失计算中加入数值稳定性措施,比如避免除以零、使用 log-sum-exp 技巧避免数值下溢等。

  • 代码审查:仔细审查新损失项的实现代码,确保所有操作都是正确的,没有潜在的逻辑错误或数据类型不匹配。

  • 逐层检查梯度:在训练过程中打印各层的梯度,识别梯度异常增大的层,有助于定位问题所在。

通过上述步骤,您可以逐步排查并解决导致特定权重变为 NaN 的问题。在复杂模型中,问题可能不单一,需要综合多个方面的检查和调整。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

相关推荐

  1. 深度学习(23):SmoothL1Loss损失函数

    2024-06-18 14:42:04       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-18 14:42:04       10 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-18 14:42:04       12 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-18 14:42:04       11 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-18 14:42:04       14 阅读

热门阅读

  1. 查看mysql数据库端口号

    2024-06-18 14:42:04       7 阅读
  2. 美股 — “四巫日”

    2024-06-18 14:42:04       8 阅读
  3. MyBatis 插件机制详解

    2024-06-18 14:42:04       8 阅读
  4. 富格林:可信守则有效防范暗箱

    2024-06-18 14:42:04       8 阅读
  5. 2024.6.17总结1113

    2024-06-18 14:42:04       8 阅读
  6. AI之Lambda index

    2024-06-18 14:42:04       8 阅读
  7. python中的结构

    2024-06-18 14:42:04       7 阅读
  8. 山东大学软件学院深度学习期末回忆版

    2024-06-18 14:42:04       9 阅读
  9. C# Socket通讯简单Demo

    2024-06-18 14:42:04       6 阅读
  10. 数据库分库分表

    2024-06-18 14:42:04       5 阅读