培训期间的常见原因

我注意到训练中频繁发生的是NAN s的引入。

通常情况下,似乎是通过内部产品/完全连接或卷积层吹起来的重量来引入的。

这是否发生,因为梯度计算正在炸毁? 或者是因为重量初始化(如果是的话,为什么重量初始化有这个效果)? 或者这可能是由input数据的性质造成的?

这里最重要的问题是: 在训练期间发生NAN的最常见原因是什么? 其次,有什么方法来打击这个(为什么他们工作)?

好问题。
我多次遇到这种现象。 这是我的观察:


梯度炸毁

原因:大梯度会导致学习过程偏离轨道。

你应该期待什么:看运行日志,你应该看看每次迭代的损失值。 你会注意到,从迭代到迭代的损失开始显着增长,最终损失将会太大而不能用浮点variables来表示,并且会变成nan

你能做什么:base_lr (在solver.prototxt中)减less一个数量级(至less)。 如果您有多个丢失图层,则应该检查日志以查看哪个图层负责渐变爆炸,并减less该特定图层的loss_weight (在train_val.prototxt中),而不是一般的base_lr


糟糕的学习率政策和参数

原因: caffe未能计算出有效的学习率,而是获得'inf''nan' ,这个无效的比率将所有更新乘以,从而使所有参数无效。

你应该期望:看运行时日志,你应该看到,学习速度本身变成'nan' ,例如:

 ... sgd_solver.cpp:106] Iteration 0, lr = -nan 

你可以做什么:修复影响你的'solver.prototxt'文件的学习率的所有参数。
例如,如果您使用lr_policy: "poly"而您忘记定义max_iter参数,则最终将以lr = nan
有关caffe学习率的更多信息,请参阅此主题 。


错误的丢失function

原因:有时丢失层的损失的计算导致nan s出现。 例如,Feeding InfogainLoss图层具有非标准值 ,使用自定义丢失图层和bug等。

你应该期待什么:看运行时日志,你可能不会注意到任何exception情况:丢失正在逐渐减less,突然之间出现一个“ nan ”。

你能做什么:看看你是否可以重现错误,添加打印到损失层和debugging错误。

例如:一旦我使用了一个标签发生频率标准化处罚的损失。 恰好如此,如果其中一个培训标签完全没有出现在批次中 – 计算出的损失就会产生nan s。 在这种情况下,处理足够大的批次(就集合中的标签数量而言)就足以避免这个错误。


错误的input

原因:你有一个inputnan

你应该期待什么:一旦学习过程“击中”这个错误的input – 输出成为nan 。 看运行时日志,你可能不会注意到任何exception情况:丢失正在逐渐减less,突然之间出现一个“ nan ”。

你可以做什么:重新build立你的input数据集(lmdb / leveldn / hdf5 …),确保你的训练/validation集没有错误的图像文件。 对于debugging,你可以build立一个简单的networking读取input层,在它上面有一个虚拟的损失,并贯穿所有的input:如果其中一个错误,这个虚拟networking也应该产生nan


"Pooling"层中跨越大于内核大小

出于某种原因,selectstride > kernel_size进行池化可能会导致nan s。 例如:

 layer { name: "faulty_pooling" type: "Pooling" bottom: "x" top: "y" pooling_param { pool: AVE stride: 5 kernel: 3 } } 

结果与nan s在y


"BatchNorm"不稳定

据报道,在一些设置下,由于数值不稳定性, "BatchNorm"层可能会输出nan
这个问题在bvlc / caffe提出, PR#5136正在尝试修复它。


最近,我意识到'solver.prototxt'标志:在'solver.prototxt'设置'solver.prototxt' debug_info: true将使caffe print在训练过程中logging更多的debugging信息(包括梯度幅值和激活值):这些信息可以帮助识别梯度膨胀和其他问题在训练过程中 。

在我的情况下,不在卷积/去卷积层中设置偏差是原因。

解决scheme:将以下内容添加到卷积图层参数中。

bias_filler {types:“常量”值:0}

这个答案不是关于nan s的原因,而是提出一种帮助debugging的方法。 你可以有这个python层:

 class checkFiniteLayer(caffe.Layer): def setup(self, bottom, top): self.prefix = self.param_str def reshape(self, bottom, top): pass def forward(self, bottom, top): for i in xrange(len(bottom)): isbad = np.sum(1-np.isfinite(bottom[i].data[...])) if isbad>0: raise Exception("checkFiniteLayer: %s forward pass bottom %d has %.2f%% non-finite elements" % (self.prefix,i,100*float(isbad)/bottom[i].count)) def backward(self, top, propagate_down, bottom): for i in xrange(len(top)): if not propagate_down[i]: continue isf = np.sum(1-np.isfinite(top[i].diff[...])) if isf>0: raise Exception("checkFiniteLayer: %s backward pass top %d has %.2f%% non-finite elements" % (self.prefix,i,100*float(isf)/top[i].count)) 

将这个图层添加到您的train_val.prototxt ,您怀疑某些点可能会导致麻烦:

 layer { type: "Python" name: "check_loss" bottom: "fc2" top: "fc2" # "in-place" layer python_param { module: "/path/to/python/file/check_finite_layer.py" # must be in $PYTHONPATH layer: "checkFiniteLayer" param_str: "prefix-check_loss" # string for printouts } } 

我试图build立一个稀疏的自动编码器,并在其中有几个层次来诱导稀疏。 在运行我的networking时,我遇到了NaN。 去掉一些图层(在我的情况下,我实际上不得不删除1),我发现NaN消失了。 所以,我猜太多稀疏也可能导致NaN(也许有一些0/0计算被调用!)