卷积神经网络训练技巧

翻译自文章:

http://lamda.nju.edu.cn/weixs/project/CNNTricks/CNNTricks.html

1.增加数据

除了常用的水平镜像翻折、随机修剪、颜色调整,可以尝试将几种不同的处理方式组合起来,比如,同时旋转和随机放缩。还可以改变HSV色彩模型中的饱和度(S)和纯度(V),数值范围可以是0.25次幂到4次幂,然后乘以0.7到1.4范围内的一个系数,然后再加上-0.1到0.1的一个常数。你还可以改变HSV色彩模型中的色度(H),例如给每个像素的这个值增加一个-0.1到0.1的常数。

还可以使用fancy PCA,它改变了RGB(红绿蓝)的数值。实际中,可以先对图片的RGB值做PCA,然后对每个特征向量乘一个由高斯分布产生的系数,再叠加回原RGB。Fancy PCA能够提取出图片中的重要信息。

 

2.预处理

将数据处理成0均值,1方差:

[python]  view plain  copy
  1. X -= np.mean(X, axis = 0# zero-center  
  2. X /= np.std(X, axis = 0# normalize  

或者将最大值和最小值变换成1和-1。这类预处理只有在各个输入特征对算法的重要性大致相同才是有意义的。对于图片,每个像素的数值范围大致相同(0-255),所以不一定要进行这个变换。

另一个预处理的方式是PCA白化,在这个过程中,数据先变换成0中心,然后计算各个输入特征的协方差矩阵:

[python]  view plain  copy
  1. X -= np.mean(X, axis = 0# zero-center  
  2. cov = np.dot(X.T, X) / X.shape[0# computethe covariance matrix  

之后,把数据投影到特征向量上进行去相关:

[python]  view plain  copy
  1. U,S,V = np.linalg.svd(cov) # compute theSVD factorization of the data covariance matrix  
  2. Xrot = np.dot(X, U) # decorrelate the data  

最后一个变换是白化,把投影到特征向量上的每个特征除以特征值:

[python]  view plain  copy
  1. Xwhite = Xrot / np.sqrt(S + 1e-5# divideby the eigenvalues (which are square roots of the singular values)  

在分母中加上了平滑参数1e-5(或一个小的常数)以防止除0.这个变换的一个大问题是会极大的放大噪声,因为所有的维度(包括无关方差很小的维度,绝大部分是噪声)都被等同的处理了。在实际操作中可以通过增大平滑参数来减小噪声影响。

在CNN中,一般并不采用预处理,除了0均值和标准化。

 

3.初始化

设置为全0:

无法训练

用小的随机值初始化

如0.001 * N(0, 1)

矫正方差

根据每层神经元数目矫正方差,使得初始状态下每层输出的方差一致,从而提升收敛速率

[python]  view plain  copy
  1. w = np.random.randn(n) / sqrt(n) #calibrating the variances with 1/sqrt(n)  

4.训练过程

滤波器和池化的尺寸

一般倾向于使用小滤波器(如3*3),小的步进(如1)和补零,这样就不会减少参数数量,但提升了整个神经网络的准确率。常用的池化尺寸是2*2

学习率

可以使用验证集来调整学习率。如果发现验证集停上的表现不再变好,可以把学习率除以2或5。可以把学习率除以batch size,这样可以通过增大batch size达到效果。

微调与预训练

相似数据集

不相似数据集

非常少的数据

在顶层加一个线性分类器

不好处理,比如在中间某一层的基础上加一个线性分类器

非常多的数据

微调一些层

微调很多层

 

5.激活函数

sigmoid

sigmoid有两个缺点:

1.sigmoid会饱和,一旦饱和就几乎没有梯度了,而且在backpropagation的过程中会影响之前的神经元。这个性质会使初始化变得困难,一旦初始化太大,就会饱和。

2.sigmoid的输出不是以0为中心的,批梯度下降会减小这个缺点的影响。

tanh

没有sigmoid的第二个缺点

整流线性单元(ReLU)

形式为f(x)=max(0,x)

优点:

不饱和,计算快,收敛快

缺点:

输入小于0时导数为0。如果学习率太大,很多神经元将失效。

Leaky ReLU

给Relu的负半轴加一个小的slope(比如0.01)

Parametric ReLU

负半轴上函数的斜率是一个可以学习的参数。

Randomized ReLU

负半轴上函数的斜率在训练时是随机的,测试时固定。

 

比较已上激活函数,ReLU不是最好的选择。Leaky ReLU在负半轴斜率大时表现更好。PReLU在小数据集上容易过拟合,但也比ReLU好。RReLU表现最好。

 

6.正则化

L2正则化

如果不需要做特征抽取,L2一般比L1表现更好。

L1正则化

可以和L2组合,即弹性网正则化。

Max norm限制

给w设置上界,一般数量级是3或4

Dropout

训练时有dropout。测试的时候不dropout,可以看作是所有(指数级数目的)子图测试结果的平均,有点类似组合方法。dropout比例可以设置为0.5,也可以在验证集上验证得出。

 

7.分析图表

从损失函数值随着迭代的变化曲线可以看出学习率是大了还是小了。从这条曲线的宽度可以看出,如果宽度太小,可能学习率太小,如果宽度太大,可以尝试增加batch size。

learning curve可以看出是variance还是bias。

 

8.组合方法

相同的模型,不同初始化

风险在于模型的不同只是由初始化造成的

交叉验证选择多个最好模型

比如10个。风险在于可能选出不那么好的模型。

选择不同阶段的训练模型

如果数据不多,可以选择不同迭代次数的同一个模型,优点是代价非常低,缺点是缺乏多样性。

实际范例

如果视觉任务是高级的图像语义,比如静止图片中的时间辨别,一个更好的方式是使用不同的数据源来训练多个模型。

 

其他

如果数据是不均衡的,有些类有很多数据,而另一些类数据很少。不均衡数据严重影响CNN的性能。最简单的解决方案是直接对训练数据上采样和下采样。另一个有趣的解决方案是从图片中剪裁,这样还能起到增加数据的作用。此外,还可以调整微调策略来解决数据不均衡,例如,你可以将数据分成两份,一份包含那些多类,一份包含那些少类,每一份数据中的数据不均衡都不再明显,在微调阶段,先训练一份数据,再用另一份数据继续训练模型

猜你喜欢

转载自blog.csdn.net/barry_j/article/details/80053263