第5章 CHAPTER 5 深层神经网络的训练方法 本章将详细介绍深层神经网络训练过程中的相关细节和实践中经常使用的方法和技巧。神经网络的训练实质上是一个优化问题,5.1节和5.2节将详细介绍各种优化算法,并比较各种优化算法的优劣,帮助读者在实践中选择合适的优化算法。首先,对梯度下降算法存在的问题进行阐述,然后基于此引出其他改进的优化算法。这些改进的算法主要从两个方面对原始随机梯度下降算法进行改进,其中一大类优化算法旨在调整参数更新方向,优化训练速度; 而另一大类算法旨在调整学习率,即对步长做改进,使得优化更加稳定。调整参数更新方向的优化算法有动量法(或称为带动量的随机梯度下降算法)、Nesterov加速梯度; 调整学习率的算法主要包括AdaGrad、RMSprop、AdaDelta,而Adam算法对这两方面都做了相应的调整。另外,对于二阶优化算法牛顿法、拟牛顿法也会做相应介绍。5.3节介绍常见的几种参数初始化方法,如Xavier初始化、He初始化等。另外,还会介绍逐层进行批量归一化操作然后使用小随机数进行初始化的方法,这样可以降低对参数初始化的要求,在实践中取得了不错的效果。合理正则化的网络模型具有更好的泛化能力,5.4节将介绍几种常用的正则化策略。为了提升模型性能,5.5小节将介绍几种训练深层神经网络常用的小技巧,例如数据预处理、超参数调优等,有些方法已成为模型训练的标准操作。 5.1参数更新方法 本节介绍参数更新方法。首先,分析梯度下降算法的问题,然后介绍改进的优化策略,目的是调整参数更新方向,优化训练速度,包括基于动量的更新。另外对于二阶优化算法牛顿法、拟牛顿法也会做相应介绍。 5.1.1梯度下降算法的问题 在第2章中已经提到,模型表现的好坏是通过损失函数衡量的,需要找到让损失函数取得最小值的参数矩阵W,这一过程是一个优化问题,通常使用迭代优化方法来找到最优解。需要注意的是,对于深层神经网络,由于其高度非线性特性,优化的目标函数是一个非凸函数,因此神经网络的优化是一个非凸优化问题,策略上与凸优化问题有些不同。第2章提到了梯度下降算法,以及应对大数据量高计算成本的解决方案——小批量梯度下降算法和随机梯度下降算法,它们分别使用全部训练集样本、小批量训练集样本和一个样本求解损失和梯度。小批量梯度下降算法和随机梯度下降算法是对实际损失和梯度的估计。实际应用中,可以根据数据量和参数量,以及精度和计算量之间的权衡,任意选取其中一种方式。梯度下降算法是最简单的一种参数更新策略,但其存在许多问题。 (1) “z”字形下降: 当损失函数具有高条件数时会发生这种情况。也就是说,当损失函数对不同方向的参数变换敏感程度不同时,运行梯度下降算法参数会产生“z”字形下降。图51所示为损失函数等高线图,对于该损失函数只有两个参数W1和W2,如果改变其中之一,如在水平方向改变W1值,则损失函数变化非常慢,而在垂直方向对W2进行相同程度的改动,损失值变化则非常快。对于这样的损失函数,在其上运行随机梯度下降算法会产生“z”字形下降,原因是这类目标函数的梯度方向与最小值方向不一致,当计算梯度并沿着梯度前进时,在敏感方向变化较大,而在不敏感方向变化较小,可能会一遍遍跨过等高线,“z”字形前进或者后退,在敏感度较低的维度前进速度非常慢,在敏感度较高的维度上进行“z”字形运动,使得参数更新效率低下,这个问题在高维空间更加普遍。 图51二维损失函数等高线 (2) 局部极小值(可辨识性问题)、鞍点和平坦区域: 如图52所示的一维损失函数,损失函数中间有一段凹陷,运行梯度下降算法会出现参数更新“卡”在凹陷处的现象,最终得到一个局部极小点而非全局最小点。因为局部极小点处梯度为0, 图52局部极小点和鞍点 梯度下降算法在此处不执行更新。可以通过合理选择参数的初始值远离局部最小点来解决这个问题。实际上,局部极小值问题在低维空间更加严重,在高维空间并不是一个很大的问题。对于一个含有一亿个参数的高维空间,要求一个点对于一亿个维度的点都是局部极小的,向任何一个方向前进较小的一步损失都会变大,这种情况非常稀少。如果一个点在某一维度上是局部极小点的概率为p,那么在整个参数空间(假设有一亿个参数),该点是局部极小点的概率为p108,随着网络规模的增加,陷入局部极小值的可能性大大降低。 高维空间中更为突出的一个问题是鞍点,鞍点处梯度也为零。不同于局部极小点或者局部极大点在任何维度上都是局部极大点或者局部极小点,鞍点在某些维度上是局部极大点在某些维度上是局部极小点。图52中下面的曲线是二维情形中鞍点的示意图,可以看到,鞍点在水平维度上为局部极小点,而在垂直维度上为局部极大点。鞍点是高维空间中的难点,如果在一个有一亿个维度的参数空间,鞍点部分维度上为局部极小点的概率远远大于局部极小点。因此,高维空间中大部分梯度为0的点都是鞍点,并非局部极小点。鞍点使得基于梯度下降的优化算法会在此处停滞,难以从鞍点处“逃离”。在高维空间中,这是一个亟待解决的问题。 另外,还可能存在恒值的宽阔平坦区域。因为深层神经网络的参数数量极大,具有一定的冗余性,每一个参数对损失函数的贡献很小,这就导致损失函数的这种特殊“地形”,在平坦区域内梯度接近于0,若该区域又恰好是“高原”地带(即损失值很高的区域),也会导致非常差的优化结果。 (3) 随机性: 随机性是随机梯度下降的另一个问题。损失函数是在整个训练集上所有样本上定义的,如果训练集有N个样本,那么损失即这N个样本损失的和。出于提升效率的考虑,实际中通过使用小批量样本来对损失和梯度进行近似估计。也就是说,在每一次更新中没有使用真实的梯度,而是使用带噪声的梯度估计来执行参数更新,这会导致参数更新比较曲折,从而需要很长的时间达到收敛状态。 另外一个在循环神经网络中比较常见的问题是,当损失函数呈现悬崖结构,在悬崖结构附近梯度非常大,使用普通梯度下降算法可能会导致参数更新发生很大的变化,从而出现梯度爆炸现象。可以使用启发式方法解决这个问题,当更新的梯度值过大,超过规定的阈值时,就进行截断,使用于更新的梯度值低于阈值,这种方法叫作梯度截断(Gradient Clipping)。 5.1.2基于动量的更新 由于梯度下降算法存在较多问题,因而提出更多高级的优化策略。动量法(Momentum Method)在梯度下降算法的基础上引入动量项,通过累积之前梯度的指数衰减加权移动平均代替当前的梯度作为参数的更新方向,实现迭代更新,更新公式如式(52)所示,其中v由式(51)给出。 v←ρv-αθfθ=ρv-αg(51) θ←θ+v(52) 对于神经网络中的损失函数,即需要优化的目标函数,本章统一使用函数fθ表示,fθ=1m∑mi=1Lfx(i);θ,y(i),fx(i);θ指神经网络学习得到的函数,1m∑mi=1L(f(x(i);θ),y(i))为数据损失。有时需要优化的目标函数不仅仅为数据损失,有可能包含正则项(此部分内容见5.4节),由于5.1节和5.2节涉及的优化方法不需要目标函数的具体表达式,因此可简单使用fθ表示。另外,优化方法常用到目标函数关于参数的梯度,为方便将其表示为g,即g=θfθ。符号θ表示需要优化的参数,既包括权重W,也包括偏置b。 v表示速度,是参数在参数空间移动的方向和速率,v一般初始化为0。在第k次迭代时,首先使用梯度信息更新速度,然后使用更新后的速度进行参数更新,当前速度实质上是以往累积梯度的移动平均。这与梯度下降算法不同,梯度下降算法直接使用梯度信息对参数进行更新。α为学习率,与梯度下降算法中含义相同。ρ为动量因子,根据经验,ρ一般设置为0.5、0.9、0.95和0.99中的一个值。与学习率类似,一般将ρ设置为随时间变化的值能够改善优化性能,初始值一般设置为一个较小的数值,随后慢慢变大。ρ决定了前一时刻的速度对当前时刻速度预测的贡献。ρ越大,代表之前时刻累积的梯度对现在梯度方向的影响越大,而α代表当前时刻梯度对参数更新方向的重要性。完整的基于动量的梯度下降算法或者称为动量法的算法流程如表51所示。 表51基于动量的随机梯度下降(动量法) 1. Input:初始参数θ,初始速度v0 2. While 没有达到停止准则 do 3. 从训练集中采集包含m个样本的小批量x(1),…,x(m),对应目标为y(i)。 4. 计算梯度估计: g←1mθ∑mi=1Lfx(i);θ,y(i) 5. 计算速度更新: v←ρv-αg 6. 应用更新: θ←θ+v 7. End while 物理学中,一个物体的动量指该物体在它的运动方向上保持运动状态的趋势,动量表示为物体质量与速度的乘积。在动量法中,将参数的更新看作粒子的运动,并且假定粒子的质量为单位质量,所以粒子的动量值等同于粒子的速度值。设想一个具有单位质量的小球从一个小坡上滑下。首先,小球有一个初始速度v0,然后小球由于力的作用向着下坡的方向滚动。在动量法中,力正比于损失函数的负梯度,根据公式F=ma,力给小球一个加速度,使得小球速度改变。传统的梯度下降算法中,梯度直接改变位置; 动量法使用梯度改变速度,速度再改变位置。超参数ρ可以看作摩擦系数,能够有效地抑制粒子的速度,降低粒子动能,使粒子最终能够停下来。 动量法可以帮助解决梯度下降算法存在的问题。尽管在局部极小点和鞍点附近梯度为0,但小球有累积的速度,这个速度可以帮助小球越过梯度为0的点,而不至于陷入这些点无法继续更新。另外,当损失函数对不同方向的参数变换敏感程度差异较大时,运行普通梯度下降算法会出现“z”字形下降,使用动量法可以很好地进行改善,因为每个参数的更新不仅取决于当前的梯度,还取决于之前累积的梯度加权平均。如果一段时间内的梯度方向一致,那么参数更新的幅度将大于仅使用当前梯度进行更新的幅度,这会起到加速作用,这对应于参数不敏感的方向,在这些方向上更新步幅会增大,从而在这些方向获得加速; 相反地,如果一段时间内的梯度方向不一致,可以很快地抵消“z”字形梯度更新的情况,有效减少参数敏感方向步进的数量。因此,使用动量法可以有效提升效率, 图53动量法参数更新过程 加速学习进程。同时,动量法可以获得一系列随时间变换的速度,估计梯度时可抵消部分噪音,与随机梯度下降相比,能够更加平稳地接近最小值点。图53可视化了参数的更新过程,黑点代表不同迭代参数的大小,虚线箭头代表当前参数值处损失函数关于参数的梯度,实线代表使用动量法执行更新的过程。可以看到,动量法参数更新方向实质上与真实梯度方向有偏差,减小了在参数敏感方向的震荡,加速了收敛过程。 图54中,将动量法的每一步更新用向量化的形式表示出来,黑点为当前参数的位置,“梯度”向量表示负梯度或者对当前位置梯度估计的负方向。当使用动量法进行更新时,实际上是对“梯度”向量和“速度向量”两者进行加权平均进行步进。 图54动量法与Nesterov动量的比较 另一种改进的动量法为Nesterov 加速梯度(Nesterov Accelerated Gradient,NAG),也称为Nesterov动量(Nesterov Momentum)。在动量法中,先获取当前位置的梯度,然后使用梯度和速度的加权平均进行更新。而Nesterov动量中,需要根据当前的速度方向预先前进一步,在这个新的位置求取梯度,然后再回到起始位置,根据速度和新位置的梯度的加权平均实现更新。NAG的速度更新公式如式(53)所示,参数更新公式与式(52)相同,算法流程见表52。 v←ρv-αθfθ+ρv(53) 表52基于Nesterov动量的随机梯度下降算法 1. Input:学习率α,动量因子ρ 2. Input:初始参数θ,初始速度v0 3. While 没有达到停止准则 do 4. 从训练集中采集包含m个样本的小批量x(1),…,x(m),对应目标为y(i)。执行临时更新: θ~←θ+ρv 5. 计算梯度估计: g←1mθ~∑mi=1Lfx(i);θ~,y(i) 6. 计算速度更新: v←ρv-αg 7. 应用更新: θ←θ+v 8. End while 实际两者的差别在于梯度的计算,动量法在当前位置计算梯度,NAG施加速度后在新的位置计算梯度。可以这样解释: 既然速度向量最终会将小球带到虚线箭头指向的位置,那与其在现在的位置计算梯度,不如向前看一步,用未来位置计算梯度。实验证明,NAG收敛速度会更快。 图55损失函数的一阶线性近似 5.1.3二阶优化方法 以上介绍的几种方法都是一阶优化方法,因为仅使用梯度信息。对于想要优化的目标函数fθ,在点θ0处进行一阶泰勒公式展开可得 fθ≈fθ0+θ-θ0Tg(54) 其中,g为fθ的梯度在θ0处的值,通过计算点θ0处的梯度可以得到目标函数在θ0局部区域的线性近似,如图55所示。使用近似函数代替原始函数计算梯度更新,即在原始函数的梯度方向上前进较小的一步。由于该近似仅在局部小区域内成立,在更大的范围内并不成立,因此不能在该方向前进太多,这就是一阶优化方法使用梯度的原因。对目标函数进行一阶近似后,将下降方向选择为下降最快的负梯度方向,因此梯度下降法也被称为最速下降法。 一阶优化方法使用函数的一阶偏导数信息,也存在使用二阶偏导数来指导搜索的二阶优化方法。将目标函数在θ0处做二阶泰勒公式展开,得到fθ的近似式为 fθ≈fθ0+θ-θ0T·g+12θ-θ0THθ-θ0(55) 其中,g仍为fθ的梯度在θ0处的值,H是θ0点的Hessian矩阵,Hessian矩阵为fθ二阶偏导数组成的矩阵,其定义如下: Hfθi,j=2θiθjfθ(56) 基于二阶近似,目标函数可以通过一个二次函数来局部近似,如图56所示。不同于一阶近似的线性函数,可以通过近似二次函数的最小值点,不断迭代找到原始目标函数的最小值点,这就是二阶优化的思想。对于该近似二次函数的最小值点θ, 图56损失函数的二阶近似 可以通过解析方法求出。 θ=θ0-Hfθ0-1θfθ0(57) 此方法也被称为牛顿法。计算Hessian矩阵,即二阶偏导数的矩阵,然后求逆,可以直接得到对原始目标函数进行二次近似后的最小值。Hessian矩阵也被称为牛顿步长,它等价于一阶优化方法中的超参数α(也叫步长或者学习率)。实际上,二阶优化方法的好处就在于没有学习率,不用通过交叉验证确定学习率的值,相较于一阶优化方法,这是一个巨大的优势。由于神经网络中需要优化的目标函数通常不是二次函数,因此需要多次对原目标函数进行近似并使用公式(57)得到近似函数的最小值。综上所述,牛顿法先基于二阶泰勒公式展开式近似θ0处附近的fθ,然后使用以下更新公式: θk=θk-1-Hfθk-1-1θfθk-1(58) 直接得到近似函数的最小值,再在新的位置对损失函数进行二阶泰勒公式展开,这样不断迭代更新近似函数。式(58)中θk表示第k轮迭代更新后的参数,θk-1为上一轮迭代的参数。经证明,该方法能够比梯度下降法更快地达到临界点。 Hessian矩阵利用了二阶偏导数信息,从而使得参数更新更加高效,它描述了损失函数的局部曲率,使得在曲率小时能大步长更新,曲率大时小步长更新,这可以解决梯度下降算法中的“z”字形下降问题。牛顿法在选择方向时,不仅考虑梯度还考虑梯度的变化。梯度下降法每次前进时选择坡度最陡峭的方向(即梯度方向),而牛顿法不仅考虑当前坡度是否足够大,还会进一步考虑迈出一步后坡度是否变得更大。因此,牛顿法比梯度下降法更具全局思想,所以收敛速度更快。 对于牛顿法而言,鞍点是一个突出问题,如果没有适当地改进,牛顿法就会陷入鞍点。在深度神经网络中,其高度非线性导致优化的目标函数通常是一个非凸问题,这种情形下,牛顿法就会被吸引到鞍点。换句话说,由于非凸性导致Hessian矩阵非正定,在靠近鞍点处,牛顿法实际上会朝错误的方向进行更新。高维空间中鞍点数量激增,这是牛顿法不能代替梯度下降法用于训练大型神经网络的一个原因。有部分研究者提出了无鞍点牛顿法(Saddlefree Newton Method),或许可以帮助二阶优化方法扩展到大型神经网络。另外,对Hessian矩阵求逆带来存储和计算负担,Hessian矩阵元素个数是参数数量N的平方,对于一个包含100万个参数的神经网络模型, Hessian矩阵大小为 10000002,占用将近3725GB的内存。牛顿法需要求解这个N×N矩阵的逆矩阵,计算复杂度为ON3。每次迭代更新都要重新计算新位置的Hessian矩阵的逆矩阵,导致更新速度非常慢,因此牛顿法只适用于具有少量参数的网络。为解决Hessian矩阵求逆的复杂度问题,提出一系列拟牛顿法,旨在对Hessian矩阵的逆矩阵进行近似来代替Hessian矩阵进行更新,可使用正定矩阵来近似Hessian矩阵的逆矩阵。正定矩阵能保证每一步搜索方向是向下的,可降低运算复杂度。比较常用的两种拟牛顿法为DFP(DavidonFletcherPowell)算法和BFGS(BroydenFletcherGoldfarbShanno)算法,以及为解决BFGS高存储代价的无存储的LBFGS(Limitedmemory BFGS)算法。 5.1.4共轭梯度 共轭梯度法是介于梯度下降法和牛顿法之间的一种方法,它既克服了梯度下降法收敛慢的问题,又不用像牛顿法那样使用Hessian矩阵的逆矩阵,它仅利用一阶导数信息,存储量小,具有步收敛性,稳定性高,并且不需要任何外部参数。 对于共轭梯度法的研究来源于对梯度下降法缺点的研究,梯度下降法每次迭代都将当前位置的梯度方向作为更新方向,使用学习率参数确定在该更新方向上前进的步长。有几种不同的步长选择方式,通常的方式是选择一个小的常数,并随迭代次数衰减。还有一种被称为线搜索的策略,该策略在每一个搜索方向(即梯度方向)上选取能使得目标函数fθ-αθfθ最小的步长α,可以保证在每个线搜索方向上都能找到该方向上的极小值,将线搜索迭代地应用于与梯度相关的方向直至找到目标值。 图57二次目标函数使用随机梯度下降的参数更新路线 实际上,这是一种相当低效的方式。如图57所示,对于二维的二次目标函数,运用梯度下降算法更新路线,在每个更新方向执行线搜索,因此每次迭代使用的是最优步长α,可以看到梯度下降路线呈现锯齿形,收敛速度很慢。尽管这种方法比使用固定学习率更优,但是算法朝最优目标值前进的路线非常曲折。因为每一个由梯度给出的线搜索方向都与上一个线搜索方向正交,下面给出线搜索方向正交性的数学证明: 在迭代点θk∈Rn处,沿梯度方向dk执行线搜索,搜索满足式(59)的步长αk,将fθk+αdk关于α求导可得式(510),由于fθk+1=dk+1,所以方向dk与dk+1是正交的,因此上一次线搜索方向并不会影响下一次线搜索的方向,在当前梯度方向执行线搜索下降到极小值,再在新的位置重新确定搜索方向,这相当于放弃了之前线搜索方向上取得的进展,共轭梯度法则试图解决这个问题。 αk= argminfθk+αdk(59) dTk×fθk+1=0(其中,θk+1=θk+αkdk)(510) 共轭梯度法最早由Hastiness和Stiefle提出,是一种旨在求解线性方程组Ax=b的迭代方法,其中A为实对称正定矩阵。求解线性方程组Ax=b实际上可以转换为求解式(511),其中bTb项对最小值点没有影响,因此可以等价转化为求二次规划问题式(512)。 min‖Ax-b‖22=minxTATAx-bTAx+bTb(511) min‖Ax-b‖22=minxTATAx-bTAx(512) 因此,对于标准目标函数 minθfθ=12θTQθ+qTθ(513) 其中,Q∈Rn×n为对称正定矩阵,q∈Rn,由于矩阵Q正定,目标函数的Hessian矩阵2fθθθT=Q>0,故该问题实际上是一个凸优化问题。对于n维优化问题θ∈Rn,共轭梯度法最多n次迭代就可以准确找到最优解。 首先介绍共轭的概念,对于向量d1,…,dm∈Rn,对于对称正定矩阵Q∈Rn×n,若满足dTiQdj=0,i≠j,则称d1,…,dm关于Q相互共轭,向量组d1,…,dm称为Q共轭向量组,并且d1,…,dm线性无关。共轭梯度法旨在寻找一组共轭向量作为每次迭代的搜索方向,然后在这些方向上执行线搜索取得在该方向上的极小值。与梯度下降法不同,每一次搜索方向不仅由当前梯度方向得到,也与前一次搜索方向有关,当沿着当前搜索方向求极小值的时候,不会影响在之前方向取得的极小值,即不会舍弃之前方向上的进展。对于第k次迭代,搜索方向dk满足 dk=fθk+βkdk-1(514) 其中,系数βk用于控制先前方向对当前方向的贡献,可以证明当前搜索方向dk与先前所有的搜索方向d0,…,dk-1是满足两两共轭的,因此由当前迭代点梯度fθk和上一次搜索方向dk-1来确定新的搜索方向是可行的,一旦确定了每一次迭代的搜索方向就可以在这些方向上执行线搜索确定每一次迭代的步长。下面详细说明搜索方向dk和最优步长αk的确定方法。 1. 线搜索方向的确定 根据公式(514),每次求新的搜索方向需要先求解系数βk,由于当前搜索方向与前一搜索方向共轭,因此dTk-1QdK=0,将式(514)代入可得 βk=dTk-1QfθkdTk-1QdK-1(515) 可以看到,直接使用该方法求解每一次迭代的线搜索方向dk时需要求解参数βk,而该参数的求解需要计算Hessian矩阵,为了避免应用Hessian矩阵的运算,对原始的共轭梯度法进行修正,使得不需要推导计算Hessian矩阵也能求得这些共轭的搜索方向。常用的两种方法为FletcherReeves共轭梯度修正方法和PolakRibière共轭梯度修正方法,参数βk的计算公式如式(516)和式(517)所示。 1) FletcherReeves βk=θfθkTθfθkθfθk-1Tθfθk-1(516) 2) PolakRibière βk=θfθk-θfθk-1Tθfθkθfθk-1Tθfθk-1(517) 2. 最优步长的确定 确定了每次迭代的搜索方向,便可以在此方向上执行线搜索,确定每次迭代的最优步长。根据定义将式fθk+αdk关于α求导,得到αk,详细步骤如下: 令 dfθk+αdkdα|α=αk=0 得 dTk×fθk+1=0 其中,fθk+1=Qθk+1+q=Qθk+1-θk+fθk,代入上式,得 dTk×Qθk+1-θk+fθk=0 dTk×Qαkdk+fθk=0 αk=-dTkQfθkdTkQdk(518) 共轭梯度法详细流程见表53。 表53共轭梯度法 对于凸二次优化问题式(513): 1. 任意选择初始点θ0,初始更新方向d0=fθ0 2. 判断fθk的值: 若等于0,θk即为最优值,返回θk并停止迭代; 否则进行更新θk+1=θk+αkdk,αk由式(518)确定 3. 根据式(514)更新下一次搜索方向,其中βk见式(516)和式(517) 重复步骤2,3直至找到最优解 通过共轭梯度法的算法步骤可以看出,其只需要计算和存储目标函数的梯度值,与牛顿法dk=-Hkgk (其中Hk是Hessian矩阵在θk处的值)相比,共轭梯度法存储量大大减小,因此适合求解大规模问题。同时,对于梯度下降法收敛速度慢以及锯齿现象也有很大改善,但其收敛速度仍然显著慢于牛顿法或拟牛顿法。 以上对于共轭梯度法的讨论都是基于目标函数是凸二次函数的情况,是用于求解线性方程组的线性共轭梯度方法。对于深层神经网络或者其他深度学习模型,其目标函数远比二次函数复杂得多,共轭梯度法仍然适用,但是需要做一些修改。Fletcher和Reeves最早将线性共轭梯度法的思想用于求解非线性最优化问题。非线性共轭梯度法求解无约束极小化问题minfθ,其中f:Rn→R连续可微。不同的非线性共轭梯度法求解βk的算法不同,例如上文提到的FletcherReeves方法和PolakRibière方法,实际上还有很多其他方法,在此不展开介绍。需要注意的是,当目标函数是凸二次函数,并且步长αk由精确搜索得到(精确搜索要求步长αk根据式(59)求得,实际上还有其他搜索策略,例如Armijo搜索和Wolfe搜索以及满足Goldstein条件的非精确搜索),并且第一个搜索方向是梯度方向时,非线性共轭梯度法等价于标准的线性共轭梯度法。当采用精确线搜索时,所有的共轭梯度法都是下降算法,即保证每一个搜索方向都是下降方向。而采用非精确线性搜索时则不满足这样的性质,某些非线性共轭梯度法不能保证每一步都是下降方向。因此,非线性共轭梯度算法执行过程中可能需要重设参数,在执行若干步后沿负梯度方向重新开始并采取精确线搜索。实践表明,可以使用非线性共轭梯度算法训练神经网络,使用随机梯度下降迭代若干步来初始化参数效果会更好。有许多对于非线性共轭梯度法全局收敛性分析的研究,感兴趣的读者可自行查阅。 5.1.5拟牛顿法 由于Hessian矩阵维度过大带来的巨大计算量,使得牛顿法无法有效执行。为了克服这个问题,在牛顿法的基础上提出了系列改进方法——拟牛顿法(QuasiNewton Methods)。该方法的基本思想是使用正定对称矩阵近似Hessian矩阵,使用近似矩阵执行参数的更新,因此拟牛顿法可以看作对牛顿法的近似。不同的拟牛顿法构造近似矩阵的方法不同,常用的拟牛顿法包括DFP、BFGS、LBFGS等。拟牛顿法只需要使用一阶导数,不需要计算Hessian矩阵及其逆矩阵,减少了运算复杂度,因此能够更快地收敛。 构造Hessian矩阵的近似矩阵需要满足一定的条件——拟牛顿条件(也称为拟牛顿方程或者割线条件),该条件给出了构造近似矩阵的理论指导,构造的矩阵必须满足这个条件。回顾牛顿法,首先对目标函数在任一点θk+1处进行二阶泰勒公式展开得到近似函数,如式(519); 然后对近似函数求导得到式(520)。令θ=θk代入式(520)并移项整理可得式(521),通过引入变量sk和yk将式(521)进行整合可得式(524),使用Hessian矩阵的逆矩阵的形式进行表达则为式(525)。式(526)和式(527)即所谓的拟牛顿条件,二者是等价的,构造的近似矩阵需要满足相应约束,即H的近似矩阵B或者H-1的近似矩阵D都需要满足这个条件。 fθ≈fθk+1+θ-θk+1T·fθk+1+12θ-θk+1T·2fθk+1·θ-θk+1(519) fθ≈fθk+1+Hk+1·θ-θk+1(520) gk+1-gk≈Hk+1·θk+1-θk(521) sk=θk+1-θk(522) yk=gk+1-gk(523) yk≈Hk+1·sk(524) sk≈H-1k+1·yk(525) yk=Bk+1·sk(526) sk=Dk+1·yk(527) 有了拟牛顿条件,如何在满足此条件的基础上构造近似矩阵呢?下面将介绍几种常见的拟牛顿法。对于DFP算法,其实际上对Hessian矩阵的逆矩阵进行近似运算,即求矩阵D; 而BFGS算法直接对Hessian矩阵进行运算,求其近似矩阵B,BFGS算法求得Hessian矩阵的近似矩阵B后还需要对B求逆矩阵用以执行参数的更新,接下来将简述这两种方法的迭代步骤。 1. DFP算法 DFP算法最早由Davidon W.D.于1959年提出,随后由Fletcher R.和Powell M.J.D.加以完善和发展,是最早的一种拟牛顿法,DFP算法因此以三人的名字命名。该算法的核心是迭代更新H-1的近似矩阵D,其公式为 Dk+1=Dk+sksTksTkyk-DkykyTkDkyTkDkyk(528) 完整的DFP算法步骤如表54所示。 表54DFP算法 1. 任意选择初始点θ0,令近似矩阵D0=I,k=0,设置精度阈值ε 2. 确定搜索方向dk=-Dk·gk 3. 利用线搜索得到当前搜索步长αk,执行更新θk+1=θk+dkαk 4. 计算gk+1,若‖gk+1‖<ε,算法结束 5. 计算yk=gk+1-gk,并更新近似矩阵Dk+1=Dk+sksTksTkyk-DkykyTkDkyTkDkyk 6. 令k←k+1,重复步骤2~5 2. BFGS算法 BFGS算法同样是以4个发明者的名字命名的。与DFP算法不同,BFGS算法的核心是求得Hessian矩阵的近似矩阵。其性能优于DFP算法,已取代DFP算法成为求解无约束非线性优化问题的流行方法。BFGS算法的核心迭代更新公式如式(529)所示。 由于式(529)计算得到的是Hessian矩阵的近似矩阵,而执行参数更新需要用到Hessian矩阵的逆矩阵,因此还需要对得到的近似矩阵求逆矩阵,使用ShermanMorrison公式,可以将式(529)转换成含有近似矩阵的逆矩阵的更新公式,如式(530)所示。Powell证明了具有Wolfe搜索的BFGS算法的全局收敛性和超线性收敛性。 Bk+1=Bk+ykyTkyTksk-BksksTkBksTkBksk(529) B-1k+1=I-skyTkyTkskB-1kI-yksTkyTksk+sksTkyTksk(530) 完整的BFGS算法如表55所示。 表55BFGS算法 1. 任意选择初始点θ0,令近似矩阵D0=I,k=0,设置精度阈值ε 2. 确定搜索方向dk=-Dk·gk 3. 利用线搜索得到当前搜索步长αk,执行更新θk+1=θk+dkαk 4. 计算gk+1,若‖gk+1‖<ε,算法结束 5. 计算yk=gk+1-gk,并更新近似矩阵 B-1k+1=I-skyTkyTkskB-1kI-yksTkyTksk+sksTkyTksk 6. 令k←k+1,重复步骤2~5 3. LBFGS算法 由于BFGS算法在每次迭代中必须存储近似矩阵Dk,对于含有N个参数的模型,Dk矩阵的大小为N×N。对于百万级别参数的深度学习模型,需要极大的存储代价,一般的服务器是很难承受的。因此,为了减少BFGS算法迭代过程中所需的内存开销,LBFGS算法通过改进BFGS算法来避免存储完整的近似矩阵,大大降低了存储代价。与BFGS算法不同,LBFGS算法不再存储完整的近似矩阵Dk,而是存储用于计算Dk的向量序列si,yi,当需要使用矩阵Dk时,就利用存储的向量序列si,yi计算得到。另外,用户也可以只选择存储最近的m个向量si和yi,而非存储计算过程中所有的si和yi。矩阵Dk+1的计算需要使用序列si,yiki=0,如果只存储m组,只需要存储最近的m组序列si,yiki=k-m+1,因此计算得到的Dk+1是近似值。这样存储的代价由原来的ON2降为OmN。 5.2自适应学习率算法 本节介绍调整学习率的优化算法,主要包括AdaGrad、RMSprop、AdaDelta和Adam算法,并对这几种优化方法进行比较。 5.2.1学习率衰减 学习率表示每次更新的幅度,是深度学习中最重要的超参数,必须谨慎设置。学习率太大会导致损失函数爆炸,容易在目标值周围剧烈震荡,不能收敛到目标值; 而学习率太小则导致收敛速度过慢,效率不高。选择合适的学习率需要一定的技巧。实践中,将学习率随时间进行衰减(学习率衰减也称学习率退火),训练开始时使用较大的学习率以保证收敛速度,迭代过程中逐渐衰减,在接近最优点附近时使用较小的学习率。因为在目标值附近,梯度已经很小了,维持原有的学习率将使得参数在最优点附近来回震荡,此时降低学习率损失函数会获得进一步的下降。 学习率随步数衰减的设置方式: 根据经验人为设定,例如训练若干轮或迭代若干次后,将学习率进行衰减。具体何时进行衰减以及衰减多少依赖于具体问题和选择的模型。实践中的一种经验做法是,使用初始学习率训练,同时观察验证集上的错误率,当验证集上的错误率不再下降时,就乘以一个常数(例如0.5)降低学习率。 (1) 逆时衰减 αt=α011+βt(531) (2) 指数衰减 αt=α0βt(532) (3) 自然指数衰减 αt=α0e-βt(533) 其中,α0为初始学习率,第t次迭代的学习率为αt,β为衰减率,一般取值为0.96。需要注意的是,上述学习率的调整方法对所有参数适用,即所有参数在每次迭代时使用的学习率是相同的,进行相同的衰减。但是,由于损失函数在每个参数维度上的收敛速度不同(如图51中的示例),因此有必要根据不同参数的收敛情况分别设置下学习率,根据不同的参数自适应地调整每个参数学习率的方法包括AdaGrad、RMSprop、AdaDelta等,这些方法为每个参数设置不同的学习率。下面将详细介绍这几种方法。 5.2.2AdaGrad算法 AdaGrad(Adaptive Gradient)是自适应学习率算法的一种,由斯坦福大学的John Duchi教授在其攻读博士期间提出,基本思想是使用L2正则化对梯度进行调节,核心思想是训练过程中累加梯度平方和,如式(534)所示,gk表示第k次迭代的梯度值。在第k次迭代时,先累加之前所有迭代步骤的梯度的平方和(符号“⊙”表示逐元素进行乘积),然后更新参数向量时使用初始学习率除以该项,如式(535)所示,其中α为初始学习率,ε是为了防止分式分母为0而设置的小常数,一般取值为e-10~e-7,另外,分式中的加、除、开平方运算都是逐元素进行的。 Gk=∑ki=1gi⊙gi(534) Δθk=-αGk+ε⊙gk(535) AdaGrad算法对于Hessian矩阵高条件数的情况很有帮助,这种情况下目标函数对不同维度的参数敏感度不同,相对敏感的维度坡度比较陡峭,因此梯度较大,而不太敏感的维度坡度比较平缓,因此梯度较小,此种情形运行梯度下降算法会导致“z”字形下降,AdaGrad算法可以很好地解决这个问题,对于小梯度方向,累加的梯度和是一个较小的数值,对此方向的学习率进行自适应调整,使用原始学习率除以该项,可以提升在该方向上的训练速度; 而在大梯度方向会累加一个相对较大的梯度和,得到较大的除项,导致该方向的学习率下降,因此会相应地降低该方向上的训练速度。尽管调整后小梯度方向的学习率相对较大,大梯度方向的学习率相对较小,但整体上随着迭代次数的增加,累加的梯度和是单调递增的。因此,对于所有的维度,学习率都是逐渐减小的,这也导致了AdaGrad算法的一个问题: 随着迭代步骤k的增加,更新的步长越来越小。对于凸函数,AdaGrad算法表现良好,会在局部极小点附近慢下来并最终收敛; 但对于非凸的目标函数,AdaGrad算法可能会导致学习率过早和过量地减小,以至于算法还没有找到最优点就停滞不前了,很难再继续搜索最优点。 5.2.3RMSProp算法 针对AdaGrad算法存在的问题,Geoffrey Hinton提出另一种改进的自适应学习率的RMSProp算法,该方法以一种相对温和的方式调整学习率,从而改善了AdaGrad算法中因学习率单调下降导致的过早衰减问题。RMSProp算法的大体思想与AdaGrad算法相同,只是将累加梯度平方和变为梯度平方指数加权的移动平均,如式(536)所示。其中,β为衰减率,一般设置为0.9。然后,使用原始学习率除以该项进行更新,如式(537)所示,α为原始学习率。因此,相对于AdaGrad算法,RMSProp算法给遥远的历史梯度的平方一个很小的权重,相当于舍弃遥远的历史值,参数的学习率不会呈衰减趋势,有可能变小也有可能变大。RMSProp算法已经作为一种有效的优化算法用于训练深层神经网络,并成为广泛使用的优化算法之一。 Gk=βGk-1+1-βgk⊙gk=1-β∑ki=1βk-igi⊙gi(536) Δθk=-αGk+ε⊙gk(537) 5.2.4AdaDelta算法 AdaDelta算法是对AdaGrad算法的另一种改进算法,由Matthew D.Zeiler提出。尽管RMSProp算法解决了AdaGrad算法存在的学习率衰减的问题,但是原始学习率仍然需要人为设置。 AdaDelta算法使用前后两次参数更新差值Δθ的平方指数衰减移动平均来代替原始学习率,仍然使用梯度平方的指数衰减移动平均来调整学习率。对于第k次迭代,RMSProp算法根据历史迭代参数更新差Δθ的平方求移动平均,如式(538)所示。其中,Δθτ(1≤τ≤k-1)是前k-1次迭代的更新差,ΔX2k-1为前k-1次迭代的参数差平方的移动平均,β1为衰减率。使用前k-1次迭代求得的量ΔX2k-1开平方作为第k次迭代的未调整学习率。然后,与RMSProp算法的处理方式相同,对除以梯度平方的指数衰减进行调整,得到完整的第k次迭代的学习率,更新公式为式(539),此时可以计算出第k次迭代的更新差值,便可以再次使用更新公式(538)计算下一次迭代的学习率了。可以看到,AdaDelta算法将RMSProp算法中初始学习率α改为随迭代步骤动态计算的ΔX2k-1,这在一定程度上抑制了学习率的波动。 ΔX2k-1=β1ΔX2k-2+1-β1Δθk-1⊙Δθk-1(538) Δθk=-ΔX2k-1+εGk+εgk(539) AdaDelta算法在训练的初期和中期具有不错的加速效果,但到训练后期,可能会陷入局部极小值,在局部较小值附近抖动。此时,若换作带动量的随机梯度下降算法并将学习率降低一个量级,会在验证集上获得2%~5%正确率的提升。 5.2.5Adam算法 自适应动量估计(Adaptive Moment Estimation,Adam)是由Kingma D.P.和Ba J.提出的另外一种自适应学习率算法,它融合了动量法和RMSProp算法的优势,既使用动量法中梯度的移动平均代替负梯度方向作为参数更新方向,同时对不同的参数进行自适应调整学习率。首先,与动量法相同,Adam算法计算梯度的指数衰减移动平均作为新的更新方向,如式(540)所示。然后,与RMSProp算法相同,计算梯度平方的指数衰减移动平均来调整学习率,如式(541)所示,其中β1和β2是两个移动平均的衰减系数,一般β1设为0.9,β2设为0.99。式(540)和式(541)可以看作是对梯度一阶矩和二阶矩的估计。Adam算法不是动量法和RMSProp算法的简单组合,还包括偏置修正,用来修正从原点初始化的一阶矩(均值)和非中心二阶矩(方差)的估计。因为如果将M0和G0都设置为0,那么在迭代初期,Mk和Gk的值会比真实的均值和方差要小,特别是当β1和β2都接近于1时,偏差会很大,因此需要对偏差进行修正,修正公式如式(542)和式(543)所示。更新一阶矩估计和二阶矩估计之后,构造无偏估计,修正之后的Adam算法参数更新公式如式(544)所示。同样地,初始学习率可以设置为0.001,在迭代过程中也可以根据情况进行学习率衰减。Adam算法是一种非常好的优化方法,不同的问题使用Adam算法都能得到比较不错的结果。 Mk=β1Mk-1+1-β1gk(540) Gk=β2Gk-1+1-β2gk⊙gk(541) M^k=Mk1-βk1(542) G^k=Gk1-βk2(543) Δθk=-αG^k+εM^k(544) 5.2.6几种常见优化算法的比较 本章介绍了多种适用于深层神经网络的优化算法,本节对不同的优化算法进行比较,帮助读者在实践中根据需要选择合适的优化算法。优化算法是通过迭代的方法寻找目标函数的最优解,每次迭代目标函数值不断变小,不断逼近最优解,因此优化问题的重点在于如何进行迭代,即迭代公式如何选择。 将目标函数进行一阶泰勒公式的近似,通过数学分析可知参数更新方向为负梯度方向时下降速度最快,因此梯度下降法也被称为最速下降法。确定更新方向后,步长的选择有多种方式,可以人为选定也可以在选择的方向执行线搜索寻找最优步长。对于梯度下降法,每次迭代求梯度需要遍历整个训练集,从而导致巨大的计算量和存储代价,提出了梯度下降法的改进方法批量梯度下降法和随机梯度下降法,分别采用小批量和单独的样本进行梯度估计,从而降低了计算量。针对梯度下降法及其改进方法存在的缺陷,提出更多的改进优化算法。这些算法主要从两个方面对原始随机梯度下降算法进行改进,其中一大类优化算法旨在调整参数更新方向,优化训练速度; 而另一大类算法旨在调整学习率,即对步长进行改进,使得优化更加稳定。 同样也可以使用二阶优化方法,与一阶优化方法相比,二阶优化方法使用二阶导数。最广泛使用的二阶优化方法是牛顿法。牛顿法没有学习率这个超参数,收敛速度也更快,但在深层神经网络中,百万级的参数量使得Hessian矩阵的逆矩阵求解困难,Hessian矩阵的逆矩阵的存储也是一个问题。因此,通过构造近似矩阵代替Hessian逆矩阵的拟牛顿法被提出,本章介绍了其中两种算法: DFP算法和BFGS算法,以及能够降低BFGS存储代价的LBFGS算法。虽然LBFGS算法能够 解决存储空间的问题,它的一个巨大劣势是需要对整个训练集进行计算,而整个训练集一般包含几百万个样本。和小批量梯度下降法不同,在小批量上应用LBFGS算法需要一定的技巧,这也是研究热点。实践中,深层神经网络并不常用例如LBFGS算法这种二阶方法,反而是基于动量更新的梯度下降算法更加常用,因为它们更加简单并且容易扩展。 另外,还有一种特殊的优化方法——共轭梯度法,它介于梯度下降法和牛顿法之间,仅利用一阶导数信息,收敛速度比梯度下降法快,同时不需要存储和计算Hessian矩阵的逆矩阵,也不需要任何外部参数。其特点是,一系列搜索方向是共轭的。 实际应用中,Adam算法在很多情况下都是一个比较好的选择,如果能够进行整个训练集的更新,并且要解决的问题没有太大的随机性,那么LBFGS算法也是一个很好的选择。带动量的随机梯度下降算法、RMSProp算法和Adam算法都是使用度比较高的优化算法,读者可以根据自己对算法的熟悉程度进行选择。 5.3参数初始化 本节介绍常见的几种参数初始化方法,包括随机初始化、Xavier初始化、He初始化等。另外,还会介绍逐层进行批量归一化操作并使用小随机数进行初始化的方法。最后,介绍神经网络的一种有效训练方式——预训练。 5.3.1合理初始化的重要性 由于深层神经网络的复杂性,其优化问题不具有解析解,只能通过迭代优化的方式在有限时间内收敛到一个可以接受的解。迭代优化算法需要有一个初始点,而训练结果的好坏很大程度上受选择的初始点的影响,因此,对于初始点的选择必须谨慎。初始点不仅决定算法是否收敛,也能决定收敛速度的快慢以及收敛点的损失大小。即使收敛点的损失相差不大,对于训练集以外的数据点,泛化误差也可能不同,因此初始点也能影响泛化性能。由于迭代优化是一种局部优化方式,只能利用局部信息而不具有全局概念,因此其性能总是受初始点的影响。如图58所示的二维函数,如果选择初始点为w0并在此处运行梯度下降算法,算法最终会收敛到w1这个局部极小值处, 图58不合适的初始值使得损失函数 陷入局部极小值 而不是真正的最优解w,这种情况下算法永远找不到最优解。好的初始化策略应该是怎样的呢?本节将介绍几种实践中表现较好的初始化策略,例如随机初始化Xavier初始化、He初始化以及批量归一化和小随机数初始化。本节介绍的方法主要是针对权重矩阵W的初始化,对于偏置,一般情况直接将其初始化为0。也有部分研究人员在使用ReLU函数作为激活函数时,将偏置初始化为类似0.01这样的小数值,目的是使所有的ReLU单元在一开始时就能被激活并进行梯度传递,但将偏置初始化为0的情况更为常见。 5.3.2随机初始化 目前,对于参数初始化的明确指导是需要打破不同单元之间的对称性。在神经网络的训练中,一般希望数据和参数的均值都为0。数据经过合适的归一化处理,能够保证参数初始化的均值也为0,正负参数的数量大致相等。一个似乎合理的想法是把所有的参数都初始化为0。对于如图59所示的标准的双层神经网络,每一条实线代表不同单元之间的连接权重,将这些不同的连接权重全都设置为0,然后运行梯度下降算法,会发生什么呢?所有神经元将会执行相同的操作,由于初始权重都为0,给定任意输入,每个隐藏层神经元都会对输入数据做相同的运算,得到相同的激活值,并且输出层单元也会输出相同的结果。这里假设隐藏层内的神经元类型相同,输出层神经元类型相同。同样地,在运行反向传播时,也会得到相同的梯度,然后使用相同的方式进行更新,最终会得到完全相同的神经元,这将导致神经元之间没有可区分性,而实际上我们期望不同的神经元学习不同的知识。 图59双层神经网络示意图 为了打破参数之间的对称性,不能使用全0或者其他相同的数值去初始化所有参数。一种比较好的方式是对每个参数进行随机初始化,使得不同神经元之间的区分性更好。因此,更为合理的一种方式是采用小随机数进行初始化,将参数初始化为随机且不相等的小数值,神经网络中的不同神经元就可以得到不同的更新,可以学到数据中不一样的知识。其实现方式是从一个概率分布中抽样。例如,基于一个零均值的高斯分布生成随机数,使用该分布中随机抽样值对权重进行初始化,也可以使用均匀分布生成随机数。实践证明,采用哪种方法生成随机数对算法的结果影响不大。但是,并不是采用小随机数进行初始化就圆满顺利,并不一定会得到好的结果。将生成随机数的高斯分布的方差设置为0.01,使用tanh激活函数创建一个10层神经网络,并进行初始化,使得每层参数都服从高斯分布。图510给出了每一层数输出值的分布直方图,该图统计了每一层输出值的分布情况。可以看到,第一层输出值的分布近似高斯分布,第二层输出分布类似高斯分布但其方差快速变小,第3层及以后几层,几乎所有的输出值都在零值附近。分析神经网络的前向传播过程可以解释这种现象。对于每一层,其输入x与W进行点积,然后通过非线性激活函数得到激活值,即本层的输出值。因为这里使用的激活函数tanh是以0为中心的,所以可以解释为什么每层输出值是零中心分布的。由于每层权重都是使用小随机数进行初始化的,乘以一个小随机数W后,输出值会随着多次乘法运算后迅速减小,最终经过多层前向传播后,输出值将会变成一组接近于0的数,信号在前向传递的过程中逐渐消失。现在考虑反向传播,使用反向传播计算梯度时,根据链式法则,为了得到关于权重的梯度,需要上游回传的梯度乘以局部梯度。每一层权重都是与本层输入进行点积,再送入激活函数的。因此,关于本层权重的局部梯度也是本层的输入(即上一层的输出),由于这些输入值很小,其关于权重的梯度也非常小,使得这些权重基本得不到更新或者更新缓慢。类似于正向传播中输出值趋向于0,反向传播中从上游回传的梯度也会越来越接近于0。因此,小随机数初始化在结构较深的网络中可能会出现问题。 图510使用小随机数初始化的神经网络输出值逐层分布直方图图片来自: 夏飞.聊一聊深度学习的weight initialization.[Z/OL].https://zhuanlan.zhihu.com/p/25110150https://zhuanlan.zhihu.com/p/25110150. 如果将初始值调大,使得生成随机数的高斯分布方差变为1(均值仍保持为0),再次统计每层输出值的分布,如图511所示。可以看到,几乎所有层的输出值都集中在+1和-1附近。不难解释,这种情况是因为激活函数的输入过大,落在tanh激活函数的非线性区域,导致神经元的饱和。分析前向传播过程,由于每一层都乘以一个比较大的权重W,会导致激活函数的输入越来越大,导致所有的神经元都发生饱和,而神经元饱和则会导致反向传播梯度为0,因为所有参数都得不到更新。由此可以看到,使用大值随机数进行初始化仍然存在很多问题,初始化参数过大或者过小都会产生相应问题。 图511使用大值随机数初始化的神经网络输出值逐层分布直方图① 5.3.3Xavier初始化 一些研究表明,参数初始化的一个较好的方式是Xavier初始化,这是Xavier Gorton等作者在2010年发表的论文中提出的。其核心思想是要求输入的方差等于输出的方差,在满足这一条件的前提下,推导出参数的值并进行初始化。 可以通过数学推导证明其合理性,使用小随机数进行参数初始化时,网络输出数据分布的方差会随着输入神经元个数而改变,关于状态梯度的方差会随着输出神经元的个数而改变。如图512所示,对于神经网络中的任意一层,状态值z是输入与本层权重的点积,状态值是激活函数的输入,激活值h是激活函数的输出,即本层的输出值。根据数据在网络中的前向传播过程,可以得到式(545)和式(546)。其中,上标l指代不同层,nl为第l层神经元个数,nl-1为第l-1层神经元个数,下标i用于区分同一层的不同神经元。 图512网络中第l层某一神经元 zl=∑nl-1i=1Wlihl-1i(545) hl=fzl(546) 式(545)表示,对于第l层的任意一个神经元,接受前一层nl-1个神经元的输出hl-1i,进行加权求和得到状态值zl,其中i∈1,nl-1; 同样地,反向传播可以得到梯度信息,为损失函数关于状态z的梯度yz,另一组为损失函数关于参数W的梯度yW。 对于第l层任一神经元的激活值求方差可得 Varhl=nl-1VarWlVarhl-1=Varx∏lL=1nL-1VarWL(547) 详细推导过程如下: 将式(546)代入替换hl,假设状态值zl位于激活函数的线性区域,此时fzl=zl,可得 Varhl=Varfzl=Varzl =Var∑nl-1i=1Wlihl-1i =∑nl-1i=1VarWlihl-1i =∑nl-1i=1EWli2Varhl-1i+Ehl-1i2VarWli+VarWliVarhl-1i 假设W和h相互独立,使用方差公式进行展开,有 Varhl=∑nl-1i=1VarWliVarhl-1i 对上式进行简化,假设网络参数和数据均值为0,假设同层参数和激活值均服从同一分布,可得 Varhl=nl-1VarWlVarhl-1 =Varx∏lL=1nl-1VarWl 同理可得Varhl-1=nl-2VarWl-1Varhl-2,将其递归代入上式,直至式子不能继续展开。其中,Varx为网络输入的方差,这里假设所有输入服从同一分布,且zl=∑nxi=1Wlixi,nx为输入参数的数量。 输入信号经过本层神经元后,方差多了一个乘积因子nl-1VarWl。在深层神经网络中,经过多层传播就会累乘这个因子。经过l层传播后,输出的方差与输入的倍数是∏lL=1nL-1VarWL,这就是导致小随机数初始化应用于深层神经网络出现问题的原因,参数方差过小,使得输出方差累积相乘一个小数值,导致输出也越来越小,而参数方差过大可能又会导致神经元饱和。为了保证输入信号不被过分地放大和缩小,一个合理的想法是保持每层神经元的输入和输出的方差不变,这也是Glorot条件之一,即令nl-1VarWl为1,那么只需要将参数初始化为方差满足式(548)即可。 VarWl=1nl-1(548) 如果考虑反向传播,损失函数关于第l层任意神经元状态值的方差也可以采用类似方法推导出。 VarLzl=nl+1VarWl+1VarLzl+1(549) 可以看到,神经网络的任一层数据输出的方差与上一层神经元数量有关,而反向传播的状态梯度方差与后一层神经元数量有关。因此,为了保证在反向传播中误差信号不被过分放大和缩小,各层对状态值z的梯度方差也应保持一致,即nl+1VarWl+1应为1,也即nlVarWl=1。因此,参数方差应满足 VarWl=1nl(550) 若要保证信号在前向传播和反向传播中都不被过分放大和缩小,可以设置参数方差为 VarWl=2nl-1+nl(551) Grolot条件只强调参数方差应当满足的条件,只需要生成参数分布的方差满足上式即可。因此,Xavier初始化实际上有两种具体的形式,分别对应于高斯分布的 Xavier初始化和均匀分布的Xavier初始化。高斯分布的 Xavier初始化更简单,直接根据每层输入参数数量对高斯分布的方差进行缩放即可。如果该层输入参数数量较少,那么就要除一个较小的数以得到较大的方差,随机采样得到的参数值就会较大。这是符合直观的想法的,因为输入参数数量少,则必须让参数足够大,才能保证输出的方差与输入相同。反之亦然,如果输入参数数量较大,就会得到较小的参数使输出也得到相同的扩展。考虑反向传播,同时使用输入参数数量和输出值的数量对方差进行调整。对每层参数都计算出相应的高斯分布的方差,并从分布中随机采样对参数进行初始化。实践证明,Xavier初始化在使用tanh函数和sigmoid函数做激活函数的神经网络中表现不错。如图513所示,对于上文中10层神经网络的例子,将小随机数初始化替换为高斯分布的 Xavier初始化,得到的各层输出值分布图。可以看到,Xavier初始化有效地解决了随机初始化存在的问题,输出值在经过很多层之后仍然保持良好的分布,这有利于神经网络的优化。 对于在区间-a,a服从均匀分布的变量,其方差为a23,因此可求得满足Glorot条件的均匀分布,即Wl: U-3nl-1,3nl-1,考虑反向传播则Wl: U-6nl-1+nl,6nl-1+nl。实践中使用哪种形式的Xavier初始化都是可以的。 图513使用Xavier初始化的神经网络输出值逐层分布直方图图片来自: 夏飞.聊一聊深度学习的weight initialization.[Z/OL].https://zhuanlan.zhihu.com/p/25110150https://zhuanlan.zhihu.com/p/25110150. 尽管已经证明Xavier初始化在实践中表现良好,但由于其推导过程是基于线性激活这一假设,即神经元是处于激活状态的,因此对于tanh函数和sigmoid函数这种含有线性激活区域的函数仍然表现良好,只要保证状态值落在激活函数的线性区域即可。但是,对于使用ReLU函数及其系列变体作为激活函数的网络,效果并不好。仍以10层神经网络举例。如图514所示,将tanh激活函数替换为ReLU激活函数,依旧使用Xavier初始化。可以看到,尽管前几层看起来表现不错,但是后面几层的输出越来越接近0。因此,对于ReLU激活函数,可使用另外一种初始化方法——He方法,它可以很好地解决这个问题。 图514使用Xavier初始化的ReLU神经网络输出值逐层分布直方图图片来自: 夏飞.聊一聊深度学习的weight initialization.[Z/OL].https://zhuanlan.zhihu.com/p/25110150https://zhuanlan.zhihu.com/p/25110150. 5.3.4He初始化 He初始化也称为Kaiming初始化和MSRA初始化,由Kaiming He提出。由于Xavier初始化并不适用于使用ReLU做激活函数的网络,Xavier初始化的Glorot条件为,正向传播时,保持输出值的方差不变; 反向传播时,保持状态值梯度的方差保持不变。 对Glorot条件稍作变换,改为正向传播时,保持状态值的方差保持不变; 反向传播时,损失函数关于输出值的梯度的方差保持不变,这就是He初始化需要满足的条件。基于这两个条件进行数学推导,能够得到参数初始化的方法。对正向传播的状态值求方差,使其等于前一层神经元状态值的方差,推导可得 Varzl=12nl-1VarWlVarzl-1(552) 详细证明过程如下: Varzl=Var∑nl-1i=1Wlihl-1i =∑nl-1i=1VarWlihl-1i =∑nl-1i=1E(Wli)2Var(hl-1i)+E(hl-1i)2Var(Wli)+Var(Wli)Var(hl-1i) 假设参数和输出值独立,并且参数的均值E(Wli)=0,因为激活函数为ReLU函数,所以激活值的期望E(hli)≠0。于是,上式可以改写成 Var(zl)=∑nl-1i=1E(hl-1i)2Var(Wli)+Var(Wli)Var(hl-1i) =∑nl-1i=1Var(Wli)E(hl-1i)2+Var(hl-1i) =∑nl-1i=1Var(Wli)E(hl-1i)2 =nl-1Var(Wl)E(hl-1)2 因为 E(hl-1)2=E(f(zl-1))2 =∫∞-∞p(zl-1)(f(zl-1))2dzl-1 =∫0-∞p(zl-1)(f(zl-1))2dzl-1+∫∞0p(zl-1)(f(zl-1))2dzl-1 =0+∫∞0p(zl-1)(zl-1)2dzl-1 =12∫∞-∞p(zl-1)(zl-1)2dzl-1 =12E(zl-1)2 =12Var(zl-1) 将上述结果代入,可得 Var(zl)=12nl-1Var(Wl)Var(zl-1) 因此,为了保证正向传播时,状态值的方差保持不变,必须满足12nl-1VarWl=1,即式(553)。参数的方差需要根据输入参数的数量进行调整。 VarWl=2nl-1(553) 同样,反向传播采用相同的分析方式,可以计算出损失函数关于第l层任一神经元激活值的方差满足 VarLhl=12nl+1VarWl+1VarLhl+1(554) 令12nl+1VarWl+1=1,可得VarWl+1=2nl+1,即方差满足 VarWl=2nl(555) 因此,如果同时考虑正向和反向传播,将方差设置为4nl-1+nl即可。He初始化考虑了非线性激活函数ReLU对输入的影响,ReLU函数会消除一半的神经元,即将这一半神经元的参数设置为0,会使得得到的方差减半,因此使用ReLU函数时,开始时表现良好,层数加深方差会变小,从而导致越来越多的输出值集中在0附近。可以这样理解He初始化: 对于使用ReLU函数的网络,如果与使用其他激活函数例如tanh函数的网络的输入相同,因为有一半神经元的参数被设置为0,相当于只有一半输入,所以需要将Xavier方法中方差的规范化分母n变为n2。这样,能够保证状态值的分布在深度网络的每一层都表现良好。 因此,实际中如果使用ReLU函数作为激活函数,最好使用He初始化方法,将参数初始化为高斯分布或者均匀分布的较小随机数。选择高斯分布对初始化参数进行采样时,每层神经元应满足高斯分布N0,2nl-1,考虑反向传播时,应满足高斯分布N0,4nl-1+nl; 如果使用均匀分布进行采样,应为U-6nl-1,6nl-1。 5.3.5批量归一化 批量归一化(Batch Normalization,BN)是Sergey Ioffe等人于2015年提出的一种用于训练深层神经网络的方法。BN并不是一种参数初始化方法,而是一种训练深层神经网络的技巧,一种对每层神经元进行数据处理的方法。使用BN可以减少网络对参数初始尺度的依赖,降低合理初始化参数的难度,使用BN的网络仅使用小随机数进行初始化就能得到不错的效果。图515为仅使用小随机数初始化的ReLU神经网络输出值逐层分布直方图; 图516为使用BN和小随机数初始化的ReLU神经网络输出层逐层分布直方图。参数采样均来自高斯分布N(0,0.01)。可以看到,使用BN的效果非常好,每层输出分布近似,深层网络也没有出现信号消失等问题。 图515仅使用小随机数初始化的ReLU神经网络输出值逐层分布直方图图片来自: 夏飞.聊一聊深度学习的weight initialization.[Z/OL].https://zhuanlan.zhihu.com/p/25110150https://zhuanlan.zhihu.com/p/25110150. 图516使用BN和小随机数初始化的ReLU神经网络输出值逐层分布直方图① 实践证明,使用BN能带来很多训练优势,例如极大的训练速度,以及解决了深层神经网络中梯度消失的问题,还可以提升模型训练精度,对参数初始化要求低,使得训练深层网络模型更加容易和稳定。因此,BN已经成为训练深层神经网络的一种标准处理方法。 BN的核心思想是,将每一层神经元输入数据进行归一化处理,使其为高斯分布,从而保证每一层神经网络的输入参数具有相同分布。此处所说“每一层神经元的输入”为该层神经元激活函数之前的输入,即该层的状态值,是由上一层神经元的输出和本层权重计算得到的。对于深层神经网络,由于中间任意一层神经元的输入都由上一层神经元的输出得到,因此使用反向传播进行参数更新时,前层参数的变化会导致后层输入的分布发生较大的变化,引起后面每一层神经元参数的分布发生改变,由于累积效应,网络层次越深,这种变化越严重。这种在训练过程中网络中间层输入分布发生改变的现象叫作内部协变量偏移(Internal Covariate Shift)。这种现象使得深层输入分布发生改变,通常是整体分布逐渐向非线性激活函数的线性区间的上下限靠近,导致反向传播时底层神经网络产生梯度消失问题,使得模型收敛过慢。为了提升训练速度,需要减小内部协变量的偏移,因此考虑对神经网络的每一层都进行归一化处理,而不仅仅对模型的输入进行归一化处理。这样使得中间层的输入分布保持稳定,即保持同一分布。通过BN处理,使得输入值落入非线性激活函数对输入参数比较敏感的区域,在期望的高斯分布区域内保持激活状态,这样可以使梯度保持在较大的水平,加快学习和收敛的速度。 那么BN的具体实现方式是怎样的呢?BN相当于在每一层都进行一次数据预处理,因此可以看作在网络每一层输入前插入一个BN层,对输入参数分布进行调整后再输入网络的下一层。此处的“输入”依旧指激活函数之前的数据,因此BN层实际上是放在每层激活函数之前。另外,BN是基于小批量梯度下降实现参数更新的。 下面详细介绍其实现过程。对于一个深层神经网络,令其第l层的净输入为zl,输出为hl。对于激活函数f(·),可得该层输出为hl=fzl=fWhl-1+b,其中W、b分别为参数和偏置。为了提升归一化效率,使用标准归一化,将输入zl的每一维按照式(556)归一化为标准正态分布。 z^l=zl-EzlVarzl+ε(556) 其中,Ezl和Varzl是当前参数下,zl的每一维在一个批量样本集合上的均值和方差。假设该批量含有K个样本,这K个样本在第l层的输入分别是z(1,l),…,z(k,l),那么均值和方差公式如式(557)和式(558)所示。 Ezl=1K∑Kk=1z(k,l)(557) Varzl=1K∑Kk=1z(k,l)-Ezl⊙z(k,l)-Ezl(558) 尽管通过归一化处理,可以使偏移的输入分布符合均值为0、方差为1的标准正态分布,远离导数为0的饱和区,但是对于在区间(-1,1)梯度变化不大的激活函数,效果反而更差。例如,sigmoid函数在区间(-1,1)近似线性激活,逐层归一化处理后使其丧失了非线性变换的能力; 对于ReLU函数,效果更差,因为有一半神经元被置0。对于这些激活函数,逐层归一化操作实际削弱了网络的性能,为了使归一化操作不对网络的表示能力造成负面影响,可以通过添加额外的缩放和平移操作,改变输入的分布区间,如式(559)。 z^l=zl-EzlVarzl+ε⊙γ+β=BNγ,βzl(559) 其中,γ和β分别为缩放和平移因子,可以作为可学习的参数由反向传播确定,缩放和平移因子通过控制激活函数的输入参数的取值范围,使得网络通过学习拥有控制不同饱和度的能力。引入缩放和平移因子的逐层归一化处理最终构成完整的批量归一化的定义。缩放和平移是关键步骤,提供了更多的灵活性。另外,也可以通过设置γ=α和β=Ezl恢复恒等映射,从而将参数还原为未做批量归一化时的输入,即z^l=zl。 因此,使用批量归一化的神经网络的每一层输出为hl=fBNγ,βzl=fBNγ,βWhl-1。这里引入平移变换,相当于为神经层增加偏置,因此标准归一化之前的输入值Whl-1不用增加偏置。完整的BN算法流程如表56所示。 表56BN算法流程 1. Input:包含K个样本的小批量,其任意中间层第l层的净输入为zl 2. Output:z^l=BNγ,βzl 3. Calculate: 4. 小批量均值: Ezl=1K∑Kk=1z(k,l) 5. 小批量方差: Varzl=1K∑Kk=1z(k,l)-Ezl⊙z(k,l)-Ezl 6. 标准归一化: z^l=zl-EzlVarzl+ε 7. 缩放和平移: z^l=zl-EzlVarzl+ε⊙γ+β=BNγ,βzl 8. End 需要注意的是,在前向传播中使用批量样本计算的均值Ezl和方差Varzl是输入zl的函数,不是固定常量。因此,在反向传播计算参数梯度时,需要考虑Ezl和Varzl对梯度的影响。在训练完成后,用整个数据集上的均值E和方差Var代替每一次小批量样本的均值和方差,然后在测试阶段使用这两个全局统计量来进行BN操作。数据集上的均值E和方差Var可以通过以下方式获得: 每次迭代只使用小批量的样本,在每次迭代时,都将数据集在每层输入的均值和方差存储起来,当遍历整个数据集后,再根据迭代次数将得到的所有均值和方差计算数学期望,这样就可以得到整个数据集的均值和方差。 关于BN层的使用位置,通常是在全连接层和卷积层使用批量归一化处理,并且要在激活函数之前使用。使用批量归一化有很多好处,例如可以改进整个网络的梯度流,避免饱和型激活函数导致的“梯度消失”问题,使网络具有更高的健壮性; 能够在更广范围的学习率和不同的初始值下进行工作,使得参数初始化问题不再棘手,使用批量归一化会使训练变得容易; 实践证明,使用批量归一化可以提升训练速度,加快模型收敛。另一点需要指出的是,BN也可以看作一种正则化的方法,因为每层神经元的输出都源于输入以及同一批量样本中被采样的其他样本,给定的训练样本不再对网络提供确定性的输入值,输入值由随机采样确定的批量决定,因此就像在输入中添加一些噪声从而实现正则化的效果。 5.3.6预训练 预训练是早期训练深层神经网络的一种有效方式,是由Hinton基于深度信念网络提出的一种针对训练深层网络的可行方法。首先,使用自动编码器进行逐层贪婪无监督预训练,然后进行微调。主要分为以下两个阶段。 (1) 预训练阶段: 先将深层网络的输入层和第一个隐藏层取出,为网络添加与输入层同等数量的输出层构造自动编码器,优化自动编码器,使得输入和输出保持一致,这样得到的中间层表示可以看作对输入的特征表示。因此,优化自动编码器的过程实质上就是在寻找输入的其他特征表示。首先,将输出层去掉,仅保留输入层和第一个隐藏层作为深层神经网络的前两层,由此得到输入层到第一个隐藏层的初始化参数; 然后,将第一个隐藏层和第二个隐藏层取出构造自动编码器; 将第一个隐藏层作为自动编码器的输入,添加额外的输出层使之与第一个隐藏层保持一致。优化完成可以得到第一个隐藏层和第二个隐藏层之间的连接权重,再将其应用于深层网络。这样不断对深层神经网络训练的每一层进行相同的操作,最终可以得到所有层间的连接权重,将这些权重作为网络的初始化参数。 (2) 微调阶段: 将神经网络视为一个整体,使用预训练阶段得到的参数初始值和原始训练数据对模型进行调整。在这一过程中,参数被进一步更新,形成最终的模型。 目前,随着数据量的增加和计算能力的提升,深层神经网络已经很少采用自动编码器进行预训练这种方式了,而是直接使用训练数据对网络整体进行训练。但是,在计算资源或者时间有限的情况下,如果不想重新训练一个新的神经网络模型,一种简便并且十分有效的方法是,选择一个已经在其他任务上训练完成的且表现良好的模型(称为Pretrained Model),将其参数作为新任务的初始化参数并根据新任务进行调整。例如,有一个任务是分辨图片场景,这是一个图像识别问题,对于该问题,可以从头开始基于搜集的数据集构建一个性能优良的图像识别算法,这可能需要花费数年的时间。如果使用Google公司在ImageNet训练集上得到的VGG模型作为预训练模型,基于该模型进行参数初始化,在场景分辨任务上对模型进行调整训练并且进行微调,具体怎样进行微调需要根据不同的任务确定。这种方法可以大大减少训练时间,提升在新任务上的训练速度。 5.4网络正则化 本节介绍网络正则化。首先,阐述进行正则化的原因; 然后,介绍几种常用的正则化策略,包括L1正则化、L2正则化、权重衰减、提前停止、数据增强以及丢弃法和标签平滑。 5.4.1正则化的目的 优化和正则化是机器学习中的两个重要方面,优化旨在训练集上尽可能地降低损失值,即减小训练误差,获取全局最优解。5.1节和5.2节所描述的优化算法,都是在最小化目标函数的过程中不断减小训练误差。但是,训练的目的不仅是希望模型在训练数据上表现得很好,更重要的是能够在未知的新数据上具有良好的预测能力,即模型要具备良好的泛化能力。当使用训练集训练某个模型时,将训练集上的训练误差(Training Error)作为目标函数,则对模型的训练转换为一个优化问题。使用训练集训练完成的模型,要使用在先前未观测到的新数据上并对其进行预测。因此,泛化误差作为衡量模型在新数据上的表现度量,被定义为模型在新数据上的误差期望,即 Rexpf=EpLy,fx;θ=∫x×yLy,fx;θpx,ydxdy(560) 泛化误差一般通过模型在测试集数据上的测试误差进行评估,即测试误差1mtest‖xtestW-ytest‖22。由于训练数据和测试数据都是从同一分布采样得到的,因此模型的训练误差期望和测试误差期望是相同的。一个模型表现良好必须具备以下两点: ①训练误差要低; ②训练误差和测试误差之间的差距小。对应于两个极端的情况: 欠拟合和过拟合。如果训练误差不够低,会产生欠拟合现象; 反之,如果训练误差和测试误差之间的差距过大,会产生过拟合现象。图517给出了欠拟合、过拟合以及刚好拟合的情形。 图517欠拟合、过拟合与刚好拟合 一系列优化算法的提出使得深层神经网络的优化问题不再困难,但由于神经网络的表示能力非常强,常常会出现学习到的模型完美地拟合训练数据的情况,从而导致过拟合现象。正则化(Regularization)作为一种避免过拟合、提高模型的泛化能力的策略,已被广泛应用于不同的机器学习算法中。本节主要针对深度学习中经常使用的几种正则化策略进行介绍。本章介绍的正则化策略旨在提升单一模型的泛化性能,通过在现有模型中添加某些部分,防止在训练集上过拟合,从而使模型在测试集上的效果得到提升。对于通过集成多个模型以实现正则化的方法,将在5.5.3节介绍。 5.4.2L1和L2正则化 1. 参数范数惩罚 L1和L2正则化都属于参数范数惩罚的方法,被广泛用于机器学习中。参数范式惩罚通过向目标函数(训练集上的损失函数)添加惩罚项,限制模型的复杂度。添加惩罚项后的目标函数变为 LReg=1N∑Ni=1Liyi,fxi;θ+ηΩθ=L+ηΩθ(561) 超参数η用来衡量惩罚项Ωθ和数据损失项L之间的相对重要性; L( )表示数据损失; N为训练样本的数量; f( )表示待学习的神经网络; 惩罚项表示不同的参数范数。L1正则化和L2正则化对应于L1范数和L2范数,分别表示参数矩阵元素的绝对值之和与平方和,不同参数范数偏好不同的解。需要注意,数据损失函数L既与权重W相关,也与偏置相关,因此使用符号θ表示变量; 但惩罚项Ωθ一般只对权重矩阵进行惩罚,不会对偏置参数进行正则化。因为偏置参数在前向传播中不与输入数据产生互动,因而不需要控制其在数据维度上的效果。为保持统一,数据损失项和惩罚项都使用符号θ表示变量。下面详细介绍L1正则化和L2正则化这两种范数惩罚方法对模型带来的影响。 2. L2正则化 L2正则化向目标函数添加惩罚项Ωθ=12‖W‖22,乘数因子12可以使得惩罚项在求梯度时约掉系数2,是为了计算方便。L2正则化使得权重趋近于0(注意不是为0),可以通过数学分析得到。令W为未进行正则化的目标函数L最小化时的最优解,W~为添加L2正则化后的目标函数LReg的最优解,将L在最优值W处进行二阶泰勒公式近似展开,并求导得WL=HW-W,H为L在W处的Hessian矩阵。对正则化后的目标函数LReg求导可得WLReg=HW-W+ηW,当W=W~时,该导数为0,将W~代入可得HW~-W+ηW~=0,整理可得W~=H+ηI-1HW。将对称矩阵H进行分解H=QΛQT,其中Λ为对角矩阵,Q为单位正交的特征向量组。将对角化的H代入可得 W~=QΛ+ηI-1ΛQTW(562) 可以看到,使用L2正则化的效果是沿着H特征向量定义的轴来缩放W。具体而言,是使用因子λiλi+η对H中第i个特征向量对齐的W的分量进行缩放。对于H特征值较大的方向(λi≠η)正则化的影响较小; 而对于特征值较小的方向(λi=η),会使得参数分量收缩至0附近。而H的特征值大小决定不同参数分量变化对目标函数的影响程度,对于参数变化不会引起目标函数明显变化的方向(对应的特征值λi较小),这些相对不重要的方向上的分量在训练过程中因为使用正则化而被衰减; 对于那些参数变化会引起目标函数强烈变化的方向(λi较大), 图518L2正则化对最优点的影响 正则化对这些方向上的参数分量影响有限。图518展示了L2正则化的影响,实线表示未使用正则化目标函数的等值线,越往内表示目标函数值越小,中心是未正则化时的最小值点 W; 虚线为L2正则化惩罚项的等值线,二者相切点为使用正则化后目标函数的最小值点W~。可以看到,对目标函数影响较小的方向W1,正则化给出了强烈的惩罚,使得W1方向收缩至0附近,而对目标函数影响较大的方向W2影响相对较小。 3. L1正则化 L1正则化向目标函数引入惩罚项Ωθ=‖W‖1=∑iWi,与L2正则化的效果不同,L1正则化使得权重矩阵具有稀疏性。将L在未正则化时的最优值W处进行一阶泰勒公式展开得到近似的导数WL=HW-W,使用L1正则化的目标函数求导后表达式为WLReg=HW-W+ηsignW,其中符号函数signx输出±1(当x大于0时输出1,反之输出-1)。对于该种形式的梯度表达式,令其为0,无法像L2正则化一样直接写出解析解。进一步假设Hessian矩阵是对角矩阵,即H=diagH11,…,Hnn,且每个元素都大于0,可以通过对输入数据使用PCA进行预处理使该条件得到满足。直接对带有L1正则化的目标函数LReg进行二阶泰勒公式近似,并按元素进行展开可得 LReg=L|W=W+∑i12HiiWi-Wi2+ηWi(563) 其中,L|W=W为未正则化的目标函数在W处的取值。现在对于任一维Wi都可以求出使目标函数(带L1正则化)最小化的解析解。 W~i=signWimaxWi-ηHii,0(564) 如果Wi≤ηHii,正则化后该分量W~i被推向0; 反之,Wi>ηHii时,正则化将W~i向0的方向推进ηHii的距离。因此,L1正则化使得最优解W~具有稀疏性,使得某些分量为0。图519展示了L1正则化的影响,虚线为L1正则化惩罚项的等值线。 图519L1正则化对最优点的影响 可以看到,使用L1正则化的目标函数的最小点W~,在水平维度上的分量为0。L1正则化带来的稀疏性可用于特征选择(Feature Selection),即从所有特征中选择有意义的特征,简化机器学习问题。实践中,除非进行模型压缩,通常更倾向于使用L2正则化,也可以同时使用L1正则化和L2正则化,这种方法也叫作弹性网络正则化(Elastic Net Regularization)。 4. 最大范式约束 对于带惩罚项的优化问题,实际上可以转化为带约束条件的优化问题: θ=argminθ1N∑Ni=1Liyi,fxi;θ,约束条件为Ωθ≤k。Ωθ代表不同类型的范数,因此该方法也被称为最大范式约束(Max Norm Constrains),可以通过构造广义Lagrange函数求解。该方法通过对每个神经元的权重向量的范数设定上限,使用投影梯度下降来确保约束条件的满足,有研究证明使用约束条件比直接使用惩罚项的效果会更好。该方法的一个优点是,使用较大的学习率也不会导致网络出现数值“爆炸”的情况,因为参数更新始终是被约束着的,因此可以快速探索参数空间并保持一定的稳定性。 5.4.3权重衰减 对于使用L2正则化的模型,其目标函数为LReg=L+η2‖W‖22,其中L为未使用正则化的损失函数,对其求梯度得到表达式WLReg=WL+ηW。使用梯度下降法执行参数更新,在一次迭代中可得W←W-αηW+WL,整理可得W←1-αηW-αWL。可以看到,使用L2正则化会导致更新规则的改变,与普通梯度下降法的参数更新规则W←W-αWL不同,使用L2正则化后,每次使用梯度信息执行参数更新之前,要先对历史参数向量进行收缩,即乘以一个常数因子1-αη,然后再向负梯度方向前进较小的一步。正是由于L2正则化的这种特性,部分文献也称L2正则化为权重衰减(Weight Decay)。实际上,权重衰减有更广义的定义,只要满足下式即可。 W←1-εW-αWL(565) 其中,WL为损失函数关于W的梯度; α与普通梯度下降法的含义相同,为学习率; ε为权重衰减系数,通常取值较小。通过引入衰减系数ε,在每次参数更新时先对参数进行衰减,这样的方法就叫作权重衰减。当使用标准梯度下降法时,L2正则化与权重衰减的效果相同,衰减系数为ε=αη。因此,在一些深度学习框架中,权重衰减通常通过L2正则化来实现,但是在其他复杂的优化方法例如Adam方法中,二者并不等价。 5.4.4提前停止 “提前停止”是一种简单有效的正则化方法,并且在训练发生错误时,可以作为一种有效防止资源浪费的机制。当使用深层神经网络这类具有强大表示能力的网络时,常常会发生过拟合现象,而通过监测训练过程的学习曲线,能够容易地判断模型发生过拟合的时间点并及时停止训练,简单却有效地遏制过拟合情况的发生,同时避免资源的浪费。学习曲线指训练集误差和验证集误差随迭代次数的变化曲线,体现了所训练模型的表示能力随训练次数增加的变化情况。实践中监测学习曲线时,通常会看到这样一种情形: 训练误差随着时间(或迭代次数)不断降低,而验证误差会在前期下降,到某一个节点后又开始上升,总体呈现U形曲线,如图520所示。通过分析学习曲线可知,在训练的前半段,训练误差和测试误差都比较高,因此模型处于欠拟合状态; 而到后期,训练误差趋于稳定接近于0,但测试误差比较高,因此训练误差与测试误差之间的差距比较大,发生过拟合现象。因此,可以判断最优的时刻应该是某一中间时刻,训练误差此时已经稳定,而测试误差最小,理所当然的想法就是在此刻停止训练,可以获得最优复杂度的模型。 图520L2训练误差、测试误差与欠拟合、过拟合之间的关系 “提前停止”策略的具体操作过程: 分离训练集和验证集,对网络进行随机初始化并开始训练,每隔一定时间对当前训练好的模型在验证集上进行评估,并保留到目前为止使验证集误差最小的模型参数。如果验证集误差在指定的循环次数内没有进一步降低就停止训练,并输出验证集误差最小时的模型参数配置。使用“提前停止”可以获得使验证集误差最小时刻的模型,更有希望获得更低的测试误差,具有更好的泛化能力。“提前停止”作为一种隐式的正则化方法,对整个动态训练过程没有任何影响,既没有改变目标函数也没有改变网络结构,只需要定期对模型进行评估,并且保存最佳的模型参数配置。这些过程可以并行化,对训练过程产生的影响甚微。另外,“提前停止”可以与其他正则化策略结合使用,更大限度地提升模型的泛化能力。 与其他正则化方法相比,“提前停止”存在的一个缺点是,需要分离部分数据作为验证集。这会减少可以用于训练的数据,理想的情况是使用尽可能多的数据用于模型的训练。为了能够充分利用这部分分离出去的数据,可以采用二次训练,即在第一轮训练中使用“提前停止”后,再将所有数据用于二次训练过程。第二轮训练有两种策略可以使用: 一种方法是再次初始化网络,然后使用全部数据集进行训练,并在确定的训练次数后停止,这里确定的训练次数是指第一轮训练中使验证集误差最小时的训练次数; 另外一种方法是,使用第一轮训练得到的模型并在此基础上使用全部数据继续进行训练。 “提前停止”具有正则化效果,可以这样解释: 将学习率α和迭代次数τ的乘积看作权重衰减系数ε的倒数,即ατ≈1ε,使用固定的学习率迭代优化τ次,相当于将参数空间限制在初始参数的小邻域中。可以证明,使用二次误差函数的简单线性模型,当使用普通梯度下降算法时,提前终止相当于L2正则化。如图521所示,实线表示二次误差函数的等值线,左侧虚线表示普通梯度下降算法执行参数更新的路线,W~为使用“提前停止”确定的参数取值。可以看到,“提前停止”方法中,在轨迹较早的点处就停止了训练过程; 右侧虚线为L2惩罚项的等值线,是不同直径的同心圆,虚线与实现相切的点为通过L2正则化确定的最优值W~。对比左右图可以看出,二者的效果是一样的。实践中,“提前停止”比权重衰减更有优势,因其不需要对多个超参数值(衰减系数ε)进行实验,能一步到位地确定合适的正则化程度。 图521“提前停止”与L2正则化的效果对比 5.4.5数据增强 众所周知,深度学习依靠大数据驱动才得以迅速发展。深度学习模型的复杂度以及规模,决定了必须有充分多的数据才能训练出泛化性能良好的模型,使用更多高质量的数据进行训练总能得到更好的效果,因此增加训练数据量是提升模型泛化能力最直接的方法。但是,某些情况下数据量有限,可以使用数据增强(Data Augmentation)技术生成新的数据添加至训练集中以扩大数据量。即使数据集规模足够大,也可能不能覆盖全部场景,例如图像数据可能不能完全涵盖不同的视角、不同的光线照射等情况,使得训练出的模型对训练集中未出现过的场景泛化性不强。另外,某些数据的采集及处理可能困难度极高,需要高昂的成本,使用数据增强技术自动生成训练数据,可以降低获取数据的压力。综上所述,使用数据增强技术可以扩大数据集规模,使神经网络学习到不相关的模式,提高模型健壮性,防止过拟合。 数据增强技术最常应用于图像识别问题中: 每个训练样本都是一个数据点对x,y,其中x是图片,y是标签,即图片所属的类。只要对原始图片进行一系列操作和转化而不改变标签,就可以生成新的数据点对x′,y。应用于图像的不改变标签的转换操作有很多。 (1) 平移(shift): 将图像沿水平或者垂直方向移动若干个像素。 (2) 旋转(rotation): 将图像顺时针或者逆时针旋转一定角度。 (3) 缩放(zoom In/Out): 保持图像的比例进行整体的放大或者缩小。 (4) 翻转(flip): 将图像沿水平或垂直方向进行翻转。 (5) 裁剪(clip): 将图像随机裁剪成任意大小。 除了以上方法外,还有各种仿射类变换、视觉变换等。以上方法属于空间几何变换方法,也可以对像素颜色进行变换,例如添加噪声以及模糊操作。应用这些转换操作时必须注意,不能改变图像的类别。例如,在光学字符识别(Optical Character Recognition,OCR)任务中,需要从输入的图像中识别出对应的光学字符,这种情形下,水平翻转和旋转180°这两种转换操作就不适用,因为水平翻转会将字符“b”变为“d”,旋转180°会将字符“6”变为“9”。因此,对不同的任务选择合适的转换操作。 不仅图像数据可以应用数据增强技术,文本数据相应的也有一系列数据增强方法,例如随机删除、打乱词序、同义词替换、回译、文档裁剪等。数据增强技术也可以应用于语音识别任务,例如可以通过向输入层注入噪声来实现数据增强。更高级的数据增强策略可用于生成对抗网络,例如可以用来生成新的图像,一些方法可能也适用于文本数据。 在不同的任务中,向神经网络的输入层注入噪声或者引入随机性被看作是数据增强的一种方式。通过对输入层添加随机噪声再进行训练,能够降低模型对噪声的敏感性,提升模型健壮性。实际上,不仅是输入层,向中间隐藏层或者输出层添加噪声都是可行的,对应于后面将要介绍的Dropout方法和标签平滑方法,以及卷积网络中的随机池化(Stochastic Pooling)。这几种方法都符合一个范式,即在训练阶段引入噪声或者随机性,然后在测试阶段消除这种不确定性。例如,使用数据增强技术以某种方式变换图像并保持标签不变,假设这种变换为随机裁剪不同大小的图像,然后代替原始图像进行训练,测试中则会通过评估某些固定的裁剪图像或者对不同的裁剪图像取平均来抵消这种随机性。训练时,只需将随机转换应用于输入数据,这种方式对网络有正则化效果。 5.4.6丢弃法 丢弃法(Dropout)是一种在训练神经网络时,以概率1-p丢弃部分神经元的方法。Dropout作为一种简单却极其有效的正则化方法,由Srivastava提出,该方法可以与L1正则化、L2正则化以及最大范式约束等其他正则化方法结合使用。 Dropout的具体操作流程: 在每次迭代进行前向传播时,对于所有的输入和隐藏单元都随机采样得到一个对应的二值掩码,该二值掩码m∈0,1d是从参数为p的伯努利分布中采样得到的,不同单元的掩码是独立采样的。掩码为1的单元被保留下来,掩码为0的单元被丢弃。Dropout是逐层进行的。首先,将输入x与输入单元的掩码相乘,使得部分输入单元被置0。然后,继续向前传播,每经过一层先计算出该层的输出值与对应的单元掩码相乘,因此每层都有部分隐藏单元被随机置0。当前向传播完成后,由于部分神经元被丢弃,网络规模会缩小,变成原始网络的一个子网络,如图522所示,然后在子网络中进行反向传播并更新参数矩阵。注意,每次迭代前向传播神经元都要以概率p对掩码进行采样,因此每次迭代被丢弃的神经元都不是相同的,因而实际上每次迭代都是在训练从原始网络抽样得到的一个子网络,并且只更新子网络对应部分的参数集,剩余部分的参数仍保持。因此,这些子网络之间是共享参数的。对于上文中的保留概率p(丢弃概率为1-p),通常对输入单元和隐藏单元是不同的,输入单元一般设置为0.8,尽可能保留较多的输入,使得输入变化不会太大; 而隐藏单元的保留概率一般设置为0.5,这样生成的网络有最大的随机性。不考虑输入单元,对于含有n个隐藏单元的神经网络,通过Dropout生成的子网络总共有2n个,如果原始网络很庞大,那么通过采样获得的子网络数量具有指数级别。 图522神经网络使用Dropout前后对比 Dropout可以看作在单一模型中进行集成学习,Dropout中所有子网络都不独立,而是通过继承父网络参数的不同子集来共享参数。另外,由于子网络数量巨大,每个抽样得到的子网络都没有经过完全的训练,每次迭代中仅训练一个子网络,参数共享使得其余子网络也有良好的参数设定,因此最终训练得到的网络可以视为集成了数量为指数级别的不同子网络的集成模型。 模型训练完成后,为消除训练时引入的随机性,在测试阶段并不使用Dropout。因为测试阶段对样本的预测需要有一个确定的结果,如果保留这种随机性,那么可能使用同一测试样本进行两次测试,而模型可能会给出不一样的结果。由于在训练过程中使用了Dropout而测试阶段未使用,对于任一神经元,会导致输出的期望值在训练阶段和测试阶段不一致。例如,对于某一神经元的激活值x,使用Dropout与二值掩码相乘后,该神经元的期望输出为px+1-p0,以1-p的概率输出为0,以p的概率直接输出。测试阶段神经元总是激活的,因此期望输出总为x。为了保证训练阶段与测试阶段输出的期望值一致,需要在测试阶段将该单元神经元的权重乘以单元的保留概率p,从而使得期望输出由x变为px,指导这种修改的准则被称为权重比例推断规则(Weight Scaling Inference Rule)。经验证明,这种近似推断规则在神经网络上表现良好。实践中,为提升测试阶段的效率,避免在测试阶段根据概率p对神经元的激活值进行数值调整,常用的一种技巧是在测试时不做任何处理,而在训练阶段除以保留概率p以进行数值调整,这种方法叫作反向随机丢弃(Inverted Dropout)。比起普通的Dropout,该方法的一个好处在于,无论是否使用随机丢弃,预测阶段的代码都可以保持不变。 Srivastava等人在论文中表示,Dropout是一种非常有效的正则化方法。其显著优点是计算方便,只需在每次迭代时随机抽样生成n个二值掩码与神经元相乘; 另外一个优点是,Dropout几乎在所有使用分布式表示并且采用梯度下降算法训练的模型上都表现良好。除此之外,Dropout还可以进行扩展,不仅可以以任意概率对神经元进行丢弃,还可以对神经元之间的连接或者神经网络中的某些层进行随机丢弃,分别对应于Dropconnect方法和随机深度方法。Dropconnect方法在前向传播时随机将权重矩阵中的某些值设置为零,随机深度方法在训练时随机丢弃神经网络的部分层,而在测试时使用完整的网络。 Dropout这种正则化策略,在训练阶段为网络引入随机性或者噪声以防止过拟合,而在测试阶段消除这种随机性来提高泛化能力的方法,实际上批量归一化也符合这种策略。当使用BN训练模型时,相同的数据点可能出现在不同的小批量中,对于单个数据点,在训练过程中该点会如何被正则化具有一定的随机性(不同小批量计算得到的均值和方差不同,使用BN调整后的数据也会不同),但是在测试过程中,通过使用基于全局统计的正则化方法(使用整个数据集上的均值和方差对数据进行调整)来抵消这个随机性,而不是采用小批量进行估计。实际上,当使用BN训练神经网络时,一般不会再使用Dropout,仅使用BN就能给网络带来足够的正则化效果。然而,Dropout在某种程度上更好一些,因为其可以通过改变参数p来调整正则化的强度,BN并没有这种控制机制。 5.4.7标签平滑 作为训练时引入随机性这种正则化范式的另一具体实例,标签平滑(Label Smoothing)技术对网络输出即样本标签引入了一定的噪声。数据集内的样本可能会产生误标记,即对应样本的标签是错误的,如果使用这些误标记的样本数据进行训练,会导致网络过拟合,影响预测的效果。 可以通过显式地对标签的噪声进行建模来改善这种情况。标签平滑技术采用以下思路解决这个问题: 不再使用硬编码标签,在训练时假设标签可能错误,并将这种错误编码在标签中,使用软编码标签。其中,硬编码标签使用onehot向量表示样本的标签,即y=0,…,0,1,0,…,0T,如果有k种类别,相应的标签是一个k维向量,并且正确类别对应的元素为1,其余元素为0。使用硬编码标签时,如果使用softmax分类器及对应的交叉熵损失函数,会使得模型永远追求正确类别的概率趋近于1,而错误类别的概率趋近于0,这使得未经过softmax函数进行概率归一化的类别分值越来越大,与其他类别的分值相比过大,因此对应正确类别的权重会越来越大,与其他类的权重差异巨大,从而导致过拟合现象。不仅如此,如果标签是错误标记的会导致更严重的过拟合现象。对于交叉熵损失函数,模型输出永远不可能达到1(正确类别)或者0(错误类别),因此模型为了更近一步逼近这两个值会一直进行优化,从而使得权重不断增大。 标签平滑技术则通过引入噪声对标签进行平滑,将确切的类别概率0和1替换为相对容易实现的值ε和1-ε,模型输出在达到这个目标后,便不再继续进行优化,从而实现正则化。可以看作样本以概率ε被划分其他类,如果有K种类别,那么划为任意一种错误类别的概率为εK-1,正确标记的概率为1-ε,因此软编码标签的形式为y=εK-1,…,εK-1,1-ε,εK-1,…,εK-1T。通过使用软编码标签,标签平滑技术能够避免模型输出过度拟合硬编码标签,能够防止模型追求确切概率同时不影响模型学习正确分类的能力。 上文令所有错误类别的概率都是相同的,即εK-1,更好的做法是考虑类别之间的相关性以赋予错误类别不同的概率。 对于本节涉及的正则化方法,L1正则化、L2正则化在传统机器学习中使用较多,但是在深层神经网络中其作用有限。目前,深度学习中较多使用的正则化方法主要有简单有效的“提前停止”策略、Dropout和BN等。对于正则化方法的使用,应有的放矢,即先不使用正则化策略进行模型训练,观察学习曲线,当发生过拟合现象时,再考虑引入各种正则化方法。另外,多种正则化策略也可以结合使用,以获得更进一步的提升。 5.5训练深层神经网络的小技巧 本节介绍训练深层神经网络的小技巧,包括数据预处理、超参数调优、集成学习和监视训练过程。 5.5.1数据预处理 深度学习中常常需要对数据进行预处理,因为原始训练数据中,每一维特征的来源以及度量单位都有可能不同,从而造成特征之间取值范围不同。例如,在判断零件是否合格的任务中,选取的三个特征分别为零件长度、直径和表面光滑度。对“长细形”零件,长度的取值范围就会大于直径的取值范围,对“短粗形”零件则反之。对于这种不同特征取值范围差异较大的原始数据,使用基于相似性度量的机器学习算法(例如最近邻分类器)时,因为要计算例如样本之间的欧氏距离来衡量不同样本之间的相似性,取值范围较大的特征会占主导作用,所以使用之前必须要对原始训练样本进行预处理,将不同维度的特征取值范围限制在同一个区间。另外,即使神经网络可以自动调整参数来适应不同特征的取值范围,也会导致训练效率低下,使用数据预处理可以减少人工干预并且提升收敛速度。因此,数据预处理已经成为必要的一步,在很多深度学习算法中起着重要作用。数据预处理一般位于数据增强操作之后,模型训练之前,训练流程一般为数据采集、数据标记(可选)、数据增强(可选)、数据预处理和模型训练,可将训练流程分为数据和模型两部分。模型训练包括训练过程的所有方面,例如模型架构设计、参数初始化策略、优化方法、正则化策略、各种超参数的设置以及实践中使用的小技巧等,其结果是产生一个性能良好的模型; 模型训练之前的步骤都是对于数据的处理,其结果是产生能用于训练模型的数据集合。 通常使用的数据预处理包括以下两种方法: 数据归一化; 白化。下面将对这两种处理方法进行详细介绍。 数据归一化(Data Normalization)也称数据标准化,一般作为数据预处理的第一步,将数据按比例缩放,使之落入一个小的特定区间内。有很多方法可以实现数据归一化,在深度学习中比较常用的主要有缩放归一化和标准归一化。 缩放归一化是非常简单的一种归一化方法,它通过缩放将数据所有特征的取值范围重新调节,使得每一维特征的取值落在[0,1]或[-1,1]。对于每一维特征x,调节公式为 x^i=xi-miniximaxixi-minixi(566) 其中,min(x)和max(x)分别是所有样本中的特征x的最小值和最大值。例如,在处理图像时,每个像素都是一维特征,所有像素的初始值都在[0,255]。因此,对于每一个像素,只需要将其除以255就可以缩放至[0,1]。 标准归一化是另外一种比较常用的归一化方法,也称为zscore归一化。经过标准归一化处理后,所有维度的特征都服从均值为0、方差为1的标准正态分布。其具体做法是,对于训练集内的所有样本,假设样本数量为N,对于每一维特征x,首先计算特征x在所有训练样本上的均值和标准差,如式(567)和式(568)。 μ=1N∑Ni=1xi(567) σ2=1N∑Ni=1xi-μ2(568) 然后,将所有样本的特征x减去均值得到零中心化的数据,再除以标准差,调整数值范围,得到新的特征值,如式(569)。 x^i=xi-μσ(569) 图523展示了原始数据、零中心化数据和标准归一化后的数据分布。可以看到,相对于二维原始数据,去均值后的数据是以原点为中心的,然后两个维度都除以标准差调整数值范围,双向箭头描绘了数据不同维度的数值范围,中间的零中心化数据两个维度的数值范围不同,标准归一化的数据两个维度数值范围相同。 图523原始数据、零中心化数据与标准归一化后的数据图片来自: 杜客.CS231n课程笔记翻译: 线性分类笔记(上)[Z/OL].https://zhuanlan.zhihu.com/p/20918580. 注意,对于图像数据,由于像素的数值范围是0~255,因此一般不需要对图像进行标准归一化操作; 对于音频数据,该方法是十分有用的。 白化是另一种数据预处理方法,这种方法需要先对数据进行零中心化处理。白化的目的是去除输入信息的冗余信息。例如图像数据,相邻像素之间具有很强的相关性,这种相关性对于模型训练而言是冗余的。使用白化进行预处理后,可以大大降低特征之间的相关性,使得所有维度的特征都有相同的方差。数据白化首先需要使用主成分分析(Principal Component Analysis,PCA)方法去除不同成分之间的相关性。熟悉PCA的读者可能知道,PCA算法一般用于降维,此处不再用于降维,而是使用PCA去除特征间的相关性,在求出特征向量后,直接将数据映射到新的特征空间(相当于坐标空间的旋转)。白化操作的输入是特征基准上的数据,令每个维度都除以其特征值来对数值范围进行归一化。因此,白化的步骤主要包括PCA预处理和白化操作。详细过程如下: (1) 对数据进行零中心化处理,即数据的每一维度独立的特征都减去该特征的样本均值,几何上可以理解为在每个维度上都将数据集的中心迁移到原点。 (2) 求解数据的协方差矩阵,对协方差矩阵分解得到特征向量,然后将经过零中心化处理的原始数据投影到特征向量上进行坐标转换,该过程去除了数据的相关性。PCA在本步骤只选取部分特征向量,丢弃那些方差较小的维度,从而实现降维。 (3) 将上一步得到的以特征向量为基准的数据的每一维都除以对应维度的特征值,这样得到的数据被重新调整数值范围,数据的分布变成均值为0、协方差矩阵为单位矩阵的高斯分布。 图524展示了对于二维原始数据,分别使用PCA进行去相关性以及使用白化操作之后数据的分布。对于图左侧的二维原始数据,中间表示的是经过PCA操作的数据。可以看出,去相关性的数据是零中心的,变换到了数据协方差矩阵的基准轴上,协方差矩阵变成对角阵。白化后的数据,每个维度都被特征值调整了数值范围,将数据协方差矩阵变为单位矩阵。从几何上解释,就是对数据在各个方向上拉伸压缩,使之服从高斯分布。 图524原始数据、去相关性数据与白化后的数据① 实际上,对于图像数据,大部分情况下只进行零中心化的处理,而不会归一化像素值。因为对于图像来说,每个像素已经具有相对一致的范围和分布,没有必要进行归一化。相比之下,一般的机器学习问题的数据有取值范围差别很大的特征,需要对这些特征进行归一化处理。对于PCA或者白化等更为复杂的预处理操作,图像应用领域也不会使用。需要注意的是,如果在训练阶段进行了数据预处理,那么在测试阶段也需要做预处理。例如,训练阶段求出了训练集数据的均值,在测试阶段同样应使用这个均值做相同的处理。总之,对于图像数据,只进行零中心化的预处理,使用整个训练集计算出均值图像,其尺寸和每张图像相同,然后将所有训练图像都减去均值图像的值; 对测试图像也要进行相同的操作,将测试图像减去这张均值图像然后再输入网络。 5.5.2超参数调优 神经网络中存在许许多多的超参数,在前文优化部分频繁提及的学习率就是神经网络中最重要的超参数之一。超参数是一类在模型开始学习之前就要设置的参数,不能像权重矩阵那样通过训练得到。神经网络中存在的超参数主要包括以下几类。 (1) 网络结构类: 包括神经网络的组织形式、层数、每层神经元数量、激活函数的类型、卷积网络中的核宽度以及每层核数量、是否使用零填充、池化方式的选择、卷积和池化步长、是否使用Dropout以及Dropout比率等。 (2) 优化类: 包括优化算法的选择、学习率的设置、小批量样本的数量、权重衰减系数,如果选择动量法或Adam方法,还有衰减率等。 (3) 正则类: 包括正则化策略的选择以及正则化系数。 尽管神经网络有非常多的超参数需要设置,但是不同超参数的设置难度是不同的。例如,对于Dropout比率,一般选为0.5; 动量法中的衰减因子ρ,根据经验一般设置为0.5,09,0.95和0.99中的一个值。因此,这种类型的超参数一般设置为经验上表现良好的数值即可,而不必重新尝试不同的值来找到最优的设置。但是,对于学习率这个十分重要的超参数,必须谨慎设置,因为它以一种更为复杂的方式控制模型的性能,既不能设置得太大也不能太小。因此,如果由于时间限制或者计算代价限制而只能调整少量的超参数,应当优先调整学习率。 超参数在更高层次上控制着模型的性能,因此在实践过程中,总希望找到一组最优的超参数配置,提升训练的效果,使得模型发挥最大的性能,这就是超参数优化(Hyperparameter Optimization)问题,也称为模型选择(Model Selection)问题。与普通的优化问题不同,超参数优化存在一定的困难。首先,超参数优化是一个组合优化问题,不能使用梯度下降算法进行优化,不存在一种通用而有效的优化方法; 其次,为评估不同的参数配置性能而完整地训练模型所需的时间代价非常高。因此,超参数优化并不能看作简单的参数优化问题。一组超参数配置表现如何,通常通过优化算法在独立数据集(即验证集)上的性能表现来衡量,一般采用交叉验证来估计不同参数配置在验证集上的表现,从而估计其泛化性能。交叉验证是一种检验超参数设置效果的方法。首先,使用预先确定的超参数在训练集上进行训练,然后再在独立的数据集(即验证集)上评估设置的超参数的表现,一般检验在验证集上的错误率,最终选择在验证集上表现最好的超参数配置来确定最终训练模型; 然后再使用额外的独立数据集——测试集来评估最终模型在未知数据上的泛化性能。其中,需要注意的是,无论训练集、验证集或测试集,都是从同一分布中抽取的,它们独立且同分布。另外,测试数据在模型训练期间是不可见的,只有在模型最终训练完成后用于测试阶段,测试数据不可用于训练阶段,因为这样可能会产生过拟合现象,无法正确评估模型的泛化性能。而训练集和验证集都是在训练阶段使用的,验证集是从训练集中分离出的独立数据集,二者一个用于确定超参数,另一个用于确定模型中可学习的参数。 实践中设置超参数常用的方法有人工设置、网格搜索以及随机搜索等,下面对这些方法进行详细介绍。 1. 人工设置 人工设置超参数必须充分了解超参数、训练误差和泛化误差以及计算资源(包括内存和运行时间)之间的关系,其目标是在有限运行时间和内存大小的条件下,最小化泛化误差,即提升模型在未知数据上的泛化性能。如果某些超参数配置在实践中证明具有不错的效果,可以直接基于这些经验配置。另外,在已有相同类型的应用或架构上表现不错的参数配置也可以直接使用。人工搜索主要依靠使用者的经验和判断来设置超参数,好处是可以大大降低搜索最优超参数的时间和计算代价,并且对于某些超参数而言选择经验值一般表现不错。 2. 网格搜索 网格搜索是一种传统的超参数优化方法,通过对超参数空间的一个较小的有限子集进行搜索,即通过尝试组合各个超参数的不同配置来确定一组表现不错的超参数配置。例如,对于一个含有K个超参数的模型,每个可行的超参数配置x都是超参数取值空间χ的一个点,χRK。如果第k个超参数有mK个可行的取值,对于所有超参数,共有m1×m2×…×mK个可行的超参数配置,如果某些参数是连续实值或者搜索范围无界,在引用网格搜索之前需要对这些参数设置边界并进行离散化。一般而言,对于连续的超参数,不能等间隔抽取进行离散化,需要根据超参数本身的特点来离散化。例如,对于学习率,通常是在对数尺度上进行采样,选取的学习率一般为0.1,0.01,0.001等数值; 但对于Dropout率,可能在(0,1)进行均匀采样更合适。对于超参数的搜索范围,每个超参数最小值或者最大值可以基于先前相似实验得到的经验保守地进行选取,以保证最优的超参数配置在搜索范围内。在确定了每个超参数的有限值集后,就可以对不同超参数组合进行搜索了,如图525左图展示了一个只含有两个超参数的例子,对于该例,每个超参数都包含三个可能的取值,网格搜索算法通过选取不同超参数取值组合进行训练,即选择图中每个网格点来训练不同的模型,最后在验证集上测试这些模型的性能,选取一组性能最好的配置。 通常需要多次使用网格搜索来确定最优的配置,这样效果会更好。对于超参数α,在其离散化的值集合{-1,0,1}内执行网格搜索从而确定α的最佳取值为集合中的1,极有可能是因为设置的搜索范围过小,低估了最优值α所在的范围,因此需要改变搜索的范围,例如在集合{1,2,3}再次进行搜索。实践中通常采用粗细粒度结合进行搜索,首先从粗粒度网格开始搜索,例如先在集合{1,2,3}中进行搜索,如果最佳值为1,就缩小范围,细化为细粒度网格进行搜索,在集合{-0.1,0,1}上进行精确搜索。 网格搜索存在的一个问题是,其仅适用于网络中含少量超参数的情况,例如含有三个或者三个以下的超参数的网络,常用网格搜索。一旦超参数数量明显增加,计算代价会相应地随着超参数的数量呈指数级增长,对于K个超参数的所有可能的配置,总共需要训练m1×m2×…×mK个模型并需要对这些模型进行性能评估。对于较大的K和更多的可能取值,计算量巨大,虽然可以并行地训练不同的模型,也无法提供令人满意的搜索规模。 3. 随机搜索 网格搜索是一种穷尽所有网格点(每个网格点代表一种超参数配置)的方法,需要巨大的运算力。随机搜索作为网格搜索的替代方法,简单方便,可以快速地收敛到良好取值点。与网格搜索不同,随机搜索不再对搜索范围进行固定采样,而是对超参数进行固定次数的随机搜索,对每一个超参数在固定范围内进行随机采样,然后选取一个性能最优的配置。 随机搜索比网格搜索更有效的原因在于,不同的超参数对于模型性能的影响是不同的,对于某些超参数例如学习率,对模型性能影响较大,而另外一些像正则化系数的超参数对模型性能的影响就很小。如果使用网格搜索,会在不重要的参数上做大量不必要的尝试,例如对于某个超参数α,其取值对模型性能影响甚微,此时网格搜索对于该参数的两个不同的取值(其他超参数取值都相同的情况下)会给出几乎相同的结果。而随机搜索中,其他超参数取值两次都相同的概率是很低的,随机搜索随机采样的两组超参数配置一般不会很相似,所以随机搜索会比网格搜索更快地找到较优取值,减少了对不重要参数的过度探索。 如图525所示,图中有两个需要进行搜索的超参数,分别使用网格搜索和随机搜索得到图示采样点。两个超参数一个比较重要,对模型性能影响较大,另外一个对模型性能影响较小,图中的曲线显示了重要参数良好取值的位置。可以看到,如果采用网格搜索就只能采样到3个值而错过了重要参数良好取值的区域。而随机搜索可以探索重要变量的不同取值,尽快找到良好取值的区域,可以使用更少的搜索次数更快速地确定良好取值。 图525网格搜索与随机搜索的对比 与网格搜索类似,通常也会由粗粒度到细粒度进行多次随机搜索,基于前一次的结果细化搜索范围来改进下一次搜索,直到找到一个比较合适的配置。 4. 贝叶斯优化 超参数的搜索也可以看作一种优化问题,将超参数优化问题用式(570)表示。 x=argminx∈χfx(570) 其中,决策变量x是超参数; 优化的目标函数f(·)是验证集上的性能度量,例如验证集上的错误率; x是理想的超参数组合,是搜索的目标; χ表示可行超参数域,x的取值可以是域χ中的任何值。简单来说,超参数优化问题即找到在验证集性能度量上表现最佳的超参数。 一个比较合理的想法是像训练模型参数一样对超参数进行优化,计算验证集上误差函数关于超参数的梯度,然后执行梯度下降算法进行更新。但是,这个想法大多数情况下是不可实现的,一方面因为超参数优化需要高额的计算和存储成本; 另一方面误差函数关于超参数不一定可导,因为某些超参数可能是离散的。针对以上问题,提出一系列基于模型的超参数搜索算法,其中之一就是贝叶斯优化(Bayesian Optimization,BO)。与网络搜索和随机搜索这种当前搜索结果独立于历史搜索结果的方式不同,贝叶斯优化旨在寻找更加高效的搜索算法,其充分利用历史搜索结果,并在此基础上进行进一步的探索。贝叶斯优化根据历史信息对目标函数建立概率模型,将超参数映射为目标函数的得分概率py|x,建立的概率模型被称为目标函数的“代理”,选择在代理函数上表现最佳的超参数,并用此超参数来评估目标函数以衡量选择的超参数的表现。然后,该组超参数和目标函数组成新的数据点对,作为历史信息更新概率模型以实现对目标函数更加精准的建模,再在更新后的模型上选择最有可能的解并评估目标函数,如此反复。因此,贝叶斯优化框架能够使用较少的评估次数求得目标函数的近似最优解。 需要注意的是,超参数优化是一个“黑盒优化”问题,因为关于决策变量x的目标函数fx并不可知,即超参数和验证集上性能度量值之间的映射关系无法获得,因此在优化的过程中只能获取模型的输入值和输出值,不能获取模型训练过程中的梯度信息,也不能使用凸优化方法求解。另外,评估目标函数的代价是昂贵的,因为对于不同的超参数配置,要想获取目标函数值来评估超参数配置在验证集上的表现,需要按照选取的超参数配置对模型进行完整的训练,然后再在验证集上进行评估,计算相应的性能度量,对于深层神经网络这种复杂模型,超参数数量比较多,训练复杂度高,周期也比较长,可能需要数天才能完成。而贝叶斯优化恰好可以解决上述问题,其通过选择代理而非直接对目标函数进行优化,因为代理有具体的形式且比目标函数更容易优化。另外,贝叶斯优化充分利用历史信息,尽量减少评估目标函数的次数,评估代价相对较低。因此,其在目标函数表达式未知、非凸、多峰、评估代价高昂(需要花费高额代价才能观测到目标函数的返回值)的复杂优化问题上表现良好,已被作为一种有效方法广泛使用。 在其他领域,贝叶斯优化也被称为序贯克里金优化(Sequential Kriging Optimization,SKO)、基于模型的序贯优化(Sequential Modelbased Optimization,SMBO)、高效全局优化(Efficient Global Optimization,EGO),它是一种基于模型的序贯优化方法,在前一次评估完成后才能进行下一次评估,因此贝叶斯优化是顺序的。由于其利用历史信息修正优化,因此能耗费较少的评估代价得到一个近似最优解。贝叶斯优化算法流程如表57所示,其优化过程是顺序的,体现在循环体内相同操作的多次循环。对该算法进行简单介绍: 输入参数f、χ、S、M分别表示目标函数、可行超参数域、采集函数(Acquisition Function)、目标函数的概率代理模型(Probabilistic Surrogate Model)。其中,采集函数和概率代理模型是贝叶斯优化框架的核心部分,采集函数是一种选择超参数的标准,目的是选择当前最有潜力的解从而避免不必要的采样。代理模型是以(超参数配置,目标函数值)为数据点对建立的模型,替代目标函数进行建模并进行优化,在优化过程中不断根据新增的数据点进行调整以更好地逼近目标函数。代理模型的选择有很多种,常用的有随机森林(Random Forest,RF)、高斯过程(Gaussian Processes,GPs)等。同理,采集函数也有多种选择,常用的有期望改善(Expected Improvement,EI)函数、概率改善(Probability of Improvement,PI)函数、高斯过程置信上界(GP Upper Confidence Bound,GPUCB)等。不同的贝叶斯优化方法的采集函数和代理模型有所不同,需要针对具体问题进行选择。 对于贝叶斯优化算法流程每一步的详细解释如表57所示。 表57贝叶斯优化算法流程 1. 输入参数: f,χ,S,M 2. 初始化数据集f,x→D: 首先在可行超参数域中随机采样,然后使用选择的超参数配置训练模型并进行评估来构造初始数据集D={x1,y1,…,xn,yn},其中yi=fxi,该数据集用来训练代理模型。 3. 对于|D|≤i≤T,执行如下操作: 初始化数据集后进入循环体进行迭代优化,T为循环次数,需人为设定,是参数选择的次数或者目标函数评估次数,因此T不能太大,因为评估目标函数的代价是昂贵的。 4. 选择模型函数py|x,D←(M,D): 根据选择的概率代理模型,基于数据集D可计算得到具体的模型函数表达形式,从而得到对于不同的输入目标函数的后验概率。 5. xi←argmaxx∈χSx,py|x,D: 根据代理模型给出的结果,即目标函数的后验概率分布,由采集函数确定的标准来选择下一个最具潜力的超参数。 6. yi←fxi: 使用选择的超参数代入模型进行训练并评估,得到输出值yi。 7. D←D∪xi,yi: 最后将新的数据点对加入数据集D中,作为历史信息以更精确地更新代理模型,掌握更多信息的代理模型对超参数的选择会越来越有把握。 下面采用一个具体的例子详细描述贝叶斯优化的具体流程,该例子使用高斯过程回归建立概率代理模型。假设目标函数fx服从高斯过程,每次迭代通过已有的N组实验结果D=xn,ynNn=1(yn为fxn的观测值)对高斯过程进行建模,则对于任意超参数,目标函数值都服从高斯分布,即py|x,D=Ny|μ,σ2,计算出fx的后验分布便可以使用采集函数来确定下一个超参数。首先,对于初始数据集D(有三个数据点),通过高斯过程回归得到参数在每一个取值点处目标函数的后验概率分布,每个点都服从高斯分布,虚线代表的是代理模型预测的目标函数的均值,阴影区域代表的是目标函数以均值为中心一个方差内的区域,实线代表真实目标函数值。可以看到对于已知的数据点,其方差很小,因为其真实目标函数值是已知的,因此具有高度确定性。对于其他超参数对应的点,也给出了相应的均值和方差,其中均值代表该点期望获得的效果,均值越大表示对应该点的超参数配置在模型上表现越好。因此,直观上应当选择均值较大的点,而方差反映该点的效果的不确定性,方差越大说明该点是否能在模型上取得良好效果的概率越不能确定,极可能带来显著的效果提升也有可能效果很差,因此也应该去探索。如果追求稳妥而选择均值大的点,这称为利用(Exploitation),而冒险选择方差大的点则称作探索(Exploration),不同的场景应该选择不同的策略。如果需要确定超参数配置的模型比较复杂,训练起来费时费力,这种情况下应尽量选择均值较大的超参数配置; 而如果计算力足够且模型易于训练,就不能放弃探索的机会,可以选择方差较大的点以探索性能更好的配置方案。实际上,采集函数就是在利用和探索之间权衡,给出最大化采集函数的解。例如,UCB算法中的采集函数为均值加上n倍的方差,更为复杂的EI函数,其表达式如下: EIx,D=∫∞-∞maxy-y,0py|x,Ddy(571) 其中,y=minyn,1≤n≤N是当前已有样本中的最优值。该优化问题的目标是寻找在当前模型py|x,D下,fx超过y的期望最大的点x。 假设本例中使用最简单的UCB算法,并将采集函数绘出,如图526所示。最大化采集函数的点已用星号标出,使用该点代表的超参数训练模型,并评估模型在该组超参数组合下的效果,将得到的观测数据加入数据集,则数据集内的样本就变成了4个,使用新的数据集更新概率模型,重新得到目标函数的后验概率分布并再次计算采集函数,如图527所示。可以看到,图中右边点的均值和方差都比较大,应当作为探索的区域,采集函数给出相同的结果,其给出的推荐超参数位于右边区域。再次使用推荐的超参数训练和评估,更新模型,不断重复上述过程。图528展示了当数据集有7个样本时的效果,可以看到,当样本越来越多时,对于目标函数预测的不确定性逐渐降低。因为获得了更多的信息,修正的高斯过程会越来越接近目标函数的真实分布,因此能够在极少样本的情况下逼近真实目标函数。当然,实际中深度学习中的超参数优化是一个黑盒问题,并不能得知真实的目标函数曲线,通过使用代理模型可以较大概率找到一个表现不错的解。 贝叶斯优化方法已经是一种比较成熟的超参数优化方法,Python语言中就有几个贝叶斯优化库可以直接调用,它们关于目标函数使用的代理算法不同,例如Spearmint(高斯过程代理)、SMAC(随机森林回归)、TPE(Tree Parzen Estimator,其中一种实现是Hyperopt)。贝叶斯优化仍然是一个重要的研究领域,对于其存在的种种问题,已存在部分解决措施。例如使用高斯过程建模需要计算协方差矩阵的 图526样本数为3时概率代理模型给出的预测以及采集函数给出的推荐点图片来自: tobe.贝叶斯优化: 一种更好的超参数调优方式[Z/OL].https://zhuanlan.zhihu.com/p/29779000. 图527样本数为4时更新的概率代理模型和采集函数① 逆矩阵,时间复杂度为On3,则可以使用一系列近似技术在精度和复杂度之间权衡。另外,关于贝叶斯优化算法的扩展也有很多研究,例如概率代理模型向高维扩展、向多任务扩展、向冻融(Freezethaw)扩展。相应地,对于采集函数的扩展有: 提出具有代价敏感性的采集函数,进行并行化扩展等。对于此部分内容不进行详细介绍,感兴趣的读者可自行查阅相关资料。 图528样本数为7时更新的概率代理模型和采集函数图片来自: tobe.贝叶斯优化: 一种更好的超参数调优方式[Z/OL].https://zhuanlan.zhihu.com/p/29779000. 5. 动态资源分配 尽管对于超参数优化的研究有很多,但是绝大多数都将超参数优化问题看作黑盒问题,并且只有在模型经过完整训练至收敛后才对其进行评估。对于深层神经网络,每组超参数的评估代价过高,因此部分研究尝试利用中间结果,例如Jamieson和Talwalkar在所著论文中提到的,利用模型训练的迭代属性(使用梯度下降法训练模型),将超参数优化视作非随机最优臂识别的一个实例,评估中间结果的质量(不用完全训练的模型),在训练的早期阶段就舍弃那些似乎不合适的超参数配置,而将更多的资源留给有希望获得最佳效果的超参数配置,继续进行训练。最优臂识别(Best Arm Identification)是多臂老虎机(Multiarmed Bandits)目标函数的两种形式之一,旨在给定有限的次数内,找到使平均收益最大的臂; 对于多臂老虎机问题,有随机和非随机两种设置。超参数优化可以看作多臂老虎机中非随机最优臂识别问题,其中每一个摇臂对应一个固定的超参数配置(N个摇臂则对应N组超参数配置), 摇臂次数B对应于可利用的有限资源总数。因此,为了合理利用资源,将更多的资源留给更有可能的配置,即在模型训练早期停止那些看起来不太有希望的超参数配置,使用更多的资源对候选的超参数配置进行进一步筛选,此时每组配置得到的资源更多,因此评估的结果更为准确,逐轮筛选直至确定最优配置并输出。对于该问题的解决方案——逐次减半(Successive Halving)算法,其具体过程如图529所示。 一共进行T(T=log2n-1)轮筛选,每轮筛选逐次减半直至选出最优的超参数配置。先将总的资源分为T份,每一轮筛选使用一份资源,第一轮筛选对所有超参数配置都进行评估,因此第一轮筛选中每一组超参数配置分到的资源为总资源的1/TN,N为超参数配置组数。根据评估结果选择一半数量的超参数配置进入第二轮筛选,第二轮筛选只有一半 Successive Halving Algorithm input:Budget B,n arms where i,k denotes the kth loss from the ith arm Initialize: S0=[n]. For k=0,1,…,「log2(n)-1 Pull each arm in Sk for rk=B|Sk|「log2(n) additional times and set Rk=∑kj=0rj. Let σk be a bijection on Sk such that σk(1),Rk≤σk(2),Rk≤…≤σk(|Sk|),Rk Sk+1={i∈Sk∶σk(i),Rk≤σk( |Sk|/2」),Rk} output: Singleton element of S 「log2(n) 图529逐次减半算法图片来自: Jamieson K,Talwalkar A.Nonstochastic best arm identification and hyperparameter optimization[C]//Artificial Intelligence and Statistics.2016: 240248. 数量的超参数配置,其可利用的资源仍然为一份,因此每一组超参数分到的资源是第一轮的两倍,因此有更多的资源进行更准确的评估。再根据评估结果继续筛选直到输出最优配置,筛选轮数越多每组超参数分配到的资源越多。在逐次减半算法中,超参数配置的数量N十分关键,所有的超参数配置都是从可行超参数域中采样得到的。如果采样的数量越多,那么采样中包含最佳配置的可能性越高。但是总体上,每组配置分到的资源也越少,早期评估的结果就很有可能不准确。反之,如果选择的N较小,对于超参数的评估就会越准确,但很有可能无法得到最优配置,因此N的设置是一个关键问题。来自 JMLR 2018 最新的研究提出一种改进算法——HyperBand,通过尝试不同的N来选取最优的超参数。算法流程如图530所示,本质是在逐次减半法的外层增加一层循环,外层循环用于确定合适的N值,不同循环采样得到用于评估的超参数组合的数量不同,而内层循环即逐次减半算法,通过逐 Algorithm 1: HYPERBAND algorithm for hyperparameter optimization. input: R,η(default η=3) initialization: smax=logη(R)」,B=(smax+1)R 1for s∈{smax,smax-1,…,0} do 2 3 4 5 6 7 8 9 n= BRηs(s+1) ,r=Rη-s //begin SUCCESSIVEHALVING with (n,r) inner loop T=get_hyperparameter_configuration(n) for i∈{0,…,s} do ni=nη-i」 ri=rηi L={run_then_return_val_loss(t,ri):t∈T} T=top_k(T,L,ni/η」) end 10end 11return Configuration with the smallest intermediate loss seen so far. 图530HyperBand算法图片来自: Li L,Jamieson K,DeSalvo G,et al.Hyperband: a novel banditbased approach to hyperparameter optimization[J].Journal of Machine Learning Research,2017,18(1): 67656816. 轮筛选挑选出最优的超参数配置。文中给出了一个基于MNIST数据集对LeNet网络使用HyperBand算法进行超参数调优的示例,并将迭代次数定义为预算(budget),即一个epoch代表一个预算。超参数搜索空间包括学习率、用于批量梯度下降的批大小、卷积核数目等,图531的表中给出了需要训练的超参数组的数量和每组超参数资源分配情况。s为不同的外层循环,不同循环中超参数配置数量N不同,分别为81、27、9、6和5; ni为内层循环逐次减半算法第i轮需要评估筛选的超参数配置的数量; ri为每一组配置分配得到的资源。经过逐轮筛选得到当前N组超参数配置下,评估性能最好的一组。图531中右图给出了不同的s(代表不同的N)对搜索结果的影响,可以看到s=0(对应N=81)或者s=4(对应N=5)表现都不是最好的,因此选择合适的N实际上是对利用和探索的权衡,关于该算法的具体细节可参考相关论文。 图531不同的s使用HyperBand算法的表现图片来自: Li L,Jamieson K,DeSalvo G,et al.Hyperband: a novel banditbased approach to hyperparameter optimization[J].Journal of Machine Learning Research,2017,18(1): 67656816. 上述算法中对超参数的采样默认使用均匀随机采样,有些算法在此基础上结合了贝叶斯优化进行采样,例如BOHB算法。BOHB算法依赖HyperBand算法来决定每次运行多少组参数和每组参数分配多少预算,它的改进之处是将 HyperBand算法中每个循环开始时随机选择参数的方法替换成依赖历史数据建立模型(贝叶斯优化)进行参数选择。一旦贝叶斯优化生成的参数达到迭代所需的配置数, 就会使用这些配置执行标准的逐次减半算法。观察这些参数在不同资源分配下的表现,在后续迭代中用作贝叶斯优化模型选择参数的基准数据。无论是逐次减半算法还是HyperBand算法,都是在给定有限资源的条件下,更好地利用资源找到最优超参数,并且可以和贝叶斯优化算法进行融合。 6. 神经架构搜索 神经网络中的超参数可以根据其属性分为两类。一类是与训练有关的超参数,例如学习率、批量大小、正则化系数以及学习率衰减系数等。而另一类则是与网络结构有关的超参数,例如网络的拓扑结构,包括网络层数以及层间的连接关系、层的类型选择、层之间的组织排布等; 层内部也包括各种各样的超参数,例如卷积层中卷积核的大小、数量、步长以及是否使用零填充等,还有池化大小、步长的选择以及采用哪种池化方式等。部分文章将深度学习中只与训练有关的超参数优化称为超参数优化; 而将调节与网络结构有关的超参数称为神经架构搜索(Neural Architecture Search,NAS),对该类超参数进行调整会改变神经网络的结构,其优化本质即通过大量尝试来探索一种更为合理的网络结构。已经发现的并且证明表现良好的几种神经网络架构通常都是由有数年经验的专家设计的,而NAS作为一种新兴研究方向,旨在将神经网络结构设计的过程自动化,使得非神经网络领域专家也能根据具体任务使用自动设计的模型来解决问题,有效降低神经网络的使用和实现成本。论文A Survey on Neural Architecture Search总结了截至2019年所有与NAS相关的工作,NAS作为自动机器学习(Automatic Machine Learning,AutoML)的子领域之一,主要用来探索深度学习中的网络结构。该文中作者提出了一种形式化的方法,用于统一并分类现有的关于神经架构搜索的方法。如图532所示,构成NAS的三要素为搜索空间、搜索策略和性能评估策略,其搜索流程如图532所示。对于给定的“搜索空间”(即候选神经网络架构集合),使用某种搜索策略从这些候选架构中搜索出最优的神经网络架构,对于搜索出的优秀神经网络架构,使用评估策略评估该架构的性能,常用的性能指标有精度、速度等。 图532神经架构搜索框架图 搜索空间定义了可以搜索的架构类型以及形式化描述结构。从数学上看,神经网络是一个函数,对输入变量进行一系列操作得到输出,因此神经网络可以用计算图语言形式化地表示为无孤立节点的有向无环图(DAG),由于神经网络的层数、层内超参数数量都不固定,因此用于描述网络结构的参数是变长的。搜索空间的设计是神经架构搜索的重要组成部分,好的搜索空间不仅可以加速搜索过程,还会影响搜索的持续时间和架构的质量。早期的NAS工作中,由于当时的神经网络都是基于链式的前馈型网络,空间的设计主要是用于搜索链式结构。随着ResNet、DenseNet、Skip Connection等结构的出现,分支架构在性能上超越了传统网络,NAS也将这种分支架构纳入考虑,提出了合适的搜索空间,可以产生更加多样的架构。另外,NAS还考虑了含有很多重复模块的结构,例如Inception、DenseNet、ResNet等。这些重复的模块被称为cell或者block,相应地提出了基于cell的搜索,探索cell的内部结果并按一定的方式进行组合。文中将搜索空间分为全局搜索空间和基于cell的搜索空间,前者是为表示整个神经架构的图定义的; 后者假定神经架构是由若干cell组成的,这些cell被重复用于构建完整的网络,其通过减少自由度达到减小搜索空间的目的,并且使得搜索到的结构在数据集之间具有更好的迁移能力。总体来说,基于cell的搜索空间(特别是NASNet已成为领域规范)是探索新架构的良好选择。 搜索策略定义了如何在搜索空间中找到最优的网络结构,其本质是一个优化问题,通过最大化验证集上的目标函数来找到最优的结构α*,形式化表示为 α*=argmaxα∈Afα(572) 其中,A为搜索空间,f(·)为给定结构在验证集上使用选择的性能评估策略给出的性能度量,因为f(·)是不可知的,故神经架构搜索实际上是一个黑盒优化问题。文中给出了4种典型的优化方法: 强化学习、进化算法、基于代理模型的优化和一次性架构搜索。其中,强化学习系列和进化算法系列有着不错的表现。 图533强化学习用于神经架构搜索 基于强化学习的NAS算法将神经网络结构设计视为强化学习问题,最终习得能够产生网络结构的最优策略。NAS任务中,架构的生成可以看作智能体(agent)选择一系列动作(action),而奖励(reward)则是生成的架构在验证集上的性能度量。通过将奖励传回智能体,使得智能体进行调整从而做出更好的动作,学习到越来越好的网络结构,如图533所示。使用强化学习进行神经架构搜索的两项开创性工作分别为麻省理工学院的Designing Neural Network Architectures using Reinforcement Learning和Google公司的Neural Architecture Search with Reinforcement Learning。前者将网络架构搜索建模成马尔可夫决策过程,使用QLearning算法产生CNN架构; 后者使用基于策略梯度优化的方法,使用RNNcontroller采样生成描述网络结构的字符串,对生成的结构进行训练并评估,然后使用REINFORCE学习控制器的参数,使控制器产生准确率更高的结构。后来Google公司提出了NASNet,通过限定网络结构的类型,对搜索空间进行简化,即使用基于cell的搜索空间,依旧使用策略梯度方法来学习该空间下的控制器参数,具体使用PPO(Proximal Policy Optimization)算法对控制器参数进行更新。为提升搜索效率,Google公司先后提出了PNAS(Progressive Neural Architecture Search)方法和ENAS(Efficient Neural Architecture Search)方法,前者使用“基于序列模型优化(SMBO)”的策略取代NASNet所用的强化学习; 后者通过在各个网络之间共享权重来减少计算量。 进化算法(Evolutionary Algorithm,EA)是一种针对黑盒问题的基于种群的全局优化方法,由以下基本组件组成: 初始化、父代选择、重组和变异、幸存者选择。初始化定义了如何产生第一代种群,完成初始化后,重复以下步骤直到算法终止,如图534所示。 图534进化算法用于神经架构搜索 (1) 从种群中选择父代。 (2) 重组和编译产生新的个体。 (3) 评估新个体的适应度。 (4) 选择种群的幸存者。 在神经架构搜索任务中,种群由一组网络结构组成。首先,随机初始化若干网络结构作为初始种群,在步骤(1)中选择一个父代结构或者对一对结构进行变异或重组,该操作使得搜索空间中产生了新的网络结构。步骤(3)对这些结构计算适应度值(即神经网络在验证集上的精度),经过重组和变异,种群规模随之增长,“幸存者选择”是为了减小种群规模,并使个体之间的竞争成为可能。不断重复上述过程,直到找到最优网络结构。遗传算法(Genetic Algorithms,GA)是一类广泛应用于神经结构搜索的进化算法。用进化算法解决 NAS 问题,不同的工作聚焦在不同的方面,例如如何选择父代,如何更新种群,如何生成子代种群等。文中给出了6个基于EA的NAS相关工作的比较,详情可参考论文。 除了强化学习和进化算法,另一类比较新的方法为基于梯度的方法。通过将离散的搜索空间变成连续空间,目标函数变为可微函数,然后使用基于梯度的优化方法高效地寻找最优结构,其中DARTS方法和Neural Architecture Optimization中提出的方法都是基于梯度的。 除了上述三种主流方法外,实际上还有很多其他搜索策略用于神经架构搜索,例如基于模型的序列优化(上文提到的PNAS)、蒙特卡罗树搜索(MCTS)、贝叶斯优化等。由于神经结构搜索的低效性,搜索空间巨大以及评估性能需要对模型进行训练导致过大的计算量,使得NAS无法进行推广,因此后续很多工作都是针对效率问题展开的。常见的方法有层次化表示(例如NASNet使用基于cell的搜索空间减少了搜索规模)、权重共享(例如ENAS令所有的子网络重用权重而非对每个候选模型从头训练)、表现预测(例如PNAS中使用代理模型来评估候选模型的性能从而减少大量训练时间的耗费)。随着NAS的发展,作为新的研究方向,提出一系列变种及扩展。例如多目标架构搜索,同时考虑架构性能、存储空间、模型大小、计算量、功耗等多个目标。另外,已开发的结构搜索技术也已经扩展到深度学习的相关组件的高级自动化,例如搜索激活函数、自动数据增强、模型压缩等。NAS作为当前高热的研究方向,旨在帮助人们自动搜索适合当前任务的深度神经网络,以使用较低成本获得最优的深度模型。目前,已经产生了一些自动化工具可以使用,例如Google公司推出相应的平台CLOUD AUTOML,使得用户无须具备深度学习或者人工智能相关知识背景,只需根据给定的训练集和任务就能轻松地训练出高性能的深度网络,但是该平台是收费的。另一款NAS开源框架AUTO KERAS(GitHub地址为https://github.com/jhfjhfj1/autokeras)以论文Efficient Neural Architecture Search with Network Morphism(即ENAS)做指导,基于贝叶斯优化来搜索深度模型。读者可自行安装AutoKeras,并尝试给定数据集使用AUTO KERAS自动执行架构搜索。 对超参数执行交叉验证,交叉验证是在训练集上进行训练,然后在验证集上验证这些超参数的试验效果。首先,需要选择相当分散的数值,在几个epoch中进行迭代,经过迭代可以判断数值的好坏并做出相应的调整,这样就可以发现一个更精确的参数区间,并进一步搜索更精确的值。由于不断减小搜索区间的过程非常耗费时间,可以采用类似NANS激增这样的技巧,训练参数时,在每一个迭代或者epoch观察代价,如果出现一个远远大于初始代价的值,例如超过了3倍,就认为这不是一个正确的方向,则跳出循环停止对该参数的训练。与均匀采样相比,在区间内使用10的幂指数进行采样效果更好。 学习率、不同类型的衰减表、更新类型正则化以及网络结构隐藏层的数量和深度,这些都是可以优化的超参数。实际中,有大量的超参数优化采用交叉验证方式观察哪些配置效果更好。通过监测和可视化损失函数曲线可以看到哪些学习率值是好的,哪些学习率值是不好的。 5.5.3集成学习 集成学习(Ensemble Learning)作为一种在各类机器学习比赛中经常使用的技巧,实践中总能稳定提升模型的性能。集成学习通过训练多个模型并将这些模型组合起来以取得比单个模型更好的性能,其中多个模型被称为弱学习器,可以作为生成复杂模型的构件。这些弱学习器基于同一任务,通过样本扰动、输入特征扰动、输出表示扰动、算法参数扰动等方式生成,然后使用某种结合策略进行集成从而生成强学习器。集成学习的两个核心问题是如何生成弱学习器和如何组合弱学习器。可以通过使用不同的模型、不同的训练算法、不同的目标函数等生成不同的弱学习器,并且这些弱学习器需要满足“好而不同”,才能充分发挥集成学习的作用,即要求弱学习器尽量满足预测精准性和多样性。常见的组合策略有平均法(包括算术平均和加权平均)、投票法(主要有相对多数投票法、绝对多数投票法、加权投票法三种)和Stacking策略。其中,Stacking策略是在弱学习器的基础上再添加一层权重学习器(Meta Learner),该学习器将弱学习器的预测结果作为输入得到最终的预测结果。 传统集成学习中,所有弱学习器都是同质的,即如果使用决策树算法,那么对所有弱学习器都使用决策树。但是,现在集成学习的定义更加广泛,用于集成的模型也可以是异质的。为区分,前者称为同质集成,后者称为异质集成。具有代表性的集成学习方法主要有Bagging和Boosting。 1. Bagging Bagging(Bootstrap Aggregating)的主要思想是独立并行地训练多个不同的学习器,所有学习器共同决定测试样本的输出。该方法体现了自助采样法的思想。首先,通过有放回地采样构造N个数据集用于训练N个学习器,每个数据集的样本数量与原始数据集一致,因此可能有重复的样本,并且缺少部分原始训练集中的样本。通过自助采样法得到的数据集中大概有2/3的数据与原始数据集一致,并且不同的数据集缺失和重复的部分各不相同,训练集之间的差异造成训练出的学习器之间也具有差异性。图535为Bagging用于集成学习的示意图。训练得到N个弱学习器后,Bagging的结合策略非常简单,对于分类任务,可以根据N个弱学习器的结果投票决定输出值; 对于回归问题,则可以取N个学习器输出结果的算术平均值。 图535Bagging实现集成学习的示意图 随机森林(Random Forest,RF)是采用Bagging思想的一个具体实例,其以决策树作为弱学习器,然后采用Bagging集成技术训练得到随机森林模型。Bagging作为一大类集成方法,能够有效降低泛化误差,抑制模型的过拟合问题,使得集成得到的模型比单一模型更正则化,使得集成的模型泛化能力更强。 2. Boosting Bagging方法中各个弱学习器之间互相独立,与此不同,Boosting中弱学习器之间存在强依赖关系,各个弱学习器必须顺序生成。Boosting的工作机制为: 首先,使用初始训练集训练一个弱学习器; 然后,根据这个弱学习器的表现,基于先前的模型进行调整; 这样重复N次就可以生成N个弱学习器,每一个弱学习器都比前一个弱学习器有性能上的提升。按照这种方法,这些弱学习器必须顺序生成,无法并行化。Boosting框架将这些模型进行加权组合生成强学习器,这里弱学习器既可以使用同质模型也可以使用异质模型,常用作弱学习器的算法有神经网络和决策树等。 Boosting系列算法比较著名的有AdaBoost(Adaptive Boosting)算法和GBDT(Gradient Boosting Decision Tree)算法。AdaBoost算法在每次生成新的弱学习器时,将上一弱学习器发生错误的训练样本的权重增大,使得这些错误样本在后续受到更多的关注,最后将这些弱学习器进行加权组合,并且根据弱学习器的准确率赋予相应的权重,使准确率较高的弱学习器权重更高,每一轮训练中需要关注样本权重和弱学习器权重的更新。GBDT算法通过计算负梯度来改进模型,每一轮训练关注的重点是预测的残差(即负梯度),将前一次样本的残差作为输入数据进行训练,尽量拟合该参数,使得下一轮输出的残差不断减小,因此GBDT算法可以做到每一轮训练一定会向损失函数减小的梯度方向变化。GBDT算法仅利用了一阶的导数信息,改进算法XGBoost(EXtreme Gradient Boosting)对损失函数进行二阶泰勒公式展开,并添加正则项以避免过拟合。 与Bagging算法不同,Boosting算法旨在提升弱学习器的性能,随着集成的模型数量增加,算法性能会稳健提升,但效果的提升速度会越来越慢。 3. 神经网络中的集成 神经网络中使用集成技术主要是为了减小模型的泛化,避免过拟合。因此,部分模型集成方法可以看作正则化方法。通过训练多个独立的模型,然后在测试时对多个模型的预测结果取均值,使用该方法总能提升神经网络的准确率。有多种集成方法可以帮助实现正则化,例如使用同一神经网络进行不同的初始化,模型的多样化来自不同的初始条件; 或者应用不同的超参数配置,当使用交叉验证寻找最优超参数配置时,取性能较好的几组配置训练模型以实现集成,该方法提升了用于集成的子模型的多样性,但缺点是可能包含性能不理想的模型。也可以不独立地训练不同的模型,仅在单一模型中进行集成,例如可以在训练过程的不同时刻保留模型的快照,然后使用这些模型快照进行集成,在测试阶段把多个快照的预测结果进行平均。另一个技巧是,训练模型时,对不同时刻的每个模型参数计算指数衰减平均值,从而得到网络训练过程中一个比较平滑的集成模型,然后使用该集成模型的参数,这种方法叫作Polyak平均。 也可以使用集成技术构建比单个模型表示能力更强的集成模型,例如向集成模型逐步引入神经网络。 5.5.4监视训练过程 目前为止已经介绍了构建神经网络需要注意的各方面问题,那么如何基于特定任务从无到有地逐步建立一个端到端的模型呢?训练过程中又该如何进行人为把控以获得最好的效果呢?本节主要针对以上两个问题进行展开,介绍一个深度学习模型的完整构建流程以及监视训练过程。 设计流程可以分为数据和模型两大部分,数据部分包括大量的数据处理工作,例如数据采集。如果是监督学习,还需要为样本数据打标签,还要进行数据清洗等基础数据操作。总之,数据处理旨在获取高质量的数据集,这对模型性能的表现有很大的影响。假设已经获得了质量良好的数据集,本节将重点关注模型构建与训练。 针对具体应用,实际中通常将设计流程分为以下板块。 (1) 确定目标,根据具体任务选择合适的性能度量,并确定合理的性能期望作为目标。 (2) 确定合适的代理损失函数,建立一个尽量简单的端到端的工作流程。 (3) 搭建系统,监视整个训练过程,确定性能瓶颈。 (4) 查找产生性能瓶颈的原因,并进行改善,进一步提升模型性能。 在确定了任务以后,就要确定合适的性能度量,这些性能度量通常不能用作训练模型的目标函数,而是从任务层面衡量所构建系统的有效性。例如,在图像识别任务中,一般使用准确率或者等价的错误率衡量构建的系统的性能,而不是将其作为优化目标的交叉熵损失函数(不考虑正则化)。另外,许多任务需要更高级的性能度量。例如,在“癌症检测”的任务中,系统将“健康”误判为“患癌症”和将“患癌症”误判为“正常”这两种错误带来的后果是不同的,第二种错误是需要减少甚至避免的,为达到这个要求甚至可以增大第一种错误的概率。可以考虑使用代价函数来解决这个问题,对于不同的错误赋予不同的代价,可以给予第一种错误较小代价,而给予第二种错误较高代价,构建的系统应使整体代价尽可能小。其他可以用于描述系统的性能度量有精度、召回率、P权限、F分数/覆盖等,某些专业领域也有相应的标准。在确定了性能度量后,应当设立一个可实现的目标,即希望系统可以达到的性能期望,可以根据类似任务的表现来大致确定这个目标,当系统表现不佳时指导系统改进,进一步实现性能的提升。 确定好性能度量后,下一步需要确定合适的代理损失函数,并建立一个端到端的系统。由于某些性能指标难以用数学参数形式化表达并且不能直接作为优化的目标,因此代理目标函数将作为实际的优化目标,应当在构建完整的系统之前就确定其具体形式。这里应当注意,构建系统的初期应当尽量简单,可以使用小数据集进行拟合,使用较为简单的模型和简单的优化算法,并且不使用各种正则化策略。当出现问题时再根据实验反馈改善系统,可以考虑收集更多的数据,使用数据增强策略,增加模型复杂度,以提升模型的表示能力,考虑引入正则化、使用更复杂的优化策略等措施逐步改善系统的性能。不要一开始就使用复杂的系统,因为难以监控和调试,实践中成功的经验表明更重要的是正确地构建完整的操作流程而非使用复杂的系统。 构建一个端到端的系统,首先需要根据数据结构选择一类合适的模型。如果数据是维度固定的向量,可以使用普通的全连接网络; 如果是类似图像数据这样具有拓扑结构的数据,则可以考虑卷积神经网络模型; 如果数据是类似语音数据这种序列数据,可以使用循环神经网络来建模。确定网络类型后,需要根据任务构建具体的网络结构,包括网络深度、每层神经元个数、不同类型的层的排布、激活函数的确定等。卷积网络还需要确定卷积核、池化核的大小及数量以及池化方法等。自主设计网络架构可能会比较困难,但可以使设计的网络更贴近具体任务,也可以直接选择在类似任务上表现优良的模型架构。网络框架搭建完成后,需要确定各种超参数的值,例如小批量的大小、优化方法的确定以及相应的超参数设置、权重衰减系数等,这里的超参数不包括与网络结构有关的超参数,超参数优化与配置的内容见5.5.2节。然后对网络进行初始化,初始化策略可见5.3节的介绍。如果使用sigmoid函数或者tanh函数作为激活函数,可选择Xavier初始化; 如果使用ReLU函数则可以使用He初始化或者使用简单的小随机数初始化,但是要配合使用批量归一化策略。初始后的网络接受预处理过的数据作为输入,先计算各层激活值和最终输出值进行前向传播,再利用反向传播计算参数梯度,并根据确定的优化策略对参数执行更新,不断迭代直至目标函数收敛或者达到预期值,常见的优化策略见5.1节和5.2节。在整个过程中,可以进行监控,发现错误适时停止以避免资源的浪费。当模型训练完成后,根据模型的性能度量评估模型的表现,这里注意应当关注模型的泛化能力,而不应该一味追求模型在训练集上的表现。根据模型的表现以及训练过程中发现的问题,对模型进行改进,例如加入各种正则化策略,使用集成学习或者对模型的某些方面做出改进,使得模型性能获得进一步提升。图536展示了深度模型构建流程,此处不包括依赖于具体任务的性能度量和代理损失函数的确定,仅将适用于所有任务的通用步骤提取出来。 图536深度模型构建流程图 通过以上介绍,已经大概了解了基于特定任务构建深度学习模型的流程。在整个过程中进行人为控制可以帮助模型取得更好的效果,那么如何监视训练过程并根据监视结果改善模型的表现呢?下面将根据流程图的顺序介绍“监视”是如何在不同部分发挥作用的。首先是超参数的确定,这里的超参数指广义的超参数,包括模型结构类型相关的超参数和与模型训练有关的超参数,涵盖流程图中确定网络结构和确定超参数两部分。由上文可知,需要评估不同超参数配置在验证集上的表现来选择超参数,需要对待评估的每一组超参数配置完整运行训练过程,这导致计算代价巨大,并且搜索速度很慢。因此,可以通过监视训练过程的学习曲线进行选择。图537展示了几种可能的学习曲线,一旦模型表现得很差导致学习曲线不能收敛或者收敛到一个较差的位置,对应图中第一种和第二种情况,可以在早期做出判断并停止训练,即使用“提前停止”策略终止模型的训练,减少在不可能有良好表现的配置上浪费过多时间和资源,而将资源留给那些更有可能表现良好的超参数配置。“提前终止”不仅可以作为一种正则化策略,还可以在训练发生错误时,有效防止资源的浪费。学习曲线横轴通常出现的两个量: 迭代次数(Iterations)和遍历次数(Epochs)。其中,每一次迭代表示执行一次参数更新,而遍历次数指遍历原始训练集的次数。假设训练集有100个样本,使用小批量梯度下降算法进行参数更新,小批量的数目为10,那么每次迭代使用10个样本进行一次更新。当遍历完训练集的全部样本时,进行了10次迭代,1次遍历。实际上,由于训练数据有限,可能需要多次遍历训练集,例如设置遍历次数为5,那么当训练结束时,就进行了50次迭代。另外,有些文献中学习曲线的横轴变量表示时间,这也是可以的。 图537几种可能的学习曲线 图538不同学习率的效果 对于最重要的一个超参数——学习率,当时间和其他资源有限时,应当首先考虑对学习率进行调整。图538给出了不同学习率的表现效果,可以看到,设置合理的学习率可达到图中合适学习率曲线的效果,学习率过高或者过低都会导致学习曲线表现出不正常的趋势。 确定网络的超参数后,需要对网络进行初始化。如何保证初始化是合理的,不至于出现梯度消失或者神经元饱和的问题呢?可以通过监控网络所有层激活值和梯度分布的直方图来发现训练过程中神经元的饱和情况,一旦出现不好的分布,说明初始化不恰当,使得学习过程太慢或者停止了。传播梯度的快速增长或者快速消失,都会阻碍优化过程。 对网络进行合理的初始化后,便可以开始训练模型了。在对整个训练集进行正式训练之前,可以先尝试在一个比较小的训练集上进行训练,确保损失值能够达到0。训练过程中应跟踪权重更新比例,即每次迭代的所有参数的更新量与未更新前参数量之间的比例,也就是在一个小批量更新中参数的变化幅度。经验性的结论是这个比例应该为10-3左右,如果比例太低说明学习率可能太小,如果比例太高则说明学习率可能太大。也可以跟踪梯度的范式及其更新,通常可以得到相似的结果。另外,在训练过程中需要重点关注模型在验证集上的表现,通过定期对训练的模型在验证集上进行评估并绘出对应性能曲线,可以判断模型是否发生过拟合,并且可以根据两条曲线之间的距离判断过拟合的程度。如图539所示,与线②相比,线③说明模型发生更严重的过拟合现象。当模型发生过拟合时,就应当考虑加入正则化策略或者增大正则化的强度,或者使用集成学习,或者收集更多的训练数据,或者使用数据增强策略等。如果训练和测试误差都比较高,可能的原因是模型欠拟合,因此应当增加模型复杂度以提升模型容量。另外一个需要检验的是通过反向传播计算得到的梯度,这在前文提及过,可以通过将部分参数的解析梯度和数值梯度进行比较验证计算的正确性。 图539模型在验证集上的表现与过拟合现象 还有很多策略可以帮助监视训练过程中的行为,例如图像数据,可以通过特征可视化来判断模型的行为。在实践中遵循以上设计流程,并通过监视训练动态,可以帮助快速定位存在的问题,带来训练上的成功,获得高性能的模型。 本章小结 本章按照神经网络训练的流程,详细介绍了训练过程中的各种细节。对于神经网络的两个重要方面“优化”和“正则化”进行了重点介绍。其中,优化旨在尽可能地降低训练误差,要求最终训练的模型在训练集上表现良好。5.1节和5.2节所描述的优化算法,都是在最小化目标函数的过程中不断降低训练误差。而正则化则要求模型在测试集上表现良好,模型要具备良好的泛化能力,即要在未知的数据上具有良好的预测能力,5.4节介绍了相关的正则化策略。另外,网络参数的合理初始化对训练过程也至关重要,因此5.3节介绍了几种实践证明比较有效的初始化方法。最后,对于实际训练中常用的小技巧也做了简要介绍。阅读完本章,读者可自行设计一个简单的模型,尝试不同的优化策略、正则化策略、初始化方法等,感受不同方法的效果,实践可帮助读者进一步提升对相关知识的理解。