培训期间的常见原因
我注意到训练中频繁发生的是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计算被调用!)