0%

DCNN-trick

深度神经网络中的实现细节(技巧Or提示)

1. 数据增强

由于深度网络需要在大量训练图像上进行训练以获得令人满意的性能,如果原始图像数据集包含有限的训练图像,则最好进行数据增强以提高性能。此外,数据扩充称为培训深层网络时必须要做的事情。

  • 有许多方法可以进行数据增强,例如流行的水平翻转随机裁剪颜色抖动。此外,还可以尝试许多不同处理的组合,例如同时进行旋转和放缩。此外,还可以尝试将所有色素的饱和度 和 值(HSV颜色空间中的S和V的分量)提高到0.25到4之间的power(对于补丁中的所有像素都相同),将这些值乘以0.7~1.4之间的系数,并且加上一个介于-0.1到0.1之间的值。此外,还可以在[-0.1, 0.1]之间添加一个值到图像/补丁中所有像素的H值(HSV的H分量)
  • Krizhevsky等人在训练著名的Alex-Net时提出了FancyPCAFancy PCAFancyPCAFancy PCA改变了训练图像中的RGB通道的强度。实际上,可以在整个训练图像中首先对RGB像素值集执行PCA。然后,对于每一个训练图像,只添加以下量的每个RGB图像的像素(例如: Ixy=[IxyR,IxyG,IxyB]T]:[P1,P2,P3][α1λ1,α2λ2,α3λ3]TI_{xy}=[I_{xy}^R, I_{xy}^G, I_{xy}^B]^{T}] : [P_{1}, P_{2}, P_{3}] [\alpha_{1} \lambda_{1}, \alpha_{2} \lambda_{2}, \alpha_{3} \lambda_{3}]^{T}),其中PiP_{i}λi\lambda_{i}分别是RGB像素值的3 * 3协方差矩阵的第 i 个本征向量和特征值,αi\alpha_{i}是具有平均值0和标准差0.1的高斯绘制的随机变量。请注意,每个αi\alpha_{i}仅针对特定训练图像的所有像素绘制一次,直到该图像再次用于训练。也就是说,当模型再次遇到相同的训练图像时,它会随机产生另一个αi\alpha_{i}用于数据增强。在ImageNet Classification with Deep Convolutional Neural Networks中,他们声称Fancy PCA可以近似捕获自然图像的重要特性,即物体特性对于照明强度和颜色的变化是不变的。对于分类性能,该方案在ImageNet 2012的竞争中将前1个错误率降低了1%以上。

2. 对图像进行预处理

现在我们已经获得了大量的训练样本(图像/作物),但是不要着急。实际上,有必要对这些图像进行预处理。介绍下列几种预处理方法:

  • zero-center the data, and then normalize them,在Python中就是以下两行代码:

    1
    2
    X -= np.mean(X, axis=0)	# zero-center
    X /= np.std(X, axis=0) # normalize

    其中,X是输入数据。该预处理的另一种形式是对每个维度进行归一化,使得沿维度的最小值和最大值分别为-1 和 1。 如果您有理由相信不同的输入要素具有不同的比例(或单位),则应用此预处理才是有意义的,但他们应该与学习算法具有大致相同的重要性。在图像的情况下,像素的相对比例已经近似相等(并且在0-255范围之内),因此不必严格地执行该附加的预处理步骤

  • 另一种类似于第一种的预处理方法是PCA  WhiteningPCA \space\space Whitening 。在此过程中,数据如上述所示先居中。然后,可以计算协方差矩阵,该矩阵高速我们数据中的相关结构:

1
2
X -=np.mean(X, axis=0)	# zero-center
cov = np.dot(X.T, X) / X.shape[0] # compute the covariance matrix

之后,通过将原始(但以零为中心)的数据投影到特征基础上来求解相关数据:

1
2
U, S, V = np.linalg.svd(cov)	# 计算数据协方差矩阵的SVD分解
Xrot = np.dot(X, U) # 将数据分解

最后一个转换是白化,它将特征基础中的数据取出来并将每个维度除以特征值以标准化比例:

1
Xwhite = Xrot / np.sqrt(S + le-5)	# 除以特征值(他们是奇异值的平方根)

注意,这里它增加一个1e-5(或一个小常数)以防止除零。这种转换的一个弱点是它可以极大地夸大数据中的噪声,因为它将所有维度(包括主要是噪声的微小方差的无关维度)拉伸到输入中的相同大小。实际上,这可以通过更强的平滑来减轻(即,将1e-5增加为更大的数量)

请注意,我们在此描述这些预处理只是为了完整性,实际上,这些变换不用于卷积神经网络。但是,将数据置零中心也非常重要,并且通常也会看到每个像素的归一化。

3. 网络的初始化

现在,数据准备好了。但是,在开始训练网络之前,必须初始化其参数。

  • 全零初始化

    在理想情况下,通过适当的数据归一化,我们可以合理的假设大约一半的权重是正的,而其中一半是负的。一个听起来合理的想法可能是将所有初始权重设置为零,但是,这证明是一个错误的想法。因为如果网络中的每个神经元计算相同的输出,那么他们也将在反向传播期间计算相同的梯度并经历完全相同的参数更新。换句话说,如果神经元的权重被初始化为相同,则神经元之间不存在不对称的来源

  • 用小随机数初始化

    因此,我们仍然希望权重非常接近零,但不是相同的零。通过这种方式,您可以将这些神经元随机变为非常接近零的小数,并将其视为对称性破坏。我们的想法是,神经元在开始时都是随机且独特的,因此他们将计算不同的更新并将自身整合为整个网络的不同部分。权重的实现可能看起来像weightweight ~ $ 0.001 \times N(0, 1)N(0, 1)$:零均值,单位标准差高斯。也可以使用从均匀分布中抽取的小叔子,但这似乎对实际中的最终性能的影响相对较小。

  • 标准差异

    上述建议的一个问题是来自随机初始化神经元的输出的分布具有随输入数量增长的方差。事实证明,您可以通过将其权重向量按其扇入的平方根(即其输入数)进行缩放,将每个神经元输出的方差归一化为1,如下所示:

    1
    w = np.random.randn(n) / sqrt(n) # calibrating the variances with 1/sqrt(n)

    其中“randn”是前面提到的Gaussian,“n”是其输入的数量。这确保了网络中的所有神经元最初具有大致相同的输出分布并且凭经验提高了收敛速度。详细的推导可以从Page。幻灯片的18到23个。请注意,在推导中,它不考虑ReLU神经元的影响

    目前的建议:

    如前所述,通过校准神经元的方差进行的先前初始化不考虑ReLU。He 等人最近关于这一主题的论文。[4]推导出一个专门针对ReLU的初始化,得出网络中神经元的方差应该如下的结论 2.0/n2.0 / n

    1
    w = np.random.randn(n)* sqrt(2.0 / n)#current recommendation

    这是目前在实践中使用的建议.

4. 培训期间的一些提示

现在,一切都准备好了。让我们开始训练深层网络!

  • 过滤器和池大小。在训练期间,输入图像的大小优选为2的幂,例如32(例如,CIFAR-10),64,224(例如,常用的ImageNet),384或512等。此外,它是重要的。使用具有零填充的小滤波器(例如3×33 \times 3)和小步幅(例如1),这不仅减少了参数的数量,而且提高了整个深度网络的准确率。同时,上面提到的特殊情况,即具有3×33 \times 3步幅1的滤波器,可以保持图像/特征图的空间大小。对于池化层,常用的池化大小为2×22 \times 2

  • 学习率。此外,正如Ilya Sutskever [2]在博客中所描述的,他建议按小批量大小划分渐变。因此,如果更改迷你批量大小,则不应始终更改学习率(LR)。为了获得适当的LR,使用验证集是一种有效的方法。通常,训练开始时LR的典型值为0.1。在实践中,如果您发现您在验证集上停止了进展,则将LR除以2(或5),并继续前进,这可能会让您感到惊讶。

  • 在预先训练的模型上进行微调。如今,许多最先进的深层网络由着名研究团体发布,即Caffe Model ZooVGG Group。由于预训练深度模型具有出色的泛化能力,您可以直接将这些预先训练过的模型应用于您自己的应用程序。为了进一步提高数据集的分类性能,一种非常简单而有效的方法是根据您自己的数据微调预先训练的模型。如下表所示,两个最重要的因素是新数据集的大小(小或大),以及它与原始数据集的相似性。可以在不同情况下使用不同的微调策略。例如,一个很好的例子是您的新数据集与用于训练预训练模型的数据非常相似。在

    Very similar dataset very different dateset
    very little data Use linear classifier on top layer You’re in trouble…Try linear classifier from different stages
    quite a lot of data Finetune a few layers Finetune a large number o flayers

    这种情况下,如果您的数据非常少,则可以在从预训练模型的顶层提取的特征上训练线性分类器。如果您手边有大量数据,请以较小的学习率微调一些预先训练过的模型。但是,如果您自己的数据集与预训练模型中使用的数据完全不同,但具有足够的训练图像,则应对您的数据进行微调,同时以较小的学习速率来提高性能。但是,如果您的数据集不仅包含很少的数据,而且与预先训练的模型中使用的数据非常不同,那么您将遇到麻烦。由于数据有限,仅训练线性分类器似乎更好。由于数据集非常不同,因此从网络顶部训练分类器可能不是最好的,因为网络包含更多数据集特定的功能。相反,在网络中较早的某个地方训练SVM分类器对激活/特征可能会更好。

5. 激活功能的选择

深度网络的关键因素之一是激活功能,它将非线性带入网络。这里我们将介绍一些流行的激活函数的细节和特征,并在本节后面给出建议。

神经åƒ

Sigmoid

SIGMOD

S形非线性具有数学形式西格玛(X)= 1 /(1 + E ^ { -  X})。它需要一个实数值,并将其“压缩”到0到1之间的范围内。特别是,大的负数变为0,大的正数变为1. S形函数在历史上经常被使用,因为它具有很好的解释作为神经元的射击速率:从完全不射击(0)到假定最大频率(1)的完全饱和射击。

在实践中,S形非线性最近已失宠,很少使用。它有两个主要缺点:

  • Sigmoids饱和并杀死渐变。乙状结肠神经元的一个非常不希望的特性是,当神经元的激活在0或1的尾部饱和时,这些区域的梯度几乎为零。回想一下,在反向传播期间,这个(局部)梯度将乘以该门的输出的梯度以用于整个目标。因此,如果局部梯度非常小,它将有效地“杀死”梯度,并且几乎没有信号将通过神经元流到其权重并递归地流向其数据。此外,在初始化乙状结肠神经元的重量以防止饱和时,必须格外小心。例如,如果初始权重太大,那么大多数神经元将变得饱和,网络几乎不会学习。

  • Sigmoid输出不是以零为中心的*。这是不合需要的,因为神经网络中后续处理层中的神经元(很快就会更多)将接收非零中心的数据。这对梯度下降期间的动态有影响,因为如果进入神经元的数据总是正的(例如,X> 0元素方式F =瓦特^的Tx + B),那么w ^在反向传播期间权重的梯度将变为全部为正,或者全部为负(取决于整个表达的梯度F)。这可能会在权重的梯度更新中引入不希望的锯齿形动态。但是,请注意,一旦这些渐变在一批数据中相加,权重的最终更新可能会有可变符号,从某种程度上缓解了这个问题。因此,这是不方便的,但与上述饱和激活问题相比,其具有较不严重的后果。

tanh(x)

正切

tanh非线性将实数值压缩到范围[-1,1]。像S形神经元一样,它的激活饱和,但与S形神经元不同,它的输出是零中心的。因此,在实践中,tanh非线性总是优于S形非线性。

Rectified Linear Unit(整流线性单元)

整流线性单元(ReLU)在过去几年中变得非常流行。它计算函数F(X)= MAX(0,x)的,它简单地设置为零阈值

  • 优点)与涉及昂贵操作(指数等)的sigmoid / tanh神经元相比,可以通过简单地将激活矩阵设置为零来实现ReLU。同时,ReLUs不会饱和。

  • 优点)发现与sigmoid / tanh函数相比,随机梯度下降的收敛大大加速(例如,[1]中的因子为6 )。有人认为这是由于它的线性,非饱和形式。

  • 缺点)不幸的是,ReLU单位在训练期间可能很脆弱并且可能“死亡”。例如,流过ReLU神经元的大梯度可能导致权重更新,使得神经元永远不会再次激活任何数据点。如果发生这种情况,那么流经该单元的梯度将从该点开始永远为零。也就是说,ReLU单元可以在训练期间不可逆转地死亡,因为它们可以从数据流形中被淘汰。例如,如果学习率设置得太高,您可能会发现多达40%的网络可能“死”(即,永远不会在整个训练数据集中激活的神经元)。通过适当设置学习率,这不是一个问题。

Leaky ReLU

lrelu

Leaky ReLUs是解决“垂死的ReLU”问题的一次尝试。当x <0的泄漏的ReLU反而具有小的负斜率(0.01或左右)时,而不是函数为零。也就是说,该函数计算f(x)= alpha xif x <0的F(X)= Xif xgeq 0,where α是一个小常量。有些人用这种形式的激活函数报告成功,但结果并不总是一致的

Parametric ReLU(参数化ReLU)

如今,提出了更广泛的激活功能,即整流单元族。在下文中,我们将讨论ReLU的变体。

relufamily

ReLU,Leaky ReLU,PReLU和RReLU。在这些图中,对于PReLU,alpha_i是学习而Leaky ReLU alpha_i是固定的。对于RReLU,alpha_ {}纪随机变量是在给定范围内保持采样,并在测试中保持固定。

第一种变体称为参数整流线性单元PReLU)[4]。在PReLU中,负面部分的斜率是从数据而不是预定义中学习的。他等人。[4]声称PReLU是超越ImageNet分类任务的人类表现的关键因素。PReLU的反向传播和更新过程非常简单,类似于传统的ReLU

随机ReLU

第二种变体称为随机整流线性单元RReLU)。在RReLU中,负部分的斜率在训练中的给定范围内随机化,然后在测试中固定。如[5]中所述,在最近的Kaggle 国家数据科学碗(NDSB)竞赛中,据报道RReLU由于其随机性质可以减少过度拟合。此外,由NDSB比赛获胜者建议alpha_i,训练中的随机抽样从1 / U(3,8)测试时间开始,并且在测试时间内被固定为其期望,即2 /(1 + U)= 2/11

在[5]中,作者评估了CIFAR-10CIFAR-100NDSB数据集上具有不同激活函数的两种最先进CNN架构的分类性能,如下表所示。请注意,对于这两个网络,激活功能后面是每个卷积层。而一个这些表中的实际表明1 /α-α上述斜率在哪里

relures

从这些表中,我们可以发现ReLU的性能并不是所有三个数据集的最佳性能。对于Leaky ReLU,更大的斜率α将获得更好的准确率。PReLU很容易在小数据集上过度拟合(其训练误差最小,而测试误差不尽如人意),但仍然优于ReLU。此外,RReLU明显优于NDSB上的其他激活功能,这表明RReLU可以克服过度拟合,因为该数据集的训练数据少于CIFAR-10 / CIFAR-100。**总之,在这三个数据集中,三种类型的ReLU变体都始终优于原始ReLU。而PReLU和RReLU似乎是更好的选择。此外,何等人。[4]**也报道了类似的结论

6. 多样化的正规化

有几种方法可以控制神经网络的容量以防止过度拟合:

  • **L2 regularization(L2正则化)**可能是最常见的正则化形式。它可以通过直接在目标中惩罚所有参数的平方幅度来实现。也就是说,对于w ^网络中的每个权重,我们将该项添加frac {1} {2} lambda w ^ 2到目标中,其中拉姆达是正则化强度。通常会看到压裂{1} {2}前面的因素,因为这个术语相对于参数的梯度w ^只是简单拉姆达威而不是2 lambda w。L2正则化具有严重惩罚峰值权重向量并且优选漫反射权向量的直观解释。
  • **L1 regularizationL1(正则化)**是另一种相对常见的正则化形式,其中对于每个权重,w ^我们将该术语添加lambda | w |到目标中。可以将L1正则化与L2正则化相结合:( lambda_1 | w | + lambda_2 w ^ 2这称为[弹性网正则化](http://web.stanford.edu/~hastie/Papers/B67.2 (2005) 301-320 Zou & Hastie.pdf))。L1正则化具有引人注目的特性,即它导致权重向量在优化期间变得稀疏(即非常接近于零)。换句话说,具有L1正则化的神经元最终仅使用其最重要输入的稀疏子集并且变得几乎不变于“噪声”输入。相比之下,来自L2正则化的最终权重向量通常是漫反射的,小数目。实际上,如果您不关心明确的特征选择,可以期望L2正则化比L1具有更好的性能。
  • Max norm constraints(最大范数约束)。另一种形式的正则化是对每个神经元的权重向量的大小强制执行绝对上限,并使用预计的梯度下降来强制执行约束。实际上,这对应于正常执行参数更新,然后通过钳制VEC【W】每个神经元的权重向量来实现约束以满足并行vec {w} parallel_2 <c。典型值为C3或4的订单。有些人报告使用这种正规化形式时的改进。其吸引人的特性之一是,即使学习率设置得太高,网络也无法“爆炸”,因为更新总是有限的。
  • Dropout是Srivastava 等人非常有效,简单且最近引入的正则化技术。在[6]中补充了其他方法(L1,L2,maxnorm)。在训练期间,丢失可以解释为在完整神经网络内对神经网络进行采样,并且仅基于输入数据更新采样网络的参数。(然而,可能的采样网络的指数数量并不是独立的,因为它们共享参数。)在测试期间,没有应用丢失,并且解释了评估所有子网络的指数级整体的平均预测(更多关于合奏在下一节)。在实践中,辍学率的价值P = 0.5 是一个合理的默认值,但可以根据验证数据进行调整。

退出

最常用的正则化技术dropout [6]。在训练时,通过仅以一定概率保持神经元活动p(超参数)或者将其设置为零来实现丢失。

7. 从数字中找到的一些见解

最后,根据上面的提示,您可以为自己的深层网络获得满意的设置(例如,数据处理,架构选择和详细信息等)。在培训期间,您可以绘制一些数字来表明您的网络的培训效果。

  • 众所周知,学习率非常敏感。从下面的图1可以看出,非常高的学习率将导致一个非常奇怪的损失曲线。即使在大量时期之后,低学习率也会使您的训练损失减慢得非常缓慢。相反,高学习率会使训练损失在开始时快速下降,但也会降低到局部最小值。因此,在这种情况下,您的网络可能无法取得令人满意的结果。为了获得良好的学习率,如图1所示的红线,其损耗曲线表现平稳,最终达到最佳性能。
  • 现在让我们放大损失曲线。时期表示在训练数据上训练一次的次数,因此每个时期有多个小批量。如果我们在每个训练批次中绘制分类损失,则曲线如图2所示。与图1类似,如果损失曲线的趋势看起来过于线性,则表明您的学习率较低; 如果它没有减少太多,它会告诉你学习率可能太高了。而且,曲线的“宽度”与批量大小有关。如果“宽度”看起来太宽,也就是说每个批次之间的差异太大,这表明您应该增加批量大小。
  • 另一个提示来自准确度曲线。如图3所示,红线是训练精度,绿线是验证线。当验证准确度收敛时,红线和绿线之间的差距将显示深层网络的有效性。如果差距很大,则表明您的网络可以在训练数据上获得良好的准确性,而在验证集上只能达到较低的准确度。很明显,你的深层模型会过度训练。因此,您应该增加深度网络的正则化强度。然而,同时在低精度水平上没有差距并不是一件好事,这表明你的深层模型具有较低的可学习性。在这种情况下,最好增加模型容量以获得更好的结果。

trainfigs

8. 集合多个深度网络的办法

在机器学习中,训练多个学习者然后将它们组合起来使用的集合方法[8]是一种最先进的学习方法。众所周知,集合通常比单个学习者更准确,并且集合方法已经在许多现实世界的任务中取得了巨大的成功。在实际应用中,特别是挑战或比赛中,几乎所有的第一名和第二名的获胜者都使用了整体方法。

在这里,我们介绍了深度学习场景中的集合的几种技能。

  • 相同型号,不同的初始化。使用交叉验证来确定最佳超参数,然后使用最佳超参数集训练多个模型,但使用不同的随机初始化。这种方法的危险在于变化只是由于初始化。
  • 在交叉验证期间发现的顶级模型。使用交叉验证来确定最佳超参数,然后选择前几个(例如10个)模型来形成整体。这改善了整体的多样性,但存在包括次优模型的危险。在实践中,这可以更容易执行,因为在交叉验证之后不需要额外的模型再训练。实际上,您可以直接从Caffe Model Zoo中选择几个最先进的深度模型来执行整体。
  • 单个模型的不同检查点。如果培训非常昂贵,那么有些人在一段时间内(例如在每个时期之后)采用单个网络的不同检查点并使用这些检查点形成整体的成功有限。显然,这种情况有些缺乏,但在实践中仍然可以很好地运作。这种方法的优点是非常便宜。
  • 一些实际的例子。如果您的视觉任务与高级图像语义相关,例如,来自静止图像的事件识别,则更好的集合方法是使用在不同数据源上训练的多个深度模型来提取不同的和互补的深度表示。例如,在与ICCV’15相关的文化事件识别挑战中,我们使用了五种不同的深度模型,这些模型训练了ImageNet地方数据库竞赛组织者提供的文化图像。之后,我们提取了五个互补的深层特征,并将它们视为多视图数据。结合[7]中描述的“早期融合”和“晚期融合”策略,我们取得了最佳表现之一,并在该挑战中排名第二。与我们的工作类似,[9]提出了Stacked NN框架,以同时融合更深层次的网络。

杂:

在实际应用中,数据通常是类不平衡的:一些类具有大量图像/训练实例,而一些类具有非常有限数量的图像。正如最近的技术报告[10]中所讨论的,当深度CNN在这些不平衡训练集上进行训练时,结果表明不平衡训练数据可能对深度网络中的整体性能产生严重的负面影响。对于这个问题,最简单的方法是通过直接对不平衡数据进行上采样和下采样来平衡训练数据,如[10]所示。另一个有趣的解决方案是我们的挑战解决方案中的一种特殊作物加工[7]。由于原始文化事件图像不平衡,我们只从具有少量训练图像的类中提取作物,一方面可以提供不同的数据源,另一方面可以解决类不平衡问题。此外,您可以调整微调策略以克服阶级不平衡。例如,您可以将自己的数据集分为两部分:一部分包含具有大量训练样本(图像/作物)的类; 另一个包含有限数量的样本类。在每个部分,阶级不平衡的问题都不会很严重。在对数据集进行微调开始时,首先要对具有大量训练样本(图像/作物)的类进行微调,其次,继续微调,但是对有限数量的样本进行微调