深度学习_吴恩达_Part_2

第四章 深层神经网络

上节主要介绍了浅层神经网络。首先介绍神经网络的基本结构,包括输入层,隐藏层和输出层。然后以简单的2 layer NN为例,详细推导了其正向传播过程和反向传播过程,使用梯度下降的方法优化神经网络参数。我们还介绍了不同的激活函数,比较各自优缺点,讨论了激活函数必须是非线性的原因。最后介绍了神经网络参数随机初始化的必要性,特别是权重,不同神经元的不能初始化为同一零值。本节课是对上节课的延伸和扩展,讨论更深层的神经网络。

4.1 深层神经网络概述

深层神经网络其实就是包含更多的隐藏层神经网络。如下图所示,分别列举了逻辑回归、1个隐藏层的神经网络、2个隐藏层的神经网络和5个隐藏层的神经网络它们的模型结构。

命名规则上,一般只参考隐藏层个数和输出层。例如,上图中的逻辑回归又叫1 layer NN,1个隐藏层的神经网络叫做2 layer NN,2个隐藏层的神经网络叫做3 layer NN,以此类推。如果是L-layer NN,则包含了L-1个隐藏层,最后的L层是输出层。

下面以一个4层神经网络为例来介绍关于神经网络的一些标记写法。如图30所示。

  • 总层数:用表示,。输入层是第层,输出层是第层。
  • 表示第层包含的单元个数,。这个模型中,,表示三个输入特征
  • 层的激活函数输出用表示,
  • 表示第层的权重,用于计算z[l]。
    另外,我们把输入记为,把输出层记为

注意,中的上标都是从开始的,

4.2 深层神经网络中的前向传播

对于第层,其正向传播过程的可以表示为:

其中,

4.3 核对矩阵的维数

对于单个训练样本,输入的维度是神经网络的参数的维度分别是:

其中,分别表示第层和层的所含单元个数。,表示输入层特征数目。

顺便提一下,反向传播过程中的的维度和维度相同

正向传播过程中的的维度分别是:

$z^{[l]}$和$a^{[l]}$的维度是一样的,且$\mathrm dz^{[l]}$和$\mathrm da^{[l]}$的维度均与$z^{[l]}$和$a^{[l]}$的维度一致。

对于$m$个训练样本,输入矩阵$X$的维度是$(n^{[0]},m)$。需要注意的是$W^{[l]}$和$b^{[l]}$的维度与只有单个样本是一致的:

只不过在运算$Z^{[l]}=W^{[l]}A^{[l−1]}+b^{[l]}$中,$b^{[l]}$会被当成$(n^{[l]},m)$矩阵进行运算,这是因为python的广播性质,且$b^{[l]}$每一列向量都是一样的。$\mathrm dW^{[l]}$和$\mathrm db^{[l]}$的维度分别与$W$和$b$的相同。但是,$Z^{[l]}$和$A^{[l]}$的维度发生了变化:

$\mathrm dZ^{[l]}$和$\mathrm dA^{[l]}$的维度分别与$Z^{[l]}$和$A^{[l]}$的相同。

4.4 为什么使用深层表示

神经网络能处理很多问题,而且效果显著。其强大能力主要源自神经网络足够“深”,也就是说网络层数越多,神经网络就更加复杂和深入,学习也更加准确。接下来,我们从几个例子入手,看一下为什么深度网络能够如此强大。

先来看人脸识别的例子,如下图所示。经过训练,神经网络第一层所做的事就是从原始图片中提取出人脸的轮廓与边缘,即边缘检测。这样每个神经元得到的是一些边缘信息。神经网络第二层所做的事情就是将前一层的边缘进行组合,组合成人脸一些局部特征,比如眼睛、鼻子、嘴巴等。再往后面,就将这些局部特征组合起来,融合成人脸的模样。可以看出,随着层数由浅到深,神经网络提取的特征也是从边缘到局部特征到整体,由简单到复杂。可见,如果隐藏层足够多,那么能够提取的特征就越丰富、越复杂,模型的准确率就会越高。

语音识别模型也是这个道理。浅层的神经元能够检测一些简单的音调,然后较深的神经元能够检测出基本的音素,更深的神经元就能够检测出单词信息。如果网络够深,还能对短语、句子进行检测。记住一点,神经网络从左到右,神经元提取的特征从简单到复杂。特征复杂度与神经网络层数成正相关。特征越来越复杂,功能也越来越强大

除了从提取特征复杂度的角度来说明深层网络的优势之外,深层网络还有另外一个优点,就是能够减少神经元个数,从而减少计算量。例如下面这个例子,使用电路理论,计算逻辑输出:

其中,⊕表示异或操作。对于这个逻辑运算,如果使用深度网络,深度网络的结构是每层将前一层的两两单元进行异或,最后到一个输出,如下图左边所示。这样,整个深度网络的层数是,不包含输入层。总共使用的神经元个数为:

可见,输入个数是$n$,这种深层网络所需的神经元个数仅仅是$n-1$个。

如果不用深层网络,仅仅使用单个隐藏层,那么需要的神经元个数将是指数级别那么大。Andrew指出,由于包含了所有的逻辑位(0和1),则需要$2^{n−1}$个神经元。这里笔者推导的是$2^n$个神经元,为啥是$2^{n−1}$请哪位高手解释下。

比较下来,处理同一逻辑问题,深层网络所需的神经元个数比浅层网络要少很多。这也是深层神经网络的优点之一。

尽管深度学习有着非常显著的优势,Andrew还是建议对实际问题进行建模时,尽量先选择层数少的神经网络模型,这也符合奥卡姆剃刀定律(Occam’s Razor)。对于比较复杂的问题,再使用较深的神经网络模型。

4.5 搭建深层神经网络模块

下面用流程块图来解释神经网络正向传播和反向传播过程。如下图所示,对于第层来说,正向传播过程中:

正向传播 反向传播
输入 $a^{[l-1]}$ $\mathrm da^{[l]}$
输出 $a^{[l]}$ $\mathrm da^{[l-1]}, \mathrm dW^{[l]}, \mathrm db^{[l]}$
参数 $W^{[l]},b^{[l]}$ $W^{[l]},b^{[l]}$
缓存变量 $z^{[l]}$

刚才这是第$l$层的流程块图,对于神经网络所有层,整体的流程块图正向传播过程和反向传播过程如下所示:

4.6 前向和反向传播

接着上一部分流程块图的内容,推导神经网络正向传播过程和反向传播过程的具体表达式。首先是正向传播过程,令层数为第$l$层,输入是$a^{[l−1]}$,输出是$a^{[l]}$,缓存变量是$z^{[l]}$。其表达式如下:

$m$个训练样本,向量化形式为:

然后是反向传播过程,输入是$\mathrm da^{[l]}$,输出是$\mathrm da^{[l−1]}, \mathrm dw^{[l]}, \mathrm db^{[l]}$。其表达式如下:

由上述第四个表达式可得$\mathrm da^{[l]}=W^{[l+1]T}⋅\mathrm dz^{[l+1]}​$,将$\mathrm da^{[l]}​$代入第一个表达式中可以得到:

该式非常重要,反映了$\mathrm dz^{[l+1]}$与$\mathrm dz^{[l]}$的递推关系。

$m$个训练样本,向量化形式为:

4.7 参数 VS超参数

该部分介绍神经网络中的参数(parameters)和超参数(hyperparameters)的概念。

神经网络中的参数就是我们熟悉的。而超参数则是例如学习速率,训练迭代次数,神经网络层数,各层神经元个数,激活函数等。之所以叫做超参数的原因是它们决定了参数的值。在后面的第二门课我们还将学习其它的超参数,这里先不讨论。

如何设置最优的超参数是一个比较困难的、需要经验知识的问题。通常的做法是选择超参数一定范围内的值,分别代入神经网络进行训练,测试cost function随着迭代次数增加的变化,根据结果选择cost function最小时对应的超参数值。这类似于validation的方法。

第五章 深度学习的实用层面

5.1 训练-验证-测试集

选择最佳的训练集(Training sets)验证集(Development sets)测试集(Test sets)对神经网络的性能影响非常重要。除此之外,在构建一个神经网络的时候,需要设置许多参数,例如神经网络的层数、每个隐藏层包含的神经元个数、学习因子(学习速率)、激活函数的选择等等。实际上很难在第一次设置的时候就选择到这些最佳的参数,而是需要通过不断地迭代更新来获得。这个循环迭代的过程是这样的:

(1) 先有个想法Idea,先选择初始的参数值,构建神经网络模型结构;

(2) 然后通过代码Code的形式,实现这个神经网络;

(3) 最后通过实验Experiment验证这些参数对应的神经网络的表现性能。

根据验证结果,我们对参数进行适当的调整优化,再进行下一次的Idea->Code->Experiment循环。通过很多次的循环,不断调整参数,选定最佳的参数值,从而让神经网络性能最优化。

一般地,我们将所有的样本数据分成三个部分:Train/Dev/Test sets。Train sets用来训练你的算法模型;Dev sets用来验证不同算法的表现情况,从中选择最好的算法模型;Test sets用来测试最好算法的实际表现,作为该算法的无偏估计。

之前人们通常设置Train sets和Test sets的数量比例为70%和30%。如果有Dev sets,则设置比例为60%、20%、20%,分别对应Train/Dev/Test sets。这种比例分配在样本数量不是很大的情况下,例如100,1000,10000,是比较科学的。但是如果数据量很大的时候,例如100万,科学的做法是要将Dev sets和Test sets的比例设置得很低。因为Dev sets的目标是用来比较验证不同算法的优劣,从而选择更好的算法模型就行了。因此,对于大数据样本,Train/Dev/Test sets的比例通常可以设置为98%/1%/1%,或者99%/0.5%/0.5%。样本数据量越大,相应的Dev/Test sets的比例可以设置的越低一些。

现代深度学习还有个重要的问题就是训练样本和测试样本分布上不匹配,意思是训练样本和测试样本来自于不同的分布。解决这一问题的比较科学的办法是尽量保证Dev sets和Test sets来自于同一分布。值得一提的是,训练样本非常重要,通常我们可以将现有的训练样本做一些处理,例如图片的翻转、假如随机噪声等,来扩大训练样本的数量,从而让该模型更加强大。即使Train sets和Dev/Test sets不来自同一分布,使用这些技巧也能提高模型性能。

最后提一点的是如果没有Test sets也是没有问题的。Test sets的目标主要是进行无偏估计。我们可以通过Train sets训练不同的算法模型,然后分别在Dev sets上进行验证,根据结果选择最好的算法模型。这样也是可以的,不需要再进行无偏估计了。如果只有Train sets和Dev sets,通常也有人把这里的Dev sets称为Test sets,我们要注意加以区别。

5.2 偏差和方差

偏差(bias)和方差(Variance)是机器学习领域非常重要的两个概念和需要解决的问题。在传统的机器学习算法中,Bias和Variance是对立的,分别对应着欠拟合和过拟合,我们常常需要在Bias和Variance之间进行权衡。而在深度学习中,我们可以同时减小Bias和Variance,构建最佳神经网络模型。

如下图所示,显示了二维平面上,high bias,just right,high variance的例子。可见,high bias对应着欠拟合,而high variance对应着过拟合。

上图这个例子中输入特征是二维的,high bias和high variance可以直接从图中分类线看出来。而对于输入特征是高维的情况,如何来判断是否出现了high bias或者high variance呢?

例如猫识别问题,输入是一幅图像,其特征维度很大。这种情况下,我们可以通过两个数值Train set errorDev set error来理解bias和variance。

(1) 假设Train set error为1%,而Dev set error为11%,即该算法模型对训练样本的识别很好,但是对验证集的识别却不太好。这说明了该模型对训练样本可能存在过拟合,模型泛化能力不强,导致验证集识别率低。这恰恰是high variance的表现。

(2) 假设Train set error为15%,而Dev set error为16%,虽然二者error接近,即该算法模型对训练样本和验证集的识别都不是太好。这说明了该模型对训练样本存在欠拟合。这恰恰是high bias的表现。

(3) 假设Train set error为15%,而Dev set error为30%,说明了该模型既存在high bias也存在high variance(深度学习中最坏的情况)。

(4) 假设Train set error为0.5%,而Dev set error为1%,即low bias和low variance,是最好的情况。

值得一提的是,以上的这些假设都是建立在base error是0的基础上,即人类都能正确识别所有猫类图片。base error不同,相应的Train set error和Dev set error会有所变化,但没有相对变化。

一般来说,Train set error体现了是否出现bias,Dev set error体现了是否出现variance(正确地说,应该是Dev set error与Train set error的相对差值)。

我们已经通过二维平面展示了high bias或者high variance的模型,下图展示了high bias and high variance的模型:

模型既存在high bias也存在high variance,可以理解成某段区域是欠拟合的,某段区域是过拟合的。

5.3 机器学习基础

机器学习中基本的一个诀窍就是避免出现high bias和high variance

这里有几点需要注意的。

第一,解决high bias和high variance的方法是不同的。实际应用中通过Train set error和Dev set error判断是否出现了high bias或者high variance,然后再选择针对性的方法解决问题。

第二,Bias和Variance的折中tradeoff。传统机器学习算法中,Bias和Variance通常是对立的,减小Bias会增加Variance,减小Variance会增加Bias。而在现在的深度学习中,通过使用更复杂的神经网络和海量的训练样本,一般能够同时有效减小Bias和Variance。这也是深度学习之所以如此强大的原因之一。

5.4 正则化

如果出现了过拟合,即high variance,则需要采用正则化regularization来解决。虽然扩大训练样本数量也是减小high variance的一种方法,但是通常获得更多训练样本的成本太高,比较困难。所以,更可行有效的办法就是使用regularization。

回顾一下之前介绍的Logistic regression。采用L2 regularization,其表达式为:

这里有个问题:为什么只对w进行正则化而不对b进行正则化呢?其实也可以对b进行正则化。但是一般w的维度很大,而b只是一个常数。相比较来说,参数很大程度上由w决定,改变b值对整体模型影响较小。所以,一般为了简便,就忽略对b的正则化了。
除了L2 regularization之外,还有另外一只正则化方法:L1 regularization。其表达式为:

与L2 regularization相比,L1 regularization得到的更加稀疏,即很多为零值,所以其优点是节约存储空间。但实际L1 regularization在解决high variance方面比L2 regularization并不更具优势。而且L1的在微分求导方面比较复杂。所以,一般L2 regularization更加常用。

L1、L2 regularization中的λ就是正则化参数(超参数的一种)。可以设置λ为不同的值,在Dev set中进行验证,选择最佳的λ。顺便提一下,在python中,由于lambda是保留字,所以为了避免冲突,我们使用lambd来表示λ。

在深度学习模型中,L2 regularization的表达式为:

通常,我们把称为Frobenius范数,记为。一个矩阵的Frobenius范数就是计算所有元素平方和再开方,如下所示:

值得注意的是,由于加入了正则化项,梯度下降算法中的计算表达式需要做如下修改:

L2 regularization也被称做权重衰减(weight decay)。这是因为,由于加上了正则项,有个增量,在更新的时候,会多减去这个增量,使得比没有正则项的值要小一些。不断迭代更新,不断地减小。

其中,

5.5 为什么正则化可以减少过拟合

为什么正则化能够有效避免high variance,防止过拟合呢?下面通过几个例子说明。

还是之前那张图,从左到右,分别表示了欠拟合,刚好拟合,过拟合三种情况。

假如我们选择了非常复杂的神经网络模型,如上图左上角所示。在未使用正则化的情况下,我们得到的分类超平面可能是类似上图右侧的过拟合。但是,如果使用L2 regularization,当λ很大时,意味着该神经网络模型中的某些神经元实际的作用很小,可以忽略。从效果上来看,其实是将某些神经元给忽略掉了。这样原本过于复杂的神经网络模型就变得不那么复杂了,而变得非常简单化了。如下图所示,整个简化的神经网络模型变成了一个逻辑回归模型。问题就从high variance变成了high bias了。

因此,选择合适大小的值,就能够同时避免high bias和high variance,得到最佳模型。

还有另外一个直观的例子来解释为什么正则化能够避免发生过拟合。假设激活函数是tanh函数。tanh函数的特点是在接近零的区域,函数近似是线性的,而当很大的时候,函数非线性且变化缓慢。当使用正则化,较大,即对权重惩罚较大减小。因为。当减小的时候,也会减小。则此时的分布在tanh函数的近似线性区域。那么这个神经元起的作用就相当于是linear regression。如果每个神经元对应的权重都比较小,那么整个神经网络模型相当于是多个linear regression的组合,即可看成一个linear network。得到的分类超平面就会比较简单,不会出现过拟合现象。

5.6 Dropout 正则化

除了L2 regularization之外,还有另外一种防止过拟合的有效方法:Dropout。

Dropout是指在深度学习网络的训练过程中,对于每层的神经元,按照一定的概率将其暂时从网络中丢弃。也就是说,每次训练时,每一层都有部分神经元不工作,起到简化复杂网络模型的效果,从而避免发生过拟合。

Dropout有不同的实现方法,接下来介绍一种常用的方法:Inverted dropout。假设对于第层神经元,设定保留神经元比例概率keep_prob=0.8,即该层有20%的神经元停止工作。为dropout向量,设置为随机vector,其中80%的元素为1,20%的元素为0。在python中可以使用如下语句生成dropout vector:

1
dl = np.random.rand(al.shape[0],al.shape[1])<keep_prob

然后,第层经过dropout,随机删减20%的神经元,只保留80%的神经元,其输出为:

1
al = np.multiply(al,dl)

最后,还要对进行scale up处理,即:

1
al /= keep_prob

以上就是Inverted dropout的方法。之所以要对进行scale up是为了保证在经过dropout后,作为下一层神经元的输入值尽量保持不变。假设第层有50个神经元,经过dropout后,有10个神经元停止工作,这样只有40神经元有作用。那么得到的只相当于原来的80%。scale up后,能够尽可能保持的期望值相比之前没有大的变化。

Inverted dropout的另外一个好处就是在对该dropout后的神经网络进行测试时能够减少scaling问题。因为在训练时,使用scale up保证的期望值没有大的变化,测试时就不需要再对样本数据进行类似的尺度伸缩操作了。

对于个样本,单次迭代训练时,随机删除掉隐藏层一定数量的神经元;然后,在删除后的剩下的神经元上正向和反向更新权重w和常数项b;接着,下一次迭代中,再恢复之前删除的神经元,重新随机删除一定数量的神经元,进行正向和反向更新w和b。不断重复上述过程,直至迭代训练完成。

值得注意的是,使用dropout训练结束后,在测试和实际应用模型时,不需要进行dropout和随机删减神经元,所有的神经元都在工作。

5.7 理解Dropout

Dropout通过每次迭代训练时,随机选择不同的神经元,相当于每次都在不同的神经网络上进行训练,类似机器学习中Bagging的方法(三个臭皮匠,赛过诸葛亮),能够防止过拟合。

除此之外,还可以从权重的角度来解释为什么dropout能够有效防止过拟合。对于某个神经元来说,某次训练时,它的某些输入在dropout的作用被过滤了。而在下一次训练时,又有不同的某些输入被过滤。经过多次训练后,某些输入被过滤,某些输入被保留。这样,该神经元就不会受某个输入非常大的影响,影响被均匀化了。也就是说,对应的权重不会很大。这从从效果上来说,与L2 regularization是类似的,都是对权重进行“惩罚”,减小了的值。

总结一下,对于同一组训练数据,利用不同的神经网络训练之后,求其输出的平均值可以减少overfitting。Dropout就是利用这个原理,每次丢掉一定数量的隐藏层神经元,相当于在不同的神经网络上进行训练,这样就减少了神经元之间的依赖性,即每个神经元不能依赖于某几个其他的神经元(指层与层之间相连接的神经元),使神经网络更加能学习到与其他神经元之间的更加健壮robust的特征。

在使用dropout的时候,有几点需要注意。

(1) 不同隐藏层的dropout系数keep_prob可以不同。一般来说,神经元越多的隐藏层,keep_out可以设置得小一些,例如0.5;神经元越少的隐藏层,keep_out可以设置的大一些,例如0.8,设置是1。

(2) 实际应用中,不建议对输入层进行dropout,如果输入层维度很大,例如图片,那么可以设置dropout,但keep_out应设置的大一些,例如0.8,0.9。

总体来说,就是越容易出现overfitting的隐藏层,其keep_prob就设置的相对小一些。没有准确固定的做法,通常可以根据validation进行选择。

Dropout在电脑视觉CV领域应用比较广泛,因为输入层维度较大,而且没有足够多的样本数量。值得注意的是dropout是一种regularization技巧,用来防止过拟合的,最好只在需要regularization的时候使用dropout。

使用dropout的时候,可以通过绘制cost function来进行debug,看看dropout是否正确执行。一般做法是,将所有层的keep_prob全设置为1,再绘制cost function,即涵盖所有神经元,看是否单调下降。下一次迭代训练时,再将keep_prob设置为其它值。

5.8 其他正则化方法

除了L2 regularization和dropout regularization之外,还有其它减少过拟合的方法。

  • 增加训练样本数量
    但是通常成本较高,难以获得额外的训练样本。但是,我们可以对已有的训练样本进行一些处理来“制造”出更多的样本,称为data augmentation。例如图片识别问题中,可以对已有的图片进行水平翻转、垂直翻转、任意角度旋转、缩放或扩大等等。如下图所示,这些处理都能“制造”出新的训练样本。虽然这些是基于原有样本的,但是对增大训练样本数量还是有很有帮助的,不需要增加额外成本,却能起到防止过拟合的效果。

在数字识别中,也可以将原有的数字图片进行任意旋转或者扭曲,或者增加一些noise,如下图所示:

  • early stopping

    一个神经网络模型随着迭代训练次数增加,train set error一般是单调减小的,而dev set error 先减小,之后又增大。也就是说训练次数过多时,模型会对训练样本拟合的越来越好,但是对验证集拟合效果逐渐变差,即发生了过拟合。因此,迭代训练次数不是越多越好,可以通过train set error和dev set error随着迭代次数的变化趋势,选择合适的迭代次数,即early stopping。

然而,Early stopping有其自身缺点。通常来说,机器学习训练模型有两个目标:

一是优化cost function,尽量减小

二是防止过拟合。

这两个目标彼此对立的,即减小的同时可能会造成过拟合,反之亦然。我们把这二者之间的关系称为正交化(orthogonalization)。该节课开始部分就讲过,在深度学习中,我们可以同时减小Bias和Variance,构建最佳神经网络模型。但是,Early stopping的做法通过减少得带训练次数来防止过拟合,这样就不会足够小。也就是说,early stopping将上述两个目标融合在一起,同时优化,但可能没有“分而治之”的效果好。

与early stopping相比,L2 regularization可以实现“分而治之”的效果:迭代训练足够多,减小,而且也能有效防止过拟合。而L2 regularization的缺点之一是最优的正则化参数的选择比较复杂。对这一点来说,early stopping比较简单。总的来说,L2 regularization更加常用一些。

5.9 归一化输入

在训练神经网络时,标准化输入可以提高训练的速度。标准化输入就是对训练数据集进行归一化的操作,即将原始数据减去其均值后,再除以其方差

以二维平面为例,下图展示了其归一化过程:

值得注意的是,由于训练集进行了标准化处理,那么对于测试集或在实际应用时,应该使用同样的对其进行标准化处理。这样保证了训练集合测试集的标准化操作一致。

之所以要对输入进行标准化操作,主要是为了让所有输入归一化同样的尺度上,方便进行梯度下降算法时能够更快更准确地找到全局最优解。假如输入特征是二维的,且的范围是的范围是。如果不进行标准化处理,之间分布极不平衡,训练得到的也会在数量级上差别很大。这样导致的结果是cost function与的关系可能是一个非常细长的椭圆形碗。对其进行梯度下降算法时,由于数值差异很大,只能选择很小的学习因子,来避免发生振荡。一旦较大,必然发生振荡,不再单调下降。如下左图所示。

然而,如果进行了标准化操作,分布均匀,数值差别不大,得到的cost function与的关系是类似圆形碗。对其进行梯度下降算法时,可以选择相对大一些,且一般不会发生振荡,保证了是单调下降的。如下右图所示。

另外一种情况,如果输入特征之间的范围本来就比较接近,那么不进行标准化操作也是没有太大影响的。但是,标准化处理在大多数场合下还是值得推荐的。

本小节参考链接:标准化和归一化的区别

5.10 梯度消失与梯度爆炸

在神经网络尤其是深度神经网络中存在可能存在这样一个问题:梯度消失和梯度爆炸。意思是当训练一个层数非常多的神经网络时,计算得到的梯度可能非常小或非常大,甚至是指数级别的减小或增大。这样会让训练过程变得非常困难。

举个例子来说明,假设一个多层的每层只包含两个神经元的深度神经网络模型,如下图所示:

为了简化复杂度便于分析,我们令各层的激活函数为线性函数,即。且忽略各层常数项的影响,令全部为零。那么,该网络的预测输出为:

如果各层权重的元素都稍大于,例如,则预测输出将正比于越大,越大,且呈指数型增长。我们称之为数值爆炸。相反,如果各层权重的元素都稍小于,例如,则预测输出将正比于。网络层数越多,呈指数型减小。我们称之为数值消失。

也就是说,如果各层权重都大于或者都小于,那么各层激活函数的输出将随着层数的增加,呈指数型增大或减小。当层数很大时,出现数值爆炸或消失。同样,这种情况也会引起梯度呈现同样的指数型增大或减小的变化。非常大时,例如,则梯度会非常大或非常小,引起每次更新的步进长度过大或者过小,这让训练过程十分困难。

5.11 神经网络的初始化权重

下面介绍如何改善Vanishing and Exploding gradients这类问题,方法是对权重进行一些初始化处理。

深度神经网络模型中,以单个神经元为例,该层()的输入个数为,其输出为:

这里忽略了常数项。为了让不会过大或者过小,由上面的式子可以有思路是有关,且越大,应该越小才好。这样能够保证不会过大。一种方法是在初始化时,控制的方差。

(1) 如果激活函数是tanh,方差为;

1
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(1/n[l-1])

(2) 如果激活函数是ReLU,方差为

1
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(2/n[l-1])

除此之外,Yoshua Bengio提出了另外一种初始化w的方法,令其方差为

1
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(2/n[l-1]*n[l])

至于选择哪种初始化方法因人而异,可以根据不同的激活函数选择不同方法。另外,我们可以对这些初始化方法中设置某些参数,作为超参数,通过验证集进行验证,得到最优参数,来优化神经网络。

5.12 梯度的数值逼近

Back Propagation神经网络有一项重要的测试是梯度检查(gradient checking)。其目的是检查验证反向传播过程中梯度下降算法是否正确。该小节将先介绍如何近似求出梯度值。

利用微分思想,函数在点处的梯度可以表示成:

其中,且足够小。

5.13 梯度检验

介绍完如何近似求出梯度值后,我们将介绍如何进行梯度检查,来验证训练过程中是否出现bugs。

梯度检查首先要做的是分别将这些矩阵构造成一维向量,然后将这些一维向量组合起来构成一个更大的一维向量,这样cost function就可以表示成

然后将反向传播过程通过梯度下降算法得到的按照一样的顺序构造成一个一维向量(与维度相同)。

接着利用对每个计算近似梯度,其值与反向传播算法得到的相比较,检查是否一致。例如,对于第个元素,近似梯度为:

计算完所有的近似梯度后,可以计算欧氏(Euclidean)距离来比较二者的相似度。公式如下:

一般来说,若欧氏距离越小,例如甚至更小,则表明越接近,即反向梯度计算是正确的,没有bugs。若欧氏距离较大,例如,则表明梯度计算可能出现问题,需要再次检查是否有bugs存在。若欧氏距离很大,例如,甚至更大,则表明差别很大,梯度下降计算过程有bugs,需要仔细检查。

5.14 关于梯度检验实现的注记

在进行梯度检查的过程中有几点需要注意的地方:

  • 不要在整个训练过程中都进行梯度检查,仅仅作为debug使用。
  • 如果梯度检查出现错误,找到对应出错的梯度,检查其推导是否出现错误。
  • 注意不要忽略正则化项,计算近似梯度的时候要包括进去。
  • 梯度检查时关闭dropout,检查完毕后再打开dropout。
  • 随机初始化时运行梯度检查,经过一些训练后再进行梯度检查(不常用)。

第六章 优化算法

6.1 Mini-batch 梯度下降法

之前介绍的神经网络训练过程是对所有个样本,称为batch,通过向量化计算方式,同时进行的。如果很大,例如达到百万数量级,训练速度往往会很慢,因为每次迭代都要对所有样本进行进行求和运算和矩阵运算。我们将这种梯度下降算法称为Batch Gradient Descent

为了解决这一问题,我们可以把个训练样本分成若干个子集,称为mini-batches,这样每个子集包含的数据量就小了,例如只有1000,然后每次在单一子集上进行神经网络训练,速度就会大大提高。这种梯度下降算法叫做Mini-batch Gradient Descent

假设总的训练样本个数,其维度为。将其分成个子集,每个mini-batch含有个样本。我们将每个mini-batch记为,其维度为。相应的每个mini-batch的输出记为,其维度为,且

这里顺便总结一下我们遇到的神经网络中几类字母的上标含义:

  • $X^{(i)}$:第$i$个样本
  • $Z^{[l]}$:神经网络第$l$层网络的线性输出
  • $X^{\{t\}},Y^{\{t\}}$:第$t$组mini-batch

ini-batches Gradient Descent的实现过程是先将总的训练样本分成个子集(mini-batches),然后对每个mini-batch进行神经网络训练,包括Forward Propagation,Compute Cost Function,Backward Propagation,循环至个mini-batch都训练完毕。

经过次循环之后,所有个训练样本都进行了梯度下降计算。这个过程,我们称之为经历了一个epoch。对于Batch Gradient Descent而言,一个epoch只进行一次梯度下降算法;而Mini-Batches Gradient Descent,一个epoch会进行次梯度下降算法。

值得一提的是,对于Mini-Batches Gradient Descent,可以进行多次epoch训练。而且,每次epoch,最好是将总体训练数据重新打乱重新分成mini-batches,这样有利于训练出最佳的神经网络模型。

6.2 理解Mini-batch 梯度下降法

Batch gradient descent和Mini-batch gradient descent的cost曲线如下图所示:

对于一般的神经网络模型,使用Batch gradient descent,随着迭代次数增加,cost是不断减小的。然而,使用Mini-batch gradient descent,随着在不同的mini-batch上迭代训练,其cost不是单调下降,而是受类似noise的影响,出现振荡。但整体的趋势是下降的,最终也能得到较低的cost值。

之所以出现细微振荡的原因是不同的mini-batch之间是有差异的。例如可能第一个子集是好的子集,而第二个子集包含了一些噪声noise。出现细微振荡是正常的。

如何选择每个mini-batch的大小,即包含的样本个数呢?有两个极端:

(1) 如果mini-batch size=m,即为Batch gradient descent,只包含一个子集为

(2) 如果mini-batch size=1,即为Stachastic gradient descent,每个样本就是一个子集,共有个子集。

我们来比较一下Batch gradient descent和Stachastic gradient descent的梯度下降曲线。如下图所示,蓝线代表Batch gradient descent,紫线代表Stachastic gradient descent。Batch gradient descent会比较平稳地接近全局最小值,但是因为使用了所有个样本,每次前进的速度有些慢。Stachastic gradient descent每次前进速度很快,但是路线曲折,有较大的振荡,最终会在最小值附近来回波动,难以真正达到最小值处。而且在数值处理上就不能使用向量化的方法来提高运算速度。

实际使用中,mini-batch size不能设置得太大(Batch gradient descent),也不能设置得太小(Stachastic gradient descent)。这样,相当于结合了Batch gradient descent和Stachastic gradient descent各自的优点,既能使用向量化优化算法,又能叫快速地找到最小值。mini-batch gradient descent的梯度下降曲线如下图绿色所示,每次前进速度较快,且振荡较小,基本能接近全局最小值。

一般来说,如果总体样本数量不太大时,例如,建议直接使用Batch gradient descent。如果总体样本数量很大时,建议将样本分成许多mini-batches。推荐常用的mini-batch size为,,,。这些都是2的幂。之所以这样设置的原因是计算机存储数据一般是2的幂,这样设置可以提高运算速度。

本小节参考链接:关于Mini-batch梯度下降法的困惑,为什么会比批量梯度下降法快?

6.3 指数加权平均

举个例子,记录半年内伦敦市的气温变化,并在二维平面上绘制出来,如下图所示:

看上去,温度数据似乎有noise,而且抖动较大。如果我们希望看到半年内气温的整体变化趋势,可以通过移动平均(moving average)的方法来对每天气温进行平滑处理。

例如我们可以设,当成第天的气温值。

第一天的气温与第天的气温有关:

第二天的气温与第一天的气温有关:

即第天与第天的气温迭代关系为:

经过移动平均处理得到的气温如下图红色曲线所示:

这种滑动平均算法称为指数加权平均(exponentially weighted average)。根据之前的推导公式,其一般形式为:

上面的例子中值决定了指数加权平均的天数,近似表示为:

例如,,则,表示将前天进行指数加权平均。,则,表示将前天进行指数加权平均。越大,则指数加权平均的天数越多,平均后的趋势线就越平缓,但是同时也会向右平移。下图绿色曲线和黄色曲线分别表示了时,指数加权平均的结果。

这里简单解释一下公式是怎么来的。准确来说,指数加权平均算法跟之前所有天的数值都有关系,根据之前的推导公式就能看出。但是指数是衰减的,一般认为衰减到就可以忽略不计了。因此,根据之前的推导公式,我们只要证明

,则。即证明转化为:

显然,当时,上述等式是近似成立的。至此,简单解释了为什么指数加权平均的天数的计算公式为

6.4 理解指数加权平均

我们将指数加权平均公式的一般形式写下来:

上式中是原始数据值,是类似指数曲线,从右向左,呈指数下降的。的值就是这两个子式的点乘,将原始数据值与衰减指数点乘,相当于做了指数衰减,离得越近,影响越大,离得越远,影响越小,衰减越厉害。

我们已经知道了指数加权平均的递推公式。实际应用中为了减少内存的使用,我们可以使用这样的语句来实现指数加权平均算法:

本小节的参考链接:为什么在优化算法中使用指数加权平均

6.5 指数加权平均的偏差修正

上文中提到当时,指数加权平均结果如下图绿色曲线所示。但是实际上,真实曲线如紫色曲线所示。

我们注意到,紫色曲线与绿色曲线的区别是,紫色曲线开始的时候相对较低一些。这是因为开始时我们设置,所以初始值会相对小一些,直到后面受前面的影响渐渐变小,趋于正常。

修正这种问题的方法是进行偏移校正(bias correction),即在每次计算完后,对进行下式处理:

在刚开始的时候,比较小,,这样就将修正得更大一些,效果是把紫色曲线开始部分向上提升一些,与绿色曲线接近重合。随着增大,基本不变,紫色曲线与绿色曲线依然重合。这样就实现了简单的偏移校正,得到我们希望的绿色曲线。

注意机器学习中,偏移校正并不是必须的。因为,在迭代一次次数后(较大),受初始值影响微乎其微,紫色曲线与绿色曲线基本重合。所以,一般可以忽略初始迭代过程,等到一定迭代之后再取值,这样就不需要进行偏移校正了。

6.6 动量(momentum)梯度下降法

动量梯度下降与梯度下降相比,就是对梯度使用指数加权平均,其他的都保存一致

该部分将介绍动量梯度下降算法,其速度要比传统的梯度下降算法快很多。做法是在每次训练时,对梯度进行指数加权平均处理,然后用得到的梯度值更新权重和常数项。下面介绍具体的实现过程。

原始的梯度下降算法如上图蓝色折线所示。在梯度下降过程中,梯度下降的振荡较大,尤其对于之间数值范围差别较大的情况。此时每一点处的梯度只与当前方向有关,产生类似折线的效果,前进缓慢。而如果对梯度进行指数加权平均,这样使当前梯度不仅与当前方向有关,还与之前的方向有关,这样处理让梯度前进方向更加平滑,减少振荡,能够更快地到达最小值处。

权重和常数项的指数加权平均表达式如下:

从动量的角度来看,以权重为例,可以成速度V,可以看成是加速度。指数加权平均实际上是计算当前的速度,当前速度由之前的速度和现在的加速度共同影响。而,又能限制速度过大。也就是说,当前的速度是渐变的,而不是瞬变的,是动量的过程。这保证了梯度下降的平稳性和准确性,减少振荡,较快地达到最小值处。

动量梯度下降算法的过程如下:

初始时,令。一般设置,即指数加权平均前10天的数据,实际应用效果较好。

另外,关于偏移校正,可以不使用。因为经过10次迭代后,随着滑动平均的过程,偏移情况会逐渐消失。

补充一下,在其它文献资料中,动量梯度下降还有另外一种写法:

即消去了前的系数。这样简化了表达式,但是学习因子相当于变成了,表示也受的影响。从效果上来说,这种写法也是可以的,但是不够直观,且调参涉及到,不够方便。所以,实际应用中,推荐第一种动量梯度下降的表达式。

6.7 root mean square prop(RMSprop)

RMSprop是另外一种优化梯度下降速度的算法。每次迭代训练过程中,其权重W和常数项b的更新表达式为:

下面简单解释一下RMSprop算法的原理,仍然以下图为例,为了便于分析,令水平方向为的方向,垂直方向为的方向。

从图中可以看出,梯度下降(蓝色折线)在垂直方向()上振荡较大,在水平方向()上振荡较小,表示在方向上梯度较大,即较大,而在方向上梯度较小,即较小。因此,上述表达式中较大,而较小。在更新的表达式中,变化值较大,而较小。也就使得变化得多一些,变化得少一些。即加快了方向的速度,减小了方向的速度,减小振荡,实现快速梯度下降算法,其梯度下降过程如绿色折线所示。总得来说,就是如果哪个方向振荡大,就减小该方向的更新速度,从而减小振荡。

还有一点需要注意的是为了避免RMSprop算法中分母为零,通常可以在分母增加一个极小的常数

其中,,或者其它较小值。

6.8 Adam优化算法

Adam(Adaptive Moment Estimation)算法结合了动量梯度下降算法和RMSprop算法。其算法流程为:

Adam算法包含了几个超参数,分别是:

  • 通常设置为
  • 通常设置为
  • 通常设置为
    一般只需要对进行调试。

实际应用中,Adam算法结合了动量梯度下降和RMSprop各自的优点,使得神经网络训练速度大大提高。

6.9 学习率衰减

减小学习因子也能有效提高神经网络训练速度,这种方法被称为learning rate decay。

Learning rate decay就是随着迭代次数增加,学习因子逐渐减小。下面用图示的方式来解释这样做的好处。下图中,蓝色折线表示使用恒定的学习因子,由于每次训练相同,步进长度不变,在接近最优值处的振荡也大,在最优值附近较大范围内振荡,与最优值距离就比较远。绿色折线表示使用不断减小的,随着训练次数增加,逐渐减小,步进长度减小,使得能够在最优值处较小范围内微弱振荡,不断逼近最优值。相比较恒定的来说,learning rate decay更接近最优值。

Learning rate decay中对可由下列公式得到:

其中,是参数(可调),epoch是训练完所有样本的次数。随着epoch增加,会不断变小。除了上面计算的公式之外,还有其它可供选择的计算公式:

其中,为可调参数,为mini-bach number。除此之外,还可以设置为关于的离散值,随着增加,呈阶梯式减小。当然,也可以根据训练情况灵活调整当前的值,但会比较耗时间。

6.10局部最优问题

在使用梯度下降算法不断减小cost function时,可能会得到局部最优解(local optima)而不是全局最优解(global optima)。之前我们对局部最优解的理解是形如碗状的凹槽,如下图左边所示。但是在神经网络中,local optima的概念发生了变化。准确地来说,大部分梯度为零的“最优点”并不是这些凹槽处,而是形如右边所示的马鞍状,称为saddle point。也就是说,梯度为零并不能保证都是convex(极小值),也有可能是concave(极大值)。特别是在神经网络中参数很多的情况下,所有参数梯度为零的点很可能都是右边所示的马鞍状的saddle point,而不是左边那样的local optimum。

类似马鞍状的plateaus会降低神经网络学习速度。Plateaus是梯度接近于零的平缓区域,如下图所示。在plateaus上梯度很小,前进缓慢,到达saddle point需要很长时间。到达saddle point后,由于随机扰动,梯度一般能够沿着图中绿色箭头,离开saddle point,继续前进,只是在plateaus上花费了太多时间。

  • Copyrights © 2015-2024 wjh
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信