caffe参数调节问题及解决方法

深度学习交流QQ群:116270156

一、caffe训练时Loss变为nan的原因

本节转载于公众号平台:极市平台

1、梯度爆炸

原因:梯度变得非常大,使得学习过程难以继续

现象:观察log,注意每一轮迭代后的loss。loss随着每轮迭代越来越大,最终超过了浮点型表示的范围,就变成了NaN。 
措施: 
1. 减小solver.prototxt中的base_lr,至少减小一个数量级。如果有多个loss layer,需要找出哪个损失层导致了梯度爆炸,并在train_val.prototxt中减小该层的loss_weight,而非是减小通用的base_lr。 
2. 设置clip gradient,用于限制过大的diff

2、不当的损失函数

原因:有时候损失层中loss的计算可能导致NaN的出现。比如,给InfogainLoss层(信息熵损失)输入没有归一化的值,使用带有bug的自定义损失层等等。

现象:观测训练产生的log时一开始并不能看到异常,loss也在逐步的降低,但突然之间NaN就出现了。 
措施:看看你是否能重现这个错误,在loss layer中加入一些输出以进行调试。 
示例:有一次我使用的loss归一化了batch中label错误的次数。如果某个label从未在batch中出现过,loss就会变成NaN。在这种情况下,可以用足够大的batch来尽量避免这个错误。

3、不当的输入

原因:输入中就含有NaN。

现象:每当学习的过程中碰到这个错误的输入,就会变成NaN。观察log的时候也许不能察觉任何异常,loss逐步的降低,但突然间就变成NaN了。 
措施:重整你的数据集,确保训练集和验证集里面没有损坏的图片。调试中你可以使用一个简单的网络来读取输入层,有一个缺省的loss,并过一遍所有输入,如果其中有错误的输入,这个缺省的层也会产生NaN。 
案例:有一次公司需要训练一个模型,把标注好的图片放在了七牛上,拉下来的时候发生了dns劫持,有一张图片被换成了淘宝的购物二维码,且这个二维码格式与原图的格式不符合,因此成为了一张“损坏”图片。每次训练遇到这个图片的时候就会产生NaN。 
良好的习惯是,你有一个检测性的网络,每次训练目标网络之前把所有的样本在这个检测性的网络里面过一遍,去掉非法值。

4、池化层中步长比核的尺寸大

如下例所示,当池化层中stride > kernel的时候会在y中产生NaN


     
     
     
     
  1. layer {
  2. name: ”faulty_pooling”
  3. type: ”Pooling”
  4. bottom: ”x”
  5. top: ”y”
  6. pooling_param {
  7. pool: AVE
  8. stride: 5
  9. kernel: 3
  10. }
  11. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

http://stackoverflow.com/questions/33962226/common-causes-of-NaNs-during-training


.

二、一些训练时候出现的问题

本节转载于公众号深度学习大讲堂,文章《caffe代码夜话1》

1、为啥label需要从0开始?

在使用SoftmaxLoss层作为损失函数层的单标签分类问题中,label要求从零开始,例如1000类的ImageNet分类任务,label的范围是0~999。这个限制来自于Caffe的一个实现机制,label会直接作为数组的下标使用,具体代码SoftmaxLoss.cpp中133行和139行的实现代码。

caffe参数调节问题及解决方法_第1张图片

132行第一层for循环中的outer_num等于batch size,对于人脸识别和图像分类等单标签分类任务而言,inner_num等于1。如果label从1开始,会导致bottom_diff数组访问越界。 
.

2、为什么Caffe中引入了这个inner_num,inner_num等于什么

从FCN全卷积网络的方向去思考。FCN中label标签长度=图片尺寸 
caffe引入inner_num使得输入image的size可以是任意大小,innuer_num大小即为softmax层输入的height*width 
.

3、在标签正确的前提下,如果倒数第一个全连接层num_output > 实际的类别数,Caffe的训练是否会报错?

不会报错且无影响 
.

4、BN中的use_global_status

caffe参数调节问题及解决方法_第2张图片 
图2. ResNet部署阶模型Proto文件片段

但是如果直接拿这个Proto用于训练(基于随机初始化),则会导致模型不收敛,原因在于在Caffe的batch_norm_layer.cpp实现中,use_global_stats==true时会强制使用模型中存储的BatchNorm层均值与方差参数,而非基于当前batch内计算均值和方差。

首先看use_global_stats变量是如何计算的: 
这里写图片描述 
图3. use_global_stats计算

再看这个变量的作用: 
caffe参数调节问题及解决方法_第3张图片 
图4. use_global_stats为true时的行为

以下代码在use_global_stats为false的时候通过moving average策略计算模型中最终存储的均值和方差: 
caffe参数调节问题及解决方法_第4张图片 
图5. BatchNorm层均值和方差的moving average

因此,对于随机初始化训练BatchNorm层,只需要在Proto文件中移除use_global_stats参数即可,Caffe会根据当前的Phase(TRAIN或者TEST)自动去设置use_global_stats的值。 
.

5、BatchNorm层是否支持in place运算,为什么?

BN是对输入那一层做归一化操作,要对每个元素-均值/标准差,且输入输出规格相当,是可以进行in place。 
标准的ReLU函数为max(x, 0),而一般为当x > 0时输出x,但x <= 0时输出negative_slope。RELU层支持in-place计算,这意味着bottom的输出和输入相同以避免内存的消耗。 

.

三、过拟合解决:dropout、batch Normalization

来源于:https://github.com/exacity/deeplearningbook-chinese/releases/

1、dropout——另类Bagging(类似随机森林RF)

引用自Dropout作者: 
在标准神经网络中,每个参数接收的导数表明其应该如何变化才能使最终损失函数降低,并给定所有其它神经网络单元的状态。因此神经单元可能以一种可以修正其它神经网络单元的错误的方式进行改变。而这就可能导致复杂的共适应(co-adaptations)。由于这些共适应现象没有推广到未见的数据,将导致过拟合。我们假设对每个隐藏层的神经网络单元,Dropout通过使其它隐藏层神经网络单元不可靠从而阻止了共适应的发生。因此,一个隐藏层神经元不能依赖其它特定神经元去纠正其错误。(来源:赛尔译文 Dropout分析)

Dropout可以被认为是集成非常多的大神经 网络的实用Bagging方法。当每个模型是一个大型神经网络时,这似乎是不切实际的,因为训练和 评估这样的网络需要花费很多运行时间和内存。 
Dropout提供了一种廉价的Bagging集成近似,能够训练和评估指数级的神经网络。 
操作方法:将一些单元的输出乘零就能有效地删除一个单元。

caffe参数调节问题及解决方法_第5张图片

(1)具体工作过程:

Dropout以概率p关闭神经元,相应的,以大小为q=1-p的概率开启其他神经元。每个单个神经元有同等概率被关闭。当一个神经元被丢弃时,无论其输入及相关的学习参数是多少,其输出都会被置为0。 
丢弃的神经元在训练阶段的前向传播和后向传播阶段都不起作用:因为这个原因,每当一个单一的神经元被丢弃时,训练阶段就好像是在一个新的神经网络上完成。 
训练阶段,可以使用伯努利随机变量、二项式随机变量来对一组神经元上的Dropout进行建模。 
(来源:赛尔译文 Dropout分析) 
caffe参数调节问题及解决方法_第6张图片

(2)dropout类型: 
正向dropout、反向dropout。 
反向Dropout有助于只定义一次模型并且只改变了一个参数(保持/丢弃概率)以使用同一模型进行训练和测试。相反,直接Dropout,迫使你在测试阶段修改网络。因为如果你不乘以比例因子q,神经网络的输出将产生更高的相对于连续神经元所期望的值(因此神经元可能饱和):这就是为什么反向Dropout是更加常见的实现方式。

(3)dropout与其他规则

故反向Dropout应该与限制参数值的其他归一化技术一起使用,以便简化学习速率选择过程

正向Dropout:通常与L2正则化和其它参数约束技术(如Max Norm1)一起使用。正则化有助于保持模型参数值在可控范围内增长。 
反向Dropout:学习速率被缩放至q的因子,我们将其称q为推动因子(boosting factor),因为它推动了学习速率。此外,我们将r(q)称为有效学习速率(effective learning rate)。总之,有效学习速率相对于所选择的学习速率更高:由于这个原因,限制参数值的正则化可以帮助简化学习速率选择过程。 
(来源:赛尔译文 Dropout分析)

(4)优势:

  • 看作是对输入内容的信息高度智能化、自适应破坏的一种形式,而不是 对输入原始值的破坏。

  • Dropout不仅仅是训练一个Bagging的集成模型,并且是共享隐藏单元的集成模型。这意味着无论其他隐藏单元是否在模型中,每个隐藏单元必须都能够表现良好。隐藏单元必须准备好进行模型之间的交换和互换。

  • 计算方便是Dropout的一个优点。训练过程中使用Dropout产生 n 个随机二进制 数与状态相乘,每个样本每次更新只需 O(n)的计算复杂度。

  • Dropout的另一个显著优点是不怎么限制适用的模型或训练过程。几乎在所有 使用分布式表示且可以用随机梯度下降训练的模型上都表现很好。包括前馈神经网 络、概率模型,如受限玻尔兹曼机(Srivastava et al., 2014),以及循环神经网络(Bayer and Osendorfer, 2014; Pascanu et al., 2014a)。许多其他差不多强大正则化策略对模 型结构的限制更严格。

(5)劣势:

  • Dropout是一个正则化技术,它减少了模型的有效容量。为了抵消这种影响,我们必须增大模型规模。不出意外的话,使 用Dropout时最佳验证集的误差会低很多,但这是以更大的模型和更多训练算法的迭 
    代次数为代价换来的。对于非常大的数据集,正则化带来的泛化误差减少得很小。在 
    这些情况下,使用Dropout和更大模型的计算代价可能超过正则化带来的好处。

  • 只有极少的训练样本可用时,Dropout不会很有效。在只有不到 5000 的样本 的Alternative Splicing数据集上 (Xiong et al., 2011),贝叶斯神经网络 (Neal, 1996)比Dropout表现更好 
    (Srivastava et al., 2014)。当有其他未分类的数据可用时,无监 督特征学习比Dropout更有优势。 
    .

2、batch Normalization

batch normalization的主要目的是改善优化,但噪音具有正则化的效果,有时使Dropout变得没有必要。 
参数训练过程中多层之间协调更新的问题:在其他层不改变的假设下,梯度用于如何更新每一个参数。但是,一般情况下会同时更新所有层。 这造成了很难选择一个合适的学习速率,因为某一层中参数更新的效果很大程度上取决 于其他所有层。 
batch normalization可应用于网络 的任何输入层或隐藏层。设 H 是需要标准化的某层的minibatch激励函数,布置为 设计矩阵,每个样本的激励出现在矩阵的每一行中。标准化 H,我们替代它为 
这里写图片描述 
其中 μ 是包含每个单元均值的向量,σ 是包含每个单元标准差的向量。 
反向传播这些操作,计算均值和标准差,并应用它们于标准化 H。这意味着,梯度不会再简单地增加 hi 的标准差或均值;标准化操作会 除掉这一操作的影响,归零其在梯度中的元素。

以前的方法添加代价函数的惩罚,以鼓励单位标准化激励统计量,或是 在每个梯度下降步骤之后重新标准化单位统计量。 
前者通常会导致不完全的标准化, 而后者通常会显著地消耗时间,因为学习算法会反复改变均值和方差而标准化步骤 会反复抵消这种变化。 
batch normalization重新参数化模型,以使一些单元总是被定 义标准化,巧妙地回避了这两个问题。

            

你可能感兴趣的:(caffe参数调节问题及解决方法)