2023年11月29日发(作者:)

keras训练出现nan的解决流程

出现nan可能是在train的loss阶段,也可能是train的metric阶段,还可能是validation阶段,反正都⼀样。

在写毕设的过程⾥⾯,⽤学弟提取的特征做DNN的训练,loss没有出现nan,但是反⽽是metric(MSE)⾥⾯出现了nan,predict的结果

===========================================================================

相关参考:

参考1:

前⾔

训练或者预测过程中经常会遇到训练损失值或者验证损失值不正常、⽆穷⼤、或者直接nan的情况:

遇到这样的现象,通常有以下⼏个原因导致:

梯度爆炸造成Loss爆炸

learningRate过⼤不仅可能会导致模型在最优点附近震荡,还有可能造成NAN

原因很简单,学习率较⾼的情况下,直接影响到每次更新值的程度⽐较⼤,⾛的步伐因此也会⼤起来。如下图,过⼤的学习率会导致⽆法顺

利地到达最低点,稍有不慎就会跳出可控制区域,此时我们将要⾯对的就是损失成倍增⼤(跨量级)。

(利⽤debug寻找错误的输⼊)

在神经⽹络中,很有可能在前⼏层的输⼊是正确的,但是到了某⼀层的时候输出就会变成nan或者inf(其中-inf代表负⽆穷,⽽nan代表不存在

的数),这个时候就需要通过debug去⼀⼀检查。

当然我们可以在⾃⼰代码中添加检测函数。

例如在Pytorch框架中我们可以使⽤_anomaly类来监测训练或者预测过程中遇到的隐晦的问题:

>>> import torch

>>> from torch import autograd

>>> class MyFunc(on):

... @staticmethod

... def forward(ctx, inp):

... return ()

... @staticmethod

损失函数可能不正确

损失函数也是有可能导致输出nan,尤其是在我们⾃⼰设计损失函数的时候。

损失函数应该考虑到是否可以正常地backward

其次对输⼊的Tensor是否进⾏了类型转化,保证计算中保持同⼀类型。

最后考虑在除数中加⼊微⼩的常数保证计算稳定性。

batchNorm可能捣⿁

如果你的⽹络中batchNorm层很多,⽽且充当⽐较重要的⾓⾊,那么可以适当地检查⼀下Tensor在输⼊Batchnorm层后有没有可能变

nan,如果恰好发⽣这种情况,batchNorm层中的移动均值(running_mean)和移动⽅差(running_var)也很有可能都是nan,⽽且这种情

况很有可能发⽣在预测阶段。

这种情况通过发⽣在训练集和验证集是两个截然不同的分布的时候,这是在训练集中学习到的均值和⽅法在验证集中是没有作⽤反⽽会捣

乱。或者在⼀个神经⽹络中存在两种结构不同的阵营:典型的是Unet,当在⾃定义Unet的时候,编码⽹络和解码⽹络如果是两个结构存在

较⼤差异的⽹络,那么在编码阶段学习到的分布在解码阶段就会出现问题。

举个真实的例⼦:Unet + resnet34 表现正常,但是使⽤Unet + resnext50 则造成损失爆炸(将解码阶段的batchnorm层失效后表现正

常)。

当然上述现象出现的原因⼤部分在当我们使⽤()(Pytorch)之后发⽣。如果你在预测阶段也将模型model设置

(True),那么问题可能就不会出现:

解决⽅式:

或者设置Batchnorm中的参数track_running_stats=False使移动均值和移动⽅差不起作⽤:

相关的问题:

采⽤stride⼤于kernel size的池化层

在卷积层的卷积步伐⼤于卷积核⼤⼩的时候,有可能产⽣nan

⽐如:

layer {

name: "faulty_pooling"

type: "Pooling"

bottom: "x"

top: "y"

pooling_param {

pool: AVE

stride: 5

kernel: 3

}

}

第⼆种情况: