鱼书(深度学习入门):第六章 与学习相关的技巧
一、参数的更新
神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题,解决这个问题的过程称为最优化(optimization)。在前几章中我们引入了梯度,使用参数的梯度,沿梯度方向更新参数,并重复这个步骤多次,从而逐渐靠近最优参数,这个过程称为随机梯度下降法(stochastic gradient descent),简称SGD。但是除了SGD,之外,还有其他更聪明的方法。下面我们将指出SGD的缺点,并介绍SGD以外的其他最优化方法。
1.SGD与SGD的缺点
我们先复习一下SGD,其数学表达式和代码实现如下:

其中进行初始化时的参数lr表示learning rate(学习率),还定义了update(params, grads)方法,这个方法在SGD中会被反复调用。
在指出SGD的缺点之前,我们先考虑下面的最小值。

它的梯度如下图所示。

这个梯度的特征是,y轴方向上大,x轴方向上小。换句话说,就是y轴方向的坡度大,而x轴方向的坡度小。这里需要注意的是,虽然函数的最小值在(x, y) = (0, 0)处,但是图中的梯度在很多地方并没有指向(0, 0)。
如果我们对这个函数应用SGD,它的下降路径如下图所示。

在图中,SGD呈“之”字形移动。这是一个相当低效的路径。也就是说, SGD的缺点是,如果函数的形状非均向(anisotropic),比如呈延伸状,搜索的路径就会非常低效。因此,我们需要比单纯朝梯度方向前进的SGD更聪明的方法。SGD低效的根本原因是,梯度的方向并没有指向最小值的方向。
为了克服SGD的缺点,下面我们将介绍Momentum、AdaGrad、Adam这3种方法来取代SGD。
2.Momentum
Momentum是“动量”的意思,易知其和物理有关。其数学表达式如下:

这里新出现了一个变量v,对应物理上的速度。上面的式子表示了物体在梯度方向上受力,在这个力的作用下,物体的速度增加这一物理法则。Momentum方法给人的感觉就像是小球在 地面上滚动。上面的式子中有αv这一项。在物体不受任何力时,该项承担使物体逐渐减速的任务(α设定为0.9之类的值),对应物理上的地面摩擦或空气阻力。
下面是Momentum的代码实现:
使用Momentum解决上面的最优化问题,其路径如下图所示:

更新的路径就像小球在碗中滚动一样。和SGD相比,我们发现 “之”字形的“程度”减轻了。这是因为虽然x轴方向上受到的力非常小,但是一直在同一方向上受力,所以朝同一个方向会有一定的加速。同样的,虽然y轴方向上受到的力很大,但是因为交互地受到正方向和反方向的力,它 们会互相抵消,所以y轴方向上的速度不稳定。因此,和SGD时的情形相比, 可以更快地朝x轴方向靠近,减弱“之”字形的变动程度。
3.AdaGrad
在神经网络的学习中,学习率(数学式中记为η)的值很重要。学习率过小,会导致学习花费过多时间;反过来,学习率过大,则会导致学习发散而不能正确进行。在关于学习率的有效技巧中,有一种被称为学习率衰减(learning rate
decay)的方法,即随着学习的进行,使学习率逐渐减小。更进一步的,可以为各个参数逐渐调整学习率的值。
AdaGrad会为参数的每个元素适当地调整学习率,与此同时进行学习(AdaGrad的Ada来自英文单词Adaptive,即“适当的”的意思)。下面是AdaGrad的数学表达式。

这里新出现了变量h,如上式所示,它保存了以前的所有梯度值的平方和(上面的式子中的表示对应矩阵元素的乘法)。然后,在更新参数时,通过乘以
,就可以调整学习的尺度。这意味着,可以按参数的元素进行学习率衰减,使变动大的参数的学习率逐渐减小。
AdaGrad的代码实现如下所示。
这里需要注意的是,最后一行加上了微小值1e-7。这是为了防止当 self.h[key]中有0时,将0用作除数的情况。在很多深度学习的框架中,这个微小值也可以设定为参数,但这里我们用的是1e-7这个固定值。
使用AdaGrad实现上面的最优化问题,其路径如下图所示。

由上图的结果可知,函数的取值高效地向着最小值移动。由于y轴方向上的梯度较大,因此刚开始变动较大,但是后面会根据这个较大的变动按比例进行调整,减小更新的步伐。因此,y轴方向上的更新程度被减弱,“之”
字形的变动程度有所衰减。
此外,AdaGrad会记录过去所有梯度的平方和。因此,学习越深入,更新的幅度就越小。实际上,如果无止境地学习,更新量就会变为 0,完全不再更新。为了改善这个问题,可以使用 RMSProp方法。RMSProp方法并不是将过去所有的梯度一视同仁地相加,而是逐渐地遗忘过去的梯度,在做加法运算时将新梯度的信息更多地反映出来。
4.Adam
Momentum参照小球在碗中滚动的物理规则进行移动,AdaGrad为参数的每个元素适当地调整更新步伐。将这两个方法融合在一起就是Adam方法的基本思路。
它的理论有些复杂,直观地讲,就是融合了Momentum和AdaGrad的方法。通过组合前面两个方法的优点,有望实现参数空间的高效搜索。此外,进行超参数的“偏置校正”也是Adam的特征。 这里不再进行过多的说明。其搜索路径如下所示。

在上图中,基于Adam的更新过程就像小球在碗中滚动一样。虽然Momentun也有类似的移动,但是相比之下,Adam的小球左右摇晃的程度有所减轻。这得益于学习的更新程度被适当地调整了。
5.使用哪种更新方法呢
上面我们介绍了SGD、Momentum、AdaGrad、Adam这4种方法,那么用哪种方法好呢?非常遗憾,(目前)并不存在能在所有问题中都表现良好的方法。这4种方法各有各的特点,都有各自擅长解决的问题和不擅长解决的问题。很多研究中至今仍在使用SGD。Momentum和AdaGrad也是值得一试的方法。最近,很多研究人员和技术人员都喜欢用Adam。
二、权重的初始值
1.可以将权重初始值设为0吗
后面我们会介绍抑制过拟合、提高泛化能力的技巧——权值衰减(weight
decay)。简单地说,权值衰减就是一种以减小权重参数的值为目的进行学习的方法。通过减小权重参数的值来抑制过拟合的发生。
如果我们把权重初始值全部设为0以减小权重的值,会怎么样呢?从结论来说,将权重初始值设为0不是一个好主意。事实上,将权重初始值设为0的话,将无法正确进行学习。这是因为在误差反向传播法中,所有的权重值都会进行相同的更新。比如,在2层神经网络中,假设第1层和第2层的权重为0。这样一来,正向传播时,因为输入层的权重为0,所以第2层的神经元全部会被传递相同的值。第2层的神经元中全部输入相同的值,这意味着反向传播时第2层的权重全部都会进行相同的更新.因此,权重被更新为相同的值,并拥有了对称的值(重复的值)。这使得神经网络拥有许多不同的权重的意义丧失了。为了防止“权重均一化” (严格地讲,是为了瓦解权重的对称结构),必须随机生成初始值。
2.隐藏层的激活值的分布
我们先来做一个简单的实验,观察权重初始值是如何影响隐藏层的激活值的分布的。这里要做的实验是,向一个5层神经网络(激活函数使用
sigmoid函数)传入随机生成的输入数据,用直方图绘制各层激活值的数据分布。

从上图可知,各层的激活值呈偏向0和1的分布。这里使用的sigmoid函数是S型函数,随着输出不断地靠近0(或者靠近1),它的导数的值逐渐接近0。因此,偏向0和1的数据分布会造成反向传播中梯度的值不断变小,最后消失。这个问题称为梯度消失(gradient vanishing)。层次加深的深度学习中,梯度消失的问题可能会更加严重。
那我们将标准差改成0.01呢?

这次呈集中在0.5附近的分布。因为不像刚才的例子那样偏向0和1,所以不会发生梯度消失的问题。但是,激活值的分布有所偏向,说明在表现力上会有很大问题。为什么这么说呢?因为如果有多个神经元都输出几乎相同的值,那它们就没有存在的意义了。因此,激活值在分布上有所偏向会出现“表现力受限”的问题。
接着,我们尝试使用Xavier Glorot等人的论文中推荐的权重初始值(俗称“Xavier初始值”)。现在,在一般的深度学习框架中,Xavier初始值已被作为标准使用。Xavier的论文中,为了使各层的激活值呈现出具有相同广度的分布,推导了合适的权重尺度。推导出的结论是,如果前一层的节点数为n,则初始值使用标准差为的分布。如下图所示。

使用Xavier初始值后,前一层的节点数越多,要设定为目标节点的初始值的权重尺度就越小。使用Xavier初始值后的结果如下图所示。从这个结果可知,越是后面的层,图像变得越歪斜,但是呈现了比之前更有广度的分布。因为各层间传递的数据有适当的广度,所以sigmoid函数的表现力不受限制,有望进行高效的学习。

3.ReLU的权重初始值
Xavier初始值是以激活函数是线性函数为前提而推导出来的。因为sigmoid函数和tanh函数左右对称,且中央附近可以视作线性函数,所以适合使用Xavier初始值。但当激活函数使用ReLU时,一般推荐使用ReLU专用的初始值,也就是Kaiming He等人推荐的初始值,也称为“He初始值”。当前一层的节点数为n时,He初始值使用标准差为的高斯分布。当Xavier初始值是
时,(直观上)可以解释为,因为ReLU的负值区域的值为0,为了使它更有广度,所以需要2倍的系数。
使用不同初始值的结果如下图所示。

观察上面的结果可知,当“std = 0.01”(即标准差为0.01的高斯分布)时,各层的激活值非常小。神经网络上传递的是非常小的值,说明逆向传播时权重的梯度也同样很小。这是很严重的问题,实际上学习基本上没有进展。接下来是初始值为Xavier初始值时的结果。在这种情况下,随着层的加深, 偏向一点点变大。实际上,层加深后,激活值的偏向变大,学习时会出现梯度消失的问题。而当初始值为He初始值时,各层中分布的广度相同。由于即便层加深,数据的广度也能保持不变,因此逆向传播时,也会传递合适的值。
总结一下,当激活函数使用ReLU时,权重初始值使用He初始值,当激活函数为sigmoid或tanh等S型曲线函数时,初始值使用Xavier初始值。这是目前的最佳实践。
三、Batch Normalization
为了使各层拥有适当的广度,“强制性”地调整激活值的分布会怎样呢?实际上,Batch Normalization方法就是基于这个想法而产生的。
1.Batch Normalization 的算法
Batch Norm虽然是一个问世不久的新方法,但已经被很多研究人员和技术人员广泛使用。为什么Batch Norm这么惹人注目呢?因为Batch Norm有以下优点。1.可以使学习快速进行(可以增大学习率)。 2.不那么依赖初始值(对于初始值不用那么神经质)。3. 抑制过拟合(降低Dropout等的必要性)
如前所述,Batch Norm的思路是调整各层的激活值分布使其拥有适当的广度。为此,要向神经网络中插入对数据分布进行正规化的层,即Batch Normalization层(下文简称Batch Norm层),如下图所示。

Batch Norm,顾名思义,以进行学习时的mini-batch为单位,按mini-batch进行正规化。具体而言,就是进行使数据分布的均值为0、方差为1的正规化。用数学式表示的话,如下所示。

上式所做的是将mini-batch的输入数据{,
, ... ,
}变换为均值为0、方差为1的数据{
,
...
} ,非常简单。通过将这个处理插入到激活函数的前面(或者后面),可以减小数据分布的偏向。接着,Batch Norm层会对正规化后的数据进行缩放和平移的变换,用数学式可以如下表示。

这里,γ和β是参数。一开始γ = 1,β = 0,然后再通过学习调整到合适的值。上面就是Batch Norm的算法。这个算法是神经网络上的正向传播。如果使用第5章介绍的计算图,Batch Norm可以表示为下图。

Batch Norm的反向传播的推导有些复杂,这里我们不进行介绍。
2.Batch Normalization的评估
现在我们使用Batch Norm层进行实验。首先,使用MNIST数据集,观察使用Batch Norm层和不使用Batch Norm层时学习的过程会如何变化,结果如下图所示。

从上图的结果可知,使用Batch Norm后,学习进行得更快了。
接着, 给予不同的初始值尺度,观察学习的过程如何变化。下图是权重初始值的标准差为各种不同的值时的学习过程图。

的结果:图的标题处标明了权重初始值的标准差
我们发现,几乎所有的情况下都是使用Batch Norm时学习进行得更快。同时也可以发现,实际上,在不使用Batch Norm的情况下,如果不赋予一个尺度好的初始值,学习将完全无法进行。
综上,通过使用Batch Norm,可以推动学习的进行。并且,对权重初始值变得健壮(“对初始值健壮”表示不那么依赖初始值)。
四、正则化
机器学习的问题中,过拟合是一个很常见的问题。过拟合指的是只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态。机器学习的目标是提高泛化能力,即便是没有包含在训练数据里的未观测数据,
也希望模型可以进行正确的识别。
1.过拟合
发生过拟合的原因,主要有以下两个。1.模型拥有大量参数、表现力强。 2. 训练数据少。
这里,我们故意满足这两个条件,制造过拟合现象。为此,要从MNIST数据集原本的60000个训练数据中只选定300个,并且,为了增加网络的复杂度,使用7层网络(每层有100个神经元,激活函数为ReLU)。其结果如下所示。

过了 100 个 epoch 左右后,用训练数据测量到的识别精度几乎都为100%。但是,对于测试数据,离100%的识别精度还有较大的差距。如此大的识别精度差距,是只拟合了训练数据的结果。从图中可知,模型对训练时没有使用的一般数据(测试数据)拟合得不是很好。
2.权值衰减
权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。很多过拟合原本就是因为权重参数取值过大才发生的。
复习一下,神经网络的学习目的是减小损失函数的值。这时,例如为损失函数加上权重的平方范数(L2范数)。这样一来,就可以抑制权重变大。用符号表示的话,如果将权重记为W,L2范数的权值衰减就是,然
后将这个加到损失函数上。这里,λ是控制正则化强度的超参数。λ设置得越大,对大的权重施加的惩罚就越重。此外,
开头的
是用于将
的求导结果变成λW的调整用常量。
对于所有权重,权值衰减方法都会为损失函数加上 。因此,在求权重梯度的计算中,要为之前的误差反向传播法的结果加上正则化项的导数λW。
现在我们来进行实验。对于刚刚进行的实验,应用λ = 0.1的权值衰减,结果如下图所示。

如上图所示,虽然训练数据的识别精度和测试数据的识别精度之间有差距,但是与没有使用权值衰减的的结果相比,差距变小了。这说明过拟合受到了抑制。此外,还要注意,训练数据的识别精度没有达到100%(1.0)。
3.Dropout
权值衰减方法可以简单地实现,在某种程度上能够抑制过拟合。但是,如果网络的模型变得很复杂,只用权值衰减就难以应对了。在这种情况下,我们经常会使用Dropout方法。
Dropout是一种在学习的过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递。训练时,每传递一次数据,就会随机选择要删除的神经元。然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出, 要乘上训练时的删除比例后再输出。其结构如下图所示。

Dropout的网络。Dropout通过随机选择并删除神经元,停止向前传递信号
下面我们来实现Dropout。这里的实现重视易理解性。不过,因为训练时如果进行恰当的计算的话,正向传播时单纯地传递数据就可以了(不用乘以删除比例),所以深度学习的框架中进行了这样的实现。
这里的要点是,每次正向传播时,self.mask中都会以False的形式保存要删除的神经元。self.mask会随机生成和x形状相同的数组,并将值比dropout_ratio大的元素设为True。反向传播时的行为和ReLU相同。也就是说, 正向传播时传递了信号的神经元,反向传播时按原样传递信号;正向传播时没有传递信号的神经元,反向传播时信号将停在那里。
现在,我们使用MNIST数据集进行验证,以确认Dropout的效果。其结果如下图所示。

上图中,通过使用Dropout,训练数据和测试数据的识别精度的差距变小了。并且,训练数据也没有到达100%的识别精度。像这样,通过使用Dropout,即便是表现力强的网络,也可以抑制过拟合。
五、超参数的验证
神经网络中,除了权重和偏置等参数,超参数(hyper-parameter)也经常出现。这里所说的超参数是指,比如各层的神经元数量、batch大小、参数更新时的学习率或权值衰减等。如果这些超参数没有设置合适的值,模型的性能就会很差。虽然超参数的取值非常重要,但是在决定超参数的过程中
一般会伴随很多的试错。本节将介绍尽可能高效地寻找超参数的值的方法。
1.验证数据
之前我们使用的数据集分成了训练数据和测试数据,训练数据用于学习,测试数据用于评估泛化能力。由此,就可以评估是否只过度拟合了训练数据 (是否发生了过拟合),以及泛化能力如何等。
下面我们要对超参数设置各种各样的值以进行验证。这里要注意的是,不能使用测试数据评估超参数的性能。这一点非常重要,但也容易被忽视。这是因为如果使用测试数据调整超参数,超参数的值会对测试数据发生过拟合。换句话说,用测试数据确认超参数的值的“好坏”,就会导致超参数的值被调整为只拟合测试数据。 这样的话,可能就会得到不能拟合其他数据、泛化能力低的模型。
因此,调整超参数时,必须使用超参数专用的确认数据。用于调整超参数的数据,一般称为验证数据(validation data)。我们使用这个验证数据来评估超参数的好坏。
根据不同的数据集,有的会事先分成训练数据、验证数据、测试数据三部分,有的只分成训练数据和测试数据两部分,有的则不进行分割。在这种情况下,用户需要自行进行分割。接下来,我们使用验证数据观察超参数的最优化方法。
2.超参数的最优化
进行超参数的最优化时,逐渐缩小超参数的“好值”的存在范围非常重要。所谓逐渐缩小范围,是指一开始先大致设定一个范围,从这个范围中随机选出一个超参数(采样),用这个采样到的值进行识别精度的评估;然后,多次重复该操作,观察识别精度的结果,根据这个结果缩小超参数的“好值”的范围。通过重复这一操作,就可以逐渐确定超参数的合适范围。
超参数的范围只要“大致地指定”就可以了。所谓“大致地指定”,是指以“10的阶乘”的尺度指定范围。在超参数的搜索中,需要尽早放弃那些不符合逻辑的超参数。于是,在超参数的最优化中,减少学习的epoch,缩短一次评估所需的时间是一个不错的办法。
以上就是超参数的最优化的内容,简单归纳一下,如下所示。
步骤0设定超参数的范围。
步骤1从设定的超参数范围中随机采样。
步骤2使用步骤1中采样到的超参数的值进行学习,通过验证数据评估识别精度(但是要将epoch设置得很小)。
步骤3重复步骤1和步骤2(100次等),根据它们的识别精度的结果,缩小超参数的范围。
反复进行上述操作,不断缩小超参数的范围,在缩小到一定程度时,从该范围中选出一个超参数的值。这就是进行超参数的最优化的一种方法。
在超参数的最优化中,如果需要更精炼的方法,可以使用贝叶斯最优化(Bayesian optimization)。
3.超参数最优化的实现
现在,我们使用MNIST数据集进行超参数的最优化。这里我们将学习率和控制权值衰减强度的系数(下文称为“权值衰减系数”)这两个超参数的搜索问题作为对象。
在该实验中,权值衰减系数的初始范围为10−8到10−4,学习率的初始范围为10−6到10−2。此时,超参数的随机采样的代码如下所示。
像这样进行随机采样后,再使用那些值进行学习。之后,多次使用各种超参数的值重复进行学习,观察合乎逻辑的超参数在哪里。这里省略了具体实现,只列出了结果。结果如下图所示。

上图中,按识别精度从高到低的顺序排列了验证数据的学习的变化。 从图中可知,直到“Best-5”左右,学习进行得都很顺利。因此,我们来观察一下“Best-5”之前的超参数的值(学习率和权值衰减系数),结果如下所示。

从这个结果可以看出,学习率在0.001到0.01、权值衰减系数在10−8 到 10−6 之间时,学习可以顺利进行。像这样,观察可以使学习顺利进行的超参数的范围,从而缩小值的范围。然后,在这个缩小的范围中重复相同的操作。这样就能缩小到合适的超参数的存在范围,然后在某个阶段,选择一个最终的超参数的值。