卷积神经网络操作技巧

1.介绍

关于图像相关任务的卷积神经网络,主要从8个细节来进行详解,1)训练数据扩增;2)图像预处理;3)权值初始化;4)训练技巧;5)激活函数选择;6)正则化;7)训练过程可视化;8)多网络综合;9)类数据不平衡问题。

2.训练数据扩增

由于卷积神经网需要大量的训练图像才能获得令人满意的表现,如果原始图像集只含有有限的训练样本,则需要进行数据扩增。一般情况下,在训练神经网络时训练数据扩增是必不可少的步骤。

1)通常做法有水平翻转(horizontally flipping),随机裁剪(random crops),颜色抖动(color jittering)。而且可以同时进行不同处理,比如旋转和随机伸缩。此外还可以提升图像的饱和度和亮度,数值可以是0.25到4次幂,然后再乘以0.7到1.4的系数,还以给色调加上-0.1到0.1,一幅图像所有像素颜色抖动参数是一样的。

2)此外AlexNet中提到一种方法Fancy PCA。具体过程,首先对RGB图像做PCA,然后计算RGB三通道的3*3协方差矩阵,求得3个特征值pi和对应的特征向量ri,算得[p1,p2,p3]*[a1r1,a2r2,a3r3]T,再加上RGB三个通道,ai是均值为0,标准差为0.1的随机值。论文中解释到该操作能够获取自然图像的重要信息,具有亮度和光照不变性,能够提高超过1%的识别率。

3.图像预处理

1)均值0中心化(zero-center),规范化(normalize)

X -= np.mean(X, axis = 0)# zero-center

X /= np.std(X, axis = 0)# normalize          

还有一种预处理方法就是让像素值在[-1,1],这种操作只有对不同尺度的输入特征才有用,由于图像具有同分布[0,255],所以没必要进行该步骤。

2)PCA白化 (PCA Whitening)

首先进行0中心化,然后计算协方差矩阵

X -= np.mean(X, axis = 0)# zero-center

cov = np.dot(X.T, X) / X.shape[0]# compute the covariance matrix

然后将去中心的数据投影到特征向量进行去相关

U,S,V = np.linalg.svd(cov)# compute the SVD factorization of the data covariance matrix

Xrot = np.dot(X, U)# decorrelate the data

最后就是白化,拿在特征向量上的数据除以该特征向量对应的特征值,来规范每个特征向量的尺度。

Xwhite = Xrot / np.sqrt(S + 1e-5)# divide by the eigenvalues (which are square roots of the singular values)

加上1e-5平滑参数是为了防止除0。这种操作有个缺点就是大大扩大了数据噪声,因为所有的维度都被等同处理,包括具有小方差的噪声维度,实际过程中可以增大平滑参数来降低影响。

然后在卷积神经网中,常见的只采用均值0中心化(zero-center),规范化(normalize)。

4.权值初始化

1)全0初始化。权值初始化大约一半为正值一半为负值是比较合理的。但是如果给定全为0值,这将会有不希望结果发生。因为每个神经元具有相同的输出,然后在反向传播计算梯度时,会得到同一个梯度值,并且进行着同样的参数更新。换句话说,如果权值都初始化为相同值,会使网络处于对称状态,这是不希望看到的。

2)初始化小的随机值。想要让权值接近于0,但又不能设置为0。可以设置权值为非常接近于0的随机值,会让网络非对称,以便于训练。比如可以简单地这样初始化,0.001*N(0,1),N(0,1)符合均值为0,标准差的高斯分布。

3)校正方差。上述(2)的初始化方法会让输出方差随着输入神经元的个数而变化。把权值除以输入神经元个数的开方就可以让输出神经元方差为1,这样可以让每层输出具有相同方差,能够大大提高收敛速度

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

4)推荐做法。以上处理方法并没有考虑到ReLUs激活函数,最新文章提出如下做法

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

5.训练技巧

1)卷积核和池化size。训练过程,输入图像的大小希望为2的幂次,比如32(cifar-10),64,224(ImageNet),384,或者512。而且采用小的卷积核大小(e.g.,3*3)和小的滑动步长(e.g.,1)和补0是比较重要的,不但减少权值参数而且还能提高整个网络的准确率。此外,以上的卷积核大小(e.g.,3*3)和小的滑动步长(e.g.,1)和补0能够保持输入图像和输出特征映射的空间大小(e.g. (32+2*1-3)/1+1=32)。对于池化层,大小通常用2*2。

2)学习率(LR)。通常一般做法,给定初始值为0.1,然后监视验证集上的进程,把LR除以2或者5继续训练,会有意外惊喜。

《卷积神经网络操作技巧》

3)微调预训练模型。如今有很多来自著名研究院的最新成功模型(i.e.Caffe Model Zoo)。有了这些成功的模型,就可以直接把他们的模型参数应用到自己应用中。在自己的数据集上微调这些预训练模型能够直接提高自己的正确率。如下表所示,有两种最重要因素,自己数据集的大小、与原始数据集的相似度,不同的情况需要采用不同的微调策略。如果只有很小新数据集但是和原始数据集具有很大相似性,只要在预训练模型顶层输出特征后面加一个线性分类器;如果有大量的新数据集而且和原始数据集具有很大相似性,可以微调预训练模型最后几个顶层,并且只有一个小的学习率;如果有很小新数据集但又和原始数据集不相似,就会遇到麻烦,因为数据很少,只能训练简单的线性分类器,比较好的做法是在前面的特征层后就使用svm分类器;如果有很大的数据集但又和原始数据集不相似,就需要微调更多的权值层,并且只用小的学习率。

6.激活函数

《卷积神经网络操作技巧》

激活函数让深度网络具有非线性表达能力。这里介绍几种常见的激活函数:sigmoid,tanh,ReLU,leaky ReLU,Parametric ReLU,Randomized ReLU

1)sigmoid。sigmoid函数表达式如下,把实数压缩在0~1之间。sigmoid函数会在很多地方看到,它很好的模拟了神经元的激活状态,从0到1表示了该神经元的活跃状态。

《卷积神经网络操作技巧》 sigmoid表达式

《卷积神经网络操作技巧》 sigmoid函数

但是sigmoid函数有两个主要缺点,现在很少用它。①激活值容易饱和,容易接近0或1,会使梯度为非常接近0的数,无法进行权值更新,同时在初始化权值时很难设置初始值,因为容易使激活值饱和。②激活值是非0中心化的。如果激活值都是正值,则反向传播算w梯度都是正值或负值,这会让在权值更新时出现锯齿变化,但是相比①消极影响是不严重的。

2)tanh。tanh函数把实数压缩在-1~1之间。和sigmoid函数一样激活值容易饱和,容易接近-1或1,会使梯度为非常接近0的数,无法进行权值更新.但是它是0中心化的。在实际应用中,我们更愿意使用tanh(x),而非sigmoid函数。

《卷积神经网络操作技巧》 tanh函数

3)ReLU.。ReLU在最近几年非常流行,函数表达式为 f(x) = max(0,x)。

《卷积神经网络操作技巧》 ReLu

ReLu有以下两点好处:①该函数相比sigmoid、tanh计算简单,不会发生饱和;②训练过程中能够加快随机梯度下降收敛

但是,ReLu有一个主要问题:由于神经元梯度容易为0,这就导致该神经元在训练过程中失效。实际情况如果学习率设置过高,神经网络中有大约40%的神经元失效。

4)leaky ReLU。该激活函数是为了解决ReLu问题,在输入小于0时不设置0,而用乘上一个很小的常数值来代替。函数表达式为f(x) = max(ax,x),a是很小的常数,比如0.01。

5)Parametric ReLU。该激活函数近似leaky ReLU,只是a不是预设定一个常数,是要通过数据学习得到,并且学习起来比较简单,详情请见Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification

6)Randomized ReLU。该激活函数近似leaky ReLU,同样只是a不是预设定一个常数,而是训练过程中随机的给定在某范围内的数值,测试时给定固定的a值。这种随机特性能降低过拟合。通常建议a采样值为1/U(3,8),测试时用它的均值1/[(3+8)/2] = 2/11。

在CIFAR-10,CIFAR-100和NDSB数据集上对不同的ReLu变种比较:

《卷积神经网络操作技巧》 ReLu变种比较

从上图得出,ReLu表现是最差的。对于leaky ReLu,大的斜率会获得更好的正确率。Parametric ReLU对于小数据集容易过拟合,但是仍然要比leaky ReLu出色。Randomized ReLU是表现最好的,能够克服过拟合。

7.正则化

采用正则化方法,可以有效防止过拟合。方法有以下几种:

1)L2正则化。这是一种最常见的正则化方法,直接在损失函数里加上惩罚项。也就是对神经网络里每个权值W计算L2范数,然后加到损失函数里,用0.5*lamda*W^2。lamda是正则化强度,lamda越大正则化越强,越能防止过拟合,但是太大了就会变成欠拟合,实际工程中,一般取利用验证集做超参数确定。最后得到的权值W是分散的,数值也比较小。

2)L1正则化。这是另一种常见的正则化方法。也就是对神经网络里每个权值W计算L1范数,然后加到损失函数里,用lamda*|W|。这种L1正则化方法会让权值变得稀疏,会让权值W绝大数接近于0,这就相当于只让部分输入数据参与到神经网络,对具有噪声或者冗余的这部分输入具有鲁棒性。这种性质可以用来做特征选择。如果不需要做特征选择,一般才去L2正则化。

3)最大规范约束。这种正则化方法限制了权值的L2范数小于某个数值,比如3或者4.这样做好处就是当学习率设置太高了也能训练深度网络。

4)Dropout。该方法相比以上方法是非常高效、简单的,详情见Dropout: A Simple Way to Prevent Neural Networks from Overfitting。在训练过程中,将神经网络进行采样,也就是随机的让神经元激活值为0,而在测试时不再采用dropout。通常设置随机采样概率为0.5,也可以通过验证集来确定采样概率。

《卷积神经网络操作技巧》 Dropout网络

7.训练过程可视化

训练过程中,我们可以把训练中间结果(i.e.loss值,正确率)以图表的形式打印出来,能够实时监控训练状态,看是否有效。

1)学习率。学习率是比较敏感的。非常大的学习率会导致异常的loss曲线。小的学习率又会让你的loss曲线下降得很慢,收敛困难。相反大的学习率会让loss曲线刚开始下降得特别快,然后很快收敛,这往往是停留在局部最优。而一个好的学习率loss曲线比较平滑,最后在测试集上有比较好的表现。

《卷积神经网络操作技巧》 学习率与loss关系

《卷积神经网络操作技巧》

2)loss值。一次epoch即扫描过所有训练集,比如每一次批训练batch(i.e.128),总共训练样本有10000,则扫描所有训练集需要79次批处理(10000/128=78.125)。就可以把每一次批处理训练的loss值实时显示出来。如果loss曲线呈线性下降则说明学习率过小;如果loss曲线不下降太多,则说明学习率过大。而求loss曲线的上下宽度和batch值有关,如果太宽说明震荡比较厉害,就要提高batch值。

loss实际曲线

3)正确率。可以从正确率曲线上得出某些结论。下图红线是训练集正确率,绿线是验证集正确率。验证集正确率收敛时,比较与训练集正确率之间的差距。如果差距很大,说明在训练集上表现好,而在验证集上表现差,此时过拟合状态,就需要加大正则化力度。然而差距很小并且正确率都很低,说明此时深度模型比较差,需要增强深度网络的表示能力。

《卷积神经网络操作技巧》 正确率曲线

8.多网络综合

在机器学习问题中,综合多个学习器往往能够获得更好的结果。这里介绍在深度学习中几个技巧。

1)同样的模型使用不同的初始化。用交叉验证来获得最优的超参数,然后给这个模型不同的初始化。这种缺点就是网络的不同处只在于初始化。

2)选择多个网络模型。从Caffe Model Zoo中选取多个优秀模型,然后对每个模型交叉验证来获得最优超参数。这样能够改变网络之间的差异,但是有的网络对应用而言并非最优的。

3)单个模型不同的参数状态。把网络训练中不同的参数状态分别拿出来进行模型综合。

4)多模型在不同数据集上训练。这种方法可以从多个方面学习到不同的特征。详情可见S-NN: Stacked Neural Networks , Deep Spatial Pyramid Ensemble for Cultural Event Recognition

9.类数据不平衡问题

在实际应用中,各类的数据经常是不平衡的:有的类有大量的训练样本,而有的类有很少的数据样本,这会非常影响深度网络的表现。一种简单方法是直接上采样和下采样不平衡数据集;另一种方法是使用在缺失的类数据上进行裁剪;还有一种方法就是调整fine-tuning策略,例如把数据集分成两部分,一部分是那些具有大量数据样本的类,还有一部分是那些具有少量样本的类,这样对每个部分而言不平衡问题就能够缓和,首先fine-tuning具有大量样本的类的那部分数据集,然后继续fine-tuning具有少量样本的类的那部分数据集。

    原文作者:Wangcy
    原文地址: https://www.jianshu.com/p/a3c83280482b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞