深度神经网络训练的必知技巧

本文主要介绍8种实现细节的技巧或tricks:数据增广图像预处理网络初始化训练过程中的技巧激活函数的选择不同正则化方法来自于数据的洞察集成多个深度网络的方法

1. 数据增广

在不改变图像类别的情况下,增加数据量,能提高模型的泛化能力。

自然图像的数据增广方式包括很多,如常用的水平翻转(horizontally flipping),一定程度的位移或者裁剪和颜色抖动(color jittering)。此外还可以尝试多种操作的组合, 例如同时做旋转和随机尺度变换,此外还可以把每个patch中所有像素在HSV颜色空间中的饱和度和明度提升0.25-4次幂方,乘以0.7-1.4之间的一个因子,再加一个-0.1-0.1之间的值。同样你可以在色调通道(H)对每张图片或patch的所有像素增加一个-0.1-0.1之间的值。(未完待续。。。。。。。。)

2. 预处理

2.1 最简单的预处理方法

  • 零均值化
  • 标准化

2.1.1 为什么要零均值化

数据有过大的均值可能导致参数的梯度过大,如果有后续的处理,可能要求数据零均值,比如PCA。零均值化并没有消除像素之间的相对差异,人们对图像信息的摄取通常来自于像素之间的相对色差,而不是像素值的高低。

2.1.2 为什么要归一化

归一化是为了让不同维度的数据具有相同的分布。假如二维数据(X1,X2)两个维度都服从均值为零的正态分布,但是X1方差为100,X2方差为1。那么对(X1,X2)进行随机采样在二维坐标系中绘制的图像,应该是狭长的椭圆形。

对这些数据做特征提取会用到以下形式的表达式:

S = w1*x1 + w2*x2 + b;

那么参数W1,W2的梯度为:

dS / dw1 = x1 ; dS / dw2 = x2

由于x1与x2在分布规模上的巨大差异,w1与w2的导数也会差异巨大。此时绘制目标函数(不是S)的曲面图,就像一个深邃的峡谷,沿着峡谷方向变化的是w2,坡度很小;在峡谷垂直方向变化的是w1,坡度非常陡峭,如图1,而我们期望的目标函数是图2这样的。

目标函数是非常难以优化的,因为w1和w2的梯度差异太大,所以在两个维度上需要不同的迭代方案。但在实际操作中,为了方便,我们通常为所有维度设置相同的步长,随着迭代的进行,步长的缩减在不同维度也是同步的。这就要求w不同纬度的分布规模大致相同,而这一切都始于数据的归一化。

2.1.3 实现代码

X-=numpy.mean(X,axis=0) # 即X的每一列都减去该列的均值

注:对于灰度图像,零均值化也可以减去整张图片的均值:X-=numpy.mean(X)

X/=numpy.std(X,axis=0) # 数据归一化。

X是输入数据,(图片数目X图片维度)。另一种标准化(normalize)方式是标准化每个维度,保证每个维度的最大值和最小值是-1和1。这种预处理的方式只在输入的各个特征的尺度或者单位不同时才有意义。以图片像素作为输入为例子,所有像素值尺度都在0-255这个尺度之间,所以没必要严格的执行这种预处理操作。在自然图像上进行训练时,可以不进行归一化操作,因为理论上图像任一部分的统计性质都应该和其他部分相同,图像的这种特性被称作平稳性(stationarity)

2.2 白化(Whitening)

白化相当于在零均值化和归一化操作之间插入一个旋转操作,将数据投影到主轴上。一张图片经过白化后,可以认为每个像素之间是统计独立的。然而白化很少在卷积神经网络中使用,可能原因是图像信息本来就是依靠像素之间的相对差异来体现的,白化让像素间去相关,让这种差异变得不确定,损失了信息。

首先将数据零均值化,再计算协方差矩阵(convariance matrix)来观察数据中的相关结构。

   X-=np.mean(X,axis=0)
   cov=np.dot(X.T,X)/X.shape[0] #计算协方差矩阵

然后做去相关操作,即通过将原始数据(零均值化后的数据)投影到特征基空间(eigenbasis)。

U,S,V=np.linalg.svd(cov) #计算数据协方差矩阵的奇异值分解(SVDfactorization)
Xrot=np.dot(X,U) #对数据去相关

最后一步变换是白化,即把特征基空间的数据除以每个维度的特征值来标准化尺度。

Xwhite=Xrot/np.sqrt(S+1e-5) #除以奇异值的平方根,注意到这里加了个1e-5是为了防止分母是0的情况。

PCA白化的一个缺点是会增加数据中的噪声,因为它把输入数据的所有维度都延伸到相同的大小,这些维度中就包含噪音维度(往往表现为不相关的且方差较小)。这种缺点在实际操作中可以通过把1e-5增大到一个更大的值来引入更强的平滑。

3. 初始化

3.1 不要将参数全部初始化为零

几乎所有的CNN网络都是堆成结构,将参数零初始化会导致流过网络的数据也是对称的(都是零),并且没有办法在不受扰动的情况下打破这种数据对称,从而导致网络无法学习。

参数零初始化时,无论输入是什么,中间神经元的激活值都是相同的(任意一个神经元的激活值a=f(WTX),当权重W是零向量时,WTX也是零向量,因此经过激活函数后激活值都相同),反向传播过程中计算的梯度也是相同,每个权重参数的更新因此也是相同的,网络因此失去了不对称性。

3.2 用小的随机数初始化

初始化参数应该非常接近于零(但不全等于零),来打破网络的对称性。初始参数应该是随机且独立的来保证每个参数更新过程是不同的。给每个参数随机赋予一个接近零的值:

W=0.01*numpy.Random.randn(D,H)

randn方法生成一个零均值,方差为1的正态分布的随机数,同样也可以换用数值较小的均匀分布来产生初始化参数,但在实践中两种方法最终结果差别不大

3.3 方差归一化

用随机初始化方法来初始化参数会导致输出S的方差随输入数量(X或W向量的维度)增加而变大。

独立随机变量和的方差具有以下性质:

Var(A+B+C)=Var(A)+ Var(B)+ Var(C)
S = w1*x1 + w2*x2 +…+wi*xi+ b   

S是多个随机变量的加权和,假设W各维度之间相互独立,随着数据维度增长,S的方差将会线性积累,由于数据的维度随任务的不同,是不可控的,所以我们希望将S的方差做归一化,这只需要对W做处理就可以了:

W=numpy.random.randn(n)/sqrt(n)  #n是数据维度

上面操作是正确的推导过程:

令 n*Var(W) = 1,就得到std(W) = 1 / sqrt(n)。
注意:现在更多的论文中在实际中都在用ReLUs函数,针对ReLUs推荐:
w=numpy.random.randn(n)*sqrt(2.0/n)

4. 训练过程中

4.1 卷积滤波器和池化层大小

输入数据最好是2的整数幂次方,比如32(CIFAR-10中图片尺寸),64,224(ImageNet中常见的尺寸)。此外采用较小尺寸的滤波器(例3x3),小的步长(例1)和0值填充,不仅会减少参数数量,还会提升整个网络的准确率。当用3x3的滤波器,步长为1,填充(pad)为1时,会保持图片或特征图的空间尺寸不变。池化层经常用的池化大小是2x2。

4.2 学习率

使用验证集是获得合适LR(Learning Rate)的有效手段。开始训练时,LR通常设为0.1。在实践中,当你观察到在验证集上的loss或者准确率不在变化时,将LR除以2或5后继续跑。

4.3 在预训练的模型上微调

很多state-of-the-arts deep networks的模型被开源出来,这些预训练的模型泛化能力(generalization abilities)很强,因此可以在这些模型的基础上根据自己的任务微调。微调涉及两个重要的因素:新数据集的大小和两个数据集的相似度。网络顶层特征包含更多dataset-specific特征。

数据集相似性高 数据集相似性低
数据少 直接提取顶层特征来训练线性分类器 比较困难,尝试用不同层的特征训练一个线性分类器
数据多 用较小的学习率微调更多的层 用较小的学习率微调尽可能多的层

5. 激活函数

激活函数用于在网络中引入非线性。sigmoid 与 tanh 曾经很流行,但现在很少用于视觉模型了,主要原因在于当输入的绝对值较大时,其梯度(导数)接近于零,这时参数几乎不再更新,梯度的反向传播过程将被中断,出现梯度消散的现象。

ReLU 优点:

  • 实现起来非常简单,加速了计算过程。
  • 加速收敛,没有饱和问题,大大缓解了梯度消散的现象。

ReLU 缺点:

就是它可能会永远“死”掉,假如有一组二维数据 X(x1, x2)分布在 x1:[0,1], x2:[0,1] 的区域内,有一组参数 W(w1, w2)对 X 做线性变换,并将结果输入到ReLU。

F = w1*x1 + w2*x2

如果 w1 = w2 = -1,那么无论 X 如何取值,F 必然小于等于零。那么 ReLU 函数对 F 的导数将永远为零。这个 ReLU 节点将永远不参与整个模型的学习过程。

为了解决ReLU 在负区间的导数为零的问题,人们发明了 Leaky ReLU, Parametric ReLU, Randomized ReLU 等变体,他们的中心思想都是为ReLU 函数在负区间赋予一定的斜率,从而让其导数不为零(这里设斜率为 alpha)。

Leaky ReLU 就是直接给 alpha 指定一个固定的值,整个模型都用这个斜率:

Parametric ReLU 将 alpha 作为一个参数,通过从数据中学习获取它的最优值。

Randomized ReLU 的alpha 是在规定的区间内随机选取的,在测试阶段是定值。

有学者将当前最优的两类CNN网络结合不同的激活函数在CIFAR-10,CIFAR-100和NDSB数据集上做实验,评价四种激活函数的优劣。 实验结果表明Leaky ReLU取较大的alpha准确率更好。Parametric ReLU很容易在小数据集上过拟合(训练集上错误率最低,测试集上不理想),但依然比ReLU好。RReLU效果较好,实验表明它可以克服模型过拟合,这可能由于alpha选择的随机性。在实践中, Parametric ReLU 和 Randomized ReLU 都是可取的。

6. 正则化(Regularizations)

6.1 L2正则化

6.2 L1正则化

6.3 最大范数约束

6.4 Dropout

7. 从数字中观察

7.1 从学习率观察

太高的学习率,loss曲线会很奇怪,很容易会出现参数爆炸现象;低学习率,loss下降很慢;高学习率,一开始loss会下降很快,但很容易跌入局部最小值;好的学习率应该平滑下降。

7.2 放大loss曲线观察。

图2中横坐标是epoch(网络在整个训练集上完整的跑一遍的时间,所以每个epoch中会有多个mini batches),纵坐标是每个训练batch的分类loss。如果loss曲线表现出线性(下降缓慢)表明学习率太低;如果loss不再下降,表明学习率太高陷入局部最小值;曲线的宽度和batch size有关,如果宽度太宽,说明相邻batch间的变化太大,应该减小batch size。

7.3 从精确率曲线观察。

图3中红色线是训练集上的精确率,绿色验证集上的精确率。当验证集上精确度收敛时,红线和绿线间隔过大很明显训练集上出现了过拟合。当两线间隔很小且准确率都很低时,说明模型学习能力太低,需要增加模型的capacity。

参考文献:

时间: 2024-07-29 00:15:19

深度神经网络训练的必知技巧的相关文章

关于手机端的几个提高流量和转化率的必知技巧

现 在打开生意参谋看一下自己的数据,大家会发现,绝大部分的类目,移动端的流量已经基本都超过了50%,有的甚至超过了80%,所以对卖家而言,无线端的重 要性已经不言而喻了.但是不少卖家对于如何布局无线端,以及如何做到无线端的精细化运营还并不是很了解或者还不是很在行. 以下分享些在无线端的运营方面有一些经验分享,告诉你无线的用户是怎样的,习惯如何养成,以及最重要的实战干货. 一.首先我们先说无线端的标题优化 1. 无线端标题优化的本质和PC端一样,不一样的地方,就是选高权重词的方法,无线端选词方法最

深度神经网络DNN的多GPU数据并行框架 及其在语音识别的应用

深度神经网络(Deep Neural Networks, 简称DNN)是近年来机器学习领域中的研究热点,产生了广泛的应用.DNN具有深层结构.数千万参数需要学习,导致训练非常耗时.GPU有强大的计算能力,适合于加速深度神经网络训练.DNN的单机多GPU数据并行框架是腾讯深度学习平台的一部分,腾讯深度学习平台技术团队实现了数据并行技术加速DNN训练,提供公用算法简化实验过程.对微信语音识别应用,在模型收敛速度和模型性能上都取得了有效提升--相比单GPU 4.6倍加速比,数十亿样本的训练数天收敛,测

第十一章——训练深度神经网络

上一章我们训练了一个浅层神经网络,只要两个隐层.但如果处理复杂的问题,例如从高分辨率图像中识别上百种类的物品,这就需要训练一个深度DNN.也行包含十层,每层上百个神经元,几十万个连接.这绝不是闹着玩的: 首先,需要面对梯度消失(或者相对的梯度爆炸)问题,这会导致浅层很难被训练. 其次,这么大一个网络,训练速度很慢. 最后,一个包含上百万参数的模型,存在很大过拟合的风险. 11.1 梯度消失(爆炸)问题 反向传播算法会计算损失函数关于每一个参数的偏导数,然后使用梯度下降更新参数.不幸的是,反向传播

Visual Studio (VS IDE) 你必须知道的功能和技巧 - 【.Net必知系列】

前言 本文主要阐述一些Visual Studio开发下需要知道的少部分且比较实用的功能,也是很多人忽略的部分.一些不常用而且冷门的功能不在本文范围,当然本文的尾巴[.Net必知系列]纯属意淫,如有雷同,基情四射.. 目录 WEB项目版本发布时 Web.config 中 Web.Release.config 和 Web.Debug.config 的使用. 项目属性下[生成事件]使用. 快速分析未知架构和类调用结构的方式(VS2010/2012). 一:Web.Release.config 和 We

人人必知的10个 jQuery 小技巧

原文地址:http://info.9iphp.com/10-jquery-tips-everyone-should-know/ 人人必知的10个 jQuery 小技巧 收集的10个 jQuery 小技巧/代码片段,可以帮你快速开发. 1. 返回顶部按钮 你可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. // Back to top $('a.top').click(function () { $(document.body).animate({sc

《安卓开发必知的50个技巧》读书笔记

记录一下看<安卓开发必知的50个技巧>觉得有用的一下技巧. include标签使用注意事项 如果想在标签中覆盖被包含布局所指定的任何android:layout_*属性,必须在标签中同时指定android:layout_width和android:layout_height属性,我们可以通过指定被包含布局的layout_width和layout_height属性都为0dp,这样做的目的是由被包含布局的使用者在标签中指定layout_width和layout_height属性,如果使用者不指定这

Neural Network and DeepLearning (5.1)深度神经网络为何很难训练

在深度网络中,不同层的学习速度差异很大.例如:在网络中后面的层学习情况很好的时候,前面的层常常会在训练时停滞不前,基本上不学习了.另一种情况恰恰相反,前面的层学习的很好,后面的层却停止学习了. 这是因为基于梯度下降的学习算法的本身存在着内在的不稳定性,这种不稳定性使得前面或者后面的层的学习停止. 消失梯度问题(The vanishing gradient problem) 在某些深度神经网络中,在隐藏层反向传播时梯度倾向于变小,也就是前面隐藏层的学习速度要慢于后面的隐藏层.这就是消失的梯度问题.

用spark训练深度神经网络

SparkNet: Training Deep Network in Spark 这篇论文是 Berkeley 大学 Michael I. Jordan 组的 ICLR2016(under review) 的最新论文,有兴趣可以看看原文和源码:paper,github . 训练深度神经网络是一个非常耗时的过程,比如用卷积神经网络去训练一个目标识别任务需要好几天来训练.因此,充分利用集群的资源,加快训练速度成了一个非常重要的领域.不过,当前非常热门的批处理计算架构(例如:MapReduce 和 S

谈谈如何训练一个性能不错的深度神经网络

谈谈如何训练一个性能不错的深度神经网络 深度学习大火,将各个数据集的state of the art不断地刷新,到了开源代码一放出,有种全民皆可刷排名的节奏. 不过可别把刷数据想的那么简单,不然大家去哪发paper,怎么混饭吃= = 但是我不想发paper就想占坑刷数据怎么办,看到cifar10都尼玛刷到了95%了,我这用caffe自带的小demo才得出78%的结果,caffe你确定不是在骗我? caffe确实没在骗你= =今天我给大家介绍一下如何刷出一个性能接近paper的神经网络 以CNN为