我注意到在培训期间经常出现NAN
。
通常,内部产品/完全连接或卷积层中的重量似乎会被引入。
这是因为梯度计算正在爆发吗?或者是因为重量初始化(如果是这样,为什么重量初始化有这种效果)?或者它可能是由输入数据的性质引起的?
这里的首要问题很简单:培训期间NAN发生的最常见原因是什么?其次,有什么方法可以解决这个问题(以及为什么会这样做?)
答案 0 :(得分:100)
好问题。
我多次遇到过这种现象。以下是我的观察:
原因:大型渐变会使学习过程偏离正轨。
您应该期待什么:查看运行时日志,您应该查看每次迭代的损失值。您会注意到,从迭代到迭代,损失开始显着显着,最终损失将太大而无法由浮点变量表示,它将变为nan
。
你能做什么:将base_lr
(在solver.prototxt中)降低一个数量级(至少)。如果您有多个损失图层,则应检查日志以查看哪个图层对渐变爆炸负责,并减少该特定图层的loss_weight
(在train_val.prototxt中),而不是通用{{1} }。
原因: caffe无法计算有效的学习率,而是获得base_lr
或'inf'
,此无效率会使所有更新倍增,从而使所有参数无效。
您应该期待什么:查看运行时日志,您应该会看到学习率本身变为'nan'
,例如:
'nan'
您可以做什么:修复影响... sgd_solver.cpp:106] Iteration 0, lr = -nan
文件中学习率的所有参数。
例如,如果您使用'solver.prototxt'
而忘记定义lr_policy: "poly"
参数,则最终会得到max_iter
...
有关caffe学习率的更多信息,请参阅this thread。
原因:有时,损失层中损失的计算会导致显示lr = nan
个。例如,使用带有错误的自定义丢失层等提供InfogainLoss
layer with non-normalized values
您应该期待什么:查看运行时日志,您可能不会注意到任何异常:丢失逐渐减少,并且突然出现nan
。
你能做什么:看看你是否可以重现错误,将打印输出添加到损失层并调试错误。
例如:一旦我使用了一个损失,通过批量中标签出现的频率来规范惩罚。碰巧的是,如果其中一个训练标签没有出现在批次中 - 计算的损失产生了nan
s。在这种情况下,使用足够大的批次(相对于集合中的标签数量)足以避免此错误。
原因:您的输入中包含nan
!
你应该期待什么:一旦学习过程“命中”这个错误的输入 - 输出变为nan
。查看运行时日志,您可能不会注意到任何异常:丢失逐渐减少,并且突然出现nan
。
您可以做什么:重新构建输入数据集(lmdb / leveldn / hdf5 ...)确保您的训练/验证集中没有错误的图像文件。对于调试,你可以构建一个简单的网络来读取输入层,在它上面有一个虚拟损失并贯穿所有输入:如果其中一个有问题,这个虚拟网络也应该产生nan
。
nan
层出于某种原因,选择"Pooling"
>用于汇总的stride
可能会导致kernel_size
s。例如:
nan
layer {
name: "faulty_pooling"
type: "Pooling"
bottom: "x"
top: "y"
pooling_param {
pool: AVE
stride: 5
kernel: 3
}
}
中nan
的结果
y
据报道,由于数值不稳定,在某些设置下"BatchNorm"
图层可能会输出"BatchNorm"
。
这个issue是在bvlc / caffe中引发的,PR #5136正在尝试修复它。
最近,我开始意识到debug_info
标记:在nan
中设置debug_info: true
会在训练期间记录更多的调试信息(包括渐变幅度和激活值):此信息可以help in spotting gradient blowups and other problems in the training process。
答案 1 :(得分:3)
这个答案不是nan
的原因,而是提出一种帮助调试它的方法。
你可以拥有这个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
}
}
答案 2 :(得分:3)
在我的情况下,没有在卷积/反卷积层中设置偏差是原因。
解决方案:将以下内容添加到卷积层参数中。
bias_filler { 类型:“常数” 值:0 }
答案 3 :(得分:0)
learning_rate很高,应该降低 RNN代码的精度是nan,请选择较低的学习率值
答案 4 :(得分:-1)
我正在尝试构建一个稀疏的自动编码器,并在其中有几个层来诱导稀疏性。在运行我的网时,我遇到了NaN的。在删除一些层(在我的情况下,我实际上必须删除1),我发现NaN消失了。所以,我猜太多的稀疏性也可能导致NaN的问题(可能会调用一些0/0计算!?)