吴恩达深度学习课程笔记Lesson07(上)

第三周 超参数调试、Batch正则化和程序框架(Hyperparameter tuning)

3.1 调试处理(Tuning process)

大家好,欢迎回来,目前为止,你已经了解到,神经网络的改变会涉及到许多不同超参数的设置。现在,对于超参数而言,你要如何找到一套好的设定呢?在此视频中,我想和你分享一些指导原则,一些关于如何系统地组织超参调试过程的技巧,希望这些能够让你更有效的聚焦到合适的超参设定中。

在这里插入图片描述

关于训练深度最难的事情之一是你要处理的参数的数量,从学习速率 a a aMomentum(动量梯度下降法)的参数 β \beta β。如果使用MomentumAdam优化算法的参数, β 1 \beta_{1} β1 β 2 {\beta}_{2} β2 ε \varepsilon ε,也许你还得选择层数,也许你还得选择不同层中隐藏单元的数量,也许你还想使用学习率衰减。所以,你使用的不是单一的学习率 a a a。接着,当然你可能还需要选择mini-batch的大小。

结果证实一些超参数比其它的更为重要,我认为,最为广泛的学习应用是 a a a,学习速率是需要调试的最重要的超参数。

除了 a a a,还有一些参数需要调试,例如Momentum参数 β \beta β,0.9就是个很好的默认值。我还会调试mini-batch的大小,以确保最优算法运行有效。我还会经常调试隐藏单元,我用橙色圈住的这些,这三个是我觉得其次比较重要的,相对于 a a a而言。重要性排第三位的是其他因素,层数有时会产生很大的影响,学习率衰减也是如此。当应用Adam算法时,事实上,我从不调试 β 1 \beta_{1} β1 β 2 {\beta}_{2} β2 ε \varepsilon ε,我总是选定其分别为0.9,0.999和 1 0 − 8 10^{-8} 108,如果你想的话也可以调试它们。

但希望你粗略了解到哪些超参数较为重要, a a a无疑是最重要的,接下来是我用橙色圈住的那些,然后是我用紫色圈住的那些,但这不是严格且快速的标准,我认为,其它深度学习的研究者可能会很不同意我的观点或有着不同的直觉。

在这里插入图片描述

现在,如果你尝试调整一些超参数,该如何选择调试值呢?在早一代的机器学习算法中,如果你有两个超参数,这里我会称之为超参1,超参2,常见的做法是在网格中取样点,像这样,然后系统的研究这些数值。这里我放置的是5×5的网格,实践证明,网格可以是5×5,也可多可少,但对于这个例子,你可以尝试这所有的25个点,然后选择哪个参数效果最好。当参数的数量相对较少时,这个方法很实用。

在深度学习领域,我们常做的,我推荐你采用下面的做法,随机选择点,所以你可以选择同等数量的点,对吗?25个点,接着,用这些随机取的点试验超参数的效果。之所以这么做是因为,对于你要解决的问题而言,你很难提前知道哪个超参数最重要,正如你之前看到的,一些超参数的确要比其它的更重要。

举个例子,假设超参数1是 a a a(学习速率),取一个极端的例子,假设超参数2是Adam算法中,分母中的 ε \varepsilon ε。在这种情况下, a a a的取值很重要,而 ε \varepsilon ε取值则无关紧要。如果你在网格中取点,接着,你试验了 a a a的5个取值,那你会发现,无论 ε \varepsilon ε取何值,结果基本上都是一样的。所以,你知道共有25种模型,但进行试验的 a a a值只有5个,我认为这是很重要的。

对比而言,如果你随机取值,你会试验25个独立的 a a a,似乎你更有可能发现效果做好的那个。

在这里插入图片描述

我已经解释了两个参数的情况,实践中,你搜索的超参数可能不止两个。假如,你有三个超参数,这时你搜索的不是一个方格,而是一个立方体,超参数3代表第三维,接着,在三维立方体中取值,你会试验大量的更多的值,三个超参数中每个都是。

在这里插入图片描述

实践中,你搜索的可能不止三个超参数有时很难预知,哪个是最重要的超参数,对于你的具体应用而言,随机取值而不是网格取值表明,你探究了更多重要超参数的潜在值,无论结果是什么。

当你给超参数取值时,另一个惯例是采用由粗糙到精细的策略。

在这里插入图片描述

比如在二维的那个例子中,你进行了取值,也许你会发现效果最好的某个点,也许这个点周围的其他一些点效果也很好,那在接下来要做的是放大这块小区域(小蓝色方框内),然后在其中更密集得取值或随机取值,聚集更多的资源,在这个蓝色的方格中搜索,如果你怀疑这些超参数在这个区域的最优结果,那在整个的方格中进行粗略搜索后,你会知道接下来应该聚焦到更小的方格中。在更小的方格中,你可以更密集得取点。所以这种从粗到细的搜索也经常使用。

通过试验超参数的不同取值,你可以选择对训练集目标而言的最优值,或对于开发集而言的最优值,或在超参搜索过程中你最想优化的东西。

我希望,这能给你提供一种方法去系统地组织超参数搜索过程。另一个关键点是随机取值和精确搜索,考虑使用由粗糙到精细的搜索过程。但超参数的搜索内容还不止这些,在下一个视频中,我会继续讲解关于如何选择超参数取值的合理范围。

3.2 为超参数选择合适的范围(Using an appropriate scale to pick hyperparameters)

在上一个视频中,你已经看到了在超参数范围中,随机取值可以提升你的搜索效率。但随机取值并不是在有效范围内的随机均匀取值,而是选择合适的标尺,用于探究这些超参数,这很重要。在这个视频中,我会教你怎么做。

在这里插入图片描述

假设你要选取隐藏单元的数量 n [ l ] n^{[l]} n[l],假设,你选取的取值范围是从50到100中某点,这种情况下,看到这条从50-100的数轴,你可以随机在其取点,这是一个搜索特定超参数的很直观的方式。或者,如果你要选取神经网络的层数,我们称之为字母 L L L,你也许会选择层数为2到4中的某个值,接着顺着2,3,4随机均匀取样才比较合理,你还可以应用网格搜索,你会觉得2,3,4,这三个数值是合理的,这是在几个在你考虑范围内随机均匀取值的例子,这些取值还蛮合理的,但对某些超参数而言不适用。

在这里插入图片描述

看看这个例子,假设你在搜索超参数 a a a(学习速率),假设你怀疑其值最小是0.0001或最大是1。如果你画一条从0.0001到1的数轴,沿其随机均匀取值,那90%的数值将会落在0.1到1之间,结果就是,在0.1到1之间,应用了90%的资源,而在0.0001到0.1之间,只有10%的搜索资源,这看上去不太对。

反而,用对数标尺搜索超参数的方式会更合理,因此这里不使用线性轴,分别依次取0.0001,0.001,0.01,0.1,1,在对数轴上均匀随机取点,这样,在0.0001到0.001之间,就会有更多的搜索资源可用,还有在0.001到0.01之间等等。

在这里插入图片描述

所以在Python中,你可以这样做,使r=-4*np.random.rand(),然后 a a a随机取值,$ a =10^{r} ,所以,第一行可以得出 ,所以,第一行可以得出 ,所以,第一行可以得出r \in [ 4,0] ,那么 ,那么 ,那么a \in[10{-4},10{0}]$,所以最左边的数字是 1 0 − 4 10^{-4} 104,最右边是 1 0 0 10^{0} 100

在这里插入图片描述

更常见的情况是,如果你在 1 0 a 10^{a} 10a 1 0 b 10^{b} 10b之间取值,在此例中,这是 1 0 a 10^{a} 10a(0.0001),你可以通过 ⁡ 0.0001 \operatorname{}{0.0001} 0.0001算出 a a a的值,即-4,在右边的值是 1 0 b 10^{b} 10b,你可以算出 b b b的值 ⁡ 1 \operatorname{}1 1,即0。你要做的就是在 [ a , b ] [a,b] [a,b]区间随机均匀地给 r r r取值,这个例子中 r ∈ [ − 4 , 0 ] r \in \lbrack - 4,0\rbrack r[4,0],然后你可以设置 a a a的值,基于随机取样的超参数 a = 1 0 r a =10^{r} a=10r

在这里插入图片描述

所以总结一下,在对数坐标下取值,取最小值的对数就得到 a a a的值,取最大值的对数就得到 b b b值,所以现在你在对数轴上的 1 0 a 10^{a} 10a 1 0 b 10^{b} 10b区间取值,在 a a a b b b间随意均匀的选取 r r r值,将超参数设置为 1 0 r 10^{r} 10r,这就是在对数轴上取值的过程。

在这里插入图片描述

最后,另一个棘手的例子是给 β \beta β 取值,用于计算指数的加权平均值。假设你认为 β \beta β是0.9到0.999之间的某个值,也许这就是你想搜索的范围。记住这一点,当计算指数的加权平均值时,取0.9就像在10个值中计算平均值,有点类似于计算10天的温度平均值,而取0.999就是在1000个值中取平均。

所以和上张幻灯片上的内容类似,如果你想在0.9到0.999区间搜索,那就不能用线性轴取值,对吧?不要随机均匀在此区间取值,所以考虑这个问题最好的方法就是,我们要探究的是 1 − β 1-\beta 1β,此值在0.1到0.001区间内,所以我们会给 1 − β 1-\beta 1β取值,大概是从0.1到0.001,应用之前幻灯片中介绍的方法,这是 1 0 − 1 10^{-1} 101,这是 1 0 − 3 10^{-3} 103,值得注意的是,在之前的幻灯片里,我们把最小值写在左边,最大值写在右边,但在这里,我们颠倒了大小。这里,左边的是最大值,右边的是最小值。所以你要做的就是在 [ − 3 , − 1 ] [-3,-1] [3,1]里随机均匀的给r取值。你设定了 1 − β = 1 0 r 1- \beta = 10^{r} 1β=10r,所以 β = 1 − 1 0 r \beta = 1-10^{r} β=110r,然后这就变成了在特定的选择范围内超参数随机取值。希望用这种方式得到想要的结果,你在0.9到0.99区间探究的资源,和在0.99到0.999区间探究的一样多。

在这里插入图片描述

所以,如果你想研究更多正式的数学证明,关于为什么我们要这样做,为什么用线性轴取值不是个好办法,这是因为当 β \beta β 接近1时,所得结果的灵敏度会变化,即使 β \beta β有微小的变化。所以 β \beta β 在0.9到0.9005之间取值,无关紧要,你的结果几乎不会变化。

在这里插入图片描述

β \beta β值如果在0.999到0.9995之间,这会对你的算法产生巨大影响,对吧?在这两种情况下,是根据大概10个值取平均。但这里,它是指数的加权平均值,基于1000个值,现在是2000个值,因为这个公式 1 1 − β \frac{1}{1- \beta} 1β1,当 β \beta β接近1时, β \beta β就会对细微的变化变得很敏感。所以整个取值过程中,你需要更加密集地取值,在 β \beta β 接近1的区间内,或者说,当 1 − β 1-\beta 1β 接近于0时,这样,你就可以更加有效的分布取样点,更有效率的探究可能的结果。

希望能帮助你选择合适的标尺,来给超参数取值。如果你没有在超参数选择中作出正确的标尺决定,别担心,即使你在均匀的标尺上取值,如果数值总量较多的话,你也会得到还不错的结果,尤其是应用从粗到细的搜索方法,在之后的迭代中,你还是会聚焦到有用的超参数取值范围上。

希望这会对你的超参数搜索有帮助,下一个视频中,我们将会分享一些关于如何组建搜索过程的思考,希望它能使你的工作更高效。

3.3 超参数调试的实践:Pandas VS Caviar(Hyperparameters tuning in practice: Pandas vs. Caviar)

到现在为止,你已经听了许多关于如何搜索最优超参数的内容,在结束我们关于超参数搜索的讨论之前,我想最后和你分享一些建议和技巧,关于如何组织你的超参数搜索过程。

在这里插入图片描述

如今的深度学习已经应用到许多不同的领域,某个应用领域的超参数设定,有可能通用于另一领域,不同的应用领域出现相互交融。比如,我曾经看到过计算机视觉领域中涌现的巧妙方法,比如说ConfonetsResNets,这我们会在后续课程中讲到。它还成功应用于语音识别,我还看到过最初起源于语音识别的想法成功应用于NLP等等。

深度学习领域中,发展很好的一点是,不同应用领域的人们会阅读越来越多其它研究领域的文章,跨领域去寻找灵感。

就超参数的设定而言,我见到过有些直觉想法变得很缺乏新意,所以,即使你只研究一个问题,比如说逻辑学,你也许已经找到一组很好的参数设置,并继续发展算法,或许在几个月的过程中,观察到你的数据会逐渐改变,或也许只是在你的数据中心更新了服务器,正因为有了这些变化,你原来的超参数的设定不再好用,所以我建议,或许只是重新测试或评估你的超参数,至少每隔几个月一次,以确保你对数值依然很满意。

最后,关于如何搜索超参数的问题,我见过大概两种重要的思想流派或人们通常采用的两种重要但不同的方式。

在这里插入图片描述

一种是你照看一个模型,通常是有庞大的数据组,但没有许多计算资源或足够的CPUGPU的前提下,基本而言,你只可以一次负担起试验一个模型或一小批模型,在这种情况下,即使当它在试验时,你也可以逐渐改良。比如,第0天,你将随机参数初始化,然后开始试验,然后你逐渐观察自己的学习曲线,也许是损失函数J,或者数据设置误差或其它的东西,在第1天内逐渐减少,那这一天末的时候,你可能会说,看,它学习得真不错。我试着增加一点学习速率,看看它会怎样,也许结果证明它做得更好,那是你第二天的表现。两天后,你会说,它依旧做得不错,也许我现在可以填充下Momentum或减少变量。然后进入第三天,每天,你都会观察它,不断调整你的参数。也许有一天,你会发现你的学习率太大了,所以你可能又回归之前的模型,像这样,但你可以说是在每天花时间照看此模型,即使是它在许多天或许多星期的试验过程中。所以这是一个人们照料一个模型的方法,观察它的表现,耐心地调试学习率,但那通常是因为你没有足够的计算能力,不能在同一时间试验大量模型时才采取的办法。

在这里插入图片描述

另一种方法则是同时试验多种模型,你设置了一些超参数,尽管让它自己运行,或者是一天甚至多天,然后你会获得像这样的学习曲线,这可以是损失函数J或实验误差或损失或数据误差的损失,但都是你曲线轨迹的度量。同时你可以开始一个有着不同超参数设定的不同模型,所以,你的第二个模型会生成一个不同的学习曲线,也许是像这样的一条(紫色曲线),我会说这条看起来更好些。与此同时,你可以试验第三种模型,其可能产生一条像这样的学习曲线(红色曲线),还有另一条(绿色曲线),也许这条有所偏离,像这样,等等。或者你可以同时平行试验许多不同的模型,橙色的线就是不同的模型。用这种方式你可以试验许多不同的参数设定,然后只是最后快速选择工作效果最好的那个。在这个例子中,也许这条看起来是最好的(下方绿色曲线)。

在这里插入图片描述

打个比方,我把左边的方法称为熊猫方式。当熊猫有了孩子,他们的孩子非常少,一次通常只有一个,然后他们花费很多精力抚养熊猫宝宝以确保其能成活,所以,这的确是一种照料,一种模型类似于一只熊猫宝宝。对比而言,右边的方式更像鱼类的行为,我称之为鱼子酱方式。在交配季节,有些鱼类会产下一亿颗卵,但鱼类繁殖的方式是,它们会产生很多卵,但不对其中任何一个多加照料,只是希望其中一个,或其中一群,能够表现出色。我猜,这就是哺乳动物繁衍和鱼类,很多爬虫类动物繁衍的区别。我将称之为熊猫方式与鱼子酱方式,因为这很有趣,更容易记住。

所以这两种方式的选择,是由你拥有的计算资源决定的,如果你拥有足够的计算机去平行试验许多模型,那绝对采用鱼子酱方式,尝试许多不同的超参数,看效果怎么样。但在一些应用领域,比如在线广告设置和计算机视觉应用领域,那里的数据太多了,你需要试验大量的模型,所以同时试验大量的模型是很困难的,它的确是依赖于应用的过程。但我看到那些应用熊猫方式多一些的组织,那里,你会像对婴儿一样照看一个模型,调试参数,试着让它工作运转。尽管,当然,甚至是在熊猫方式中,试验一个模型,观察它工作与否,也许第二或第三个星期后,也许我应该建立一个不同的模型(绿色曲线),像熊猫那样照料它,我猜,这样一生中可以培育几个孩子,即使它们一次只有一个孩子或孩子的数量很少。

在这里插入图片描述

所以希望你能学会如何进行超参数的搜索过程,现在,还有另一种技巧,能使你的神经网络变得更加坚实,它并不是对所有的神经网络都适用,但当适用时,它可以使超参数搜索变得容易许多并加速试验过程,我们在下个视频中再讲解这个技巧。

3.4 归一化网络的激活函数(Normalizing activations in a network)

在深度学习兴起后,最重要的一个思想是它的一种算法,叫做Batch归一化,由Sergey loffeChristian Szegedy两位研究者创造。Batch归一化会使你的参数搜索问题变得很容易,使神经网络对超参数的选择更加稳定,超参数的范围会更加庞大,工作效果也很好,也会是你的训练更加容易,甚至是深层网络。让我们来看看Batch归一化是怎么起作用的吧。

在这里插入图片描述

当训练一个模型,比如logistic回归时,你也许会记得,归一化输入特征可以加快学习过程。你计算了平均值,从训练集中减去平均值,计算了方差,接着根据方差归一化你的数据集,在之前的视频中我们看到,这是如何把学习问题的轮廓,从很长的东西,变成更圆的东西,更易于算法优化。所以这是有效的,对logistic回归和神经网络的归一化输入特征值而言。

在这里插入图片描述

那么更深的模型呢?你不仅输入了特征值 x x x,而且这层有激活值 a [ 1 ] a^{[1]} a[1],这层有激活值 a [ 2 ] a^{[2]} a[2]等等。如果你想训练这些参数,比如 w [ 3 ] w^{[3]} w[3] b [ 3 ] b^{[3]} b[3],那归一化 a [ 2 ] a^{[2]} a[2]的平均值和方差岂不是很好?以便使 w [ 3 ] w^{[3]} w[3] b [ 3 ] b^{[3]} b[3]的训练更有效率。在logistic回归的例子中,我们看到了如何归一化 x 1 x_{1} x1 x 2 x_{2} x2 x 3 x_{3} x3,会帮助你更有效的训练 w w w b b b

所以问题来了,对任何一个隐藏层而言,我们能否归一化 a a a值,在此例中,比如说 a [ 2 ] a^{[2]} a[2]的值,但可以是任何隐藏层的,以更快的速度训练 w [ 3 ] w^{[3]} w[3] b [ 3 ] b^{[3]} b[3],因为 a [ 2 ] a^{[2]} a[2]是下一层的输入值,所以就会影响 w [ 3 ] w^{[3]} w[3] b [ 3 ] b^{[3]} b[3]的训练。简单来说,这就是Batch归一化的作用。尽管严格来说,我们真正归一化的不是 a [ 2 ] a^{[2]} a[2],而是 z [ 2 ] z^{[2]} z[2],深度学习文献中有一些争论,关于在激活函数之前是否应该将值 z [ 2 ] z^{[2]} z[2]归一化,或是否应该在应用激活函数 a [ 2 ] a^{[2]} a[2]后再规范值。实践中,经常做的是归一化 z [ 2 ] z^{[2]} z[2],所以这就是我介绍的版本,我推荐其为默认选择,那下面就是Batch归一化的使用方法。

在这里插入图片描述

在神经网络中,已知一些中间值,假设你有一些隐藏单元值,从 z ( 1 ) z^{(1)} z(1) z ( m ) z^{(m)} z(m),这些来源于隐藏层,所以这样写会更准确,即 z [ l ] ( i ) z^{[l](i)} z[l](i)为隐藏层, i i i从1到 m m m,但这样书写,我要省略 l l l及方括号,以便简化这一行的符号。所以已知这些值,如下,你要计算平均值,强调一下,所有这些都是针对 l l l层,但我省略 l l l及方括号,然后用正如你常用的那个公式计算方差,接着,你会取每个 z ( i ) z^{(i)} z(i)值,使其规范化,方法如下,减去均值再除以标准偏差,为了使数值稳定,通常将 ε \varepsilon ε作为分母,以防 σ = 0 σ=0 σ=0的情况。

在这里插入图片描述

所以现在我们已把这些 z z z值标准化,化为含平均值0和标准单位方差,所以 z z z的每一个分量都含有平均值0和方差1,但我们不想让隐藏单元总是含有平均值0和方差1,也许隐藏单元有了不同的分布会有意义,所以我们所要做的就是计算,我们称之为 z ~ ( i ) {\tilde{z}}^{(i)} z~(i) z ~ ( i ) = γ z norm ( i ) + β {\tilde{z}}^{(i)}= \gamma z_{\text{norm}}^{(i)} +\beta z~(i)=γznorm(i)+β,这里 γ \gamma γ β \beta β是你模型的学习参数,所以我们使用梯度下降或一些其它类似梯度下降的算法,比如Momentum或者NesterovAdam,你会更新 γ \gamma γ β \beta β,正如更新神经网络的权重一样。

在这里插入图片描述

请注意 γ \gamma γ β \beta β的作用是,你可以随意设置 z ~ ( i ) {\tilde{z}}^{(i)} z~(i)的平均值,事实上,如果 γ = σ 2 + ε \gamma= \sqrt{\sigma^{2} +\varepsilon} γ=σ2+ε ,如果 γ \gamma γ等于这个分母项( z norm ( i ) = z ( i ) − μ σ 2 + ε z_{\text{norm}}^{(i)} = \frac{z^{(i)} -\mu}{\sqrt{\sigma^{2} +\varepsilon}} znorm(i)=σ2+ε z(i)μ中的分母), β \beta β等于 μ \mu μ,这里的这个值是 z norm ( i ) = z ( i ) − μ σ 2 + ε z_{\text{norm}}^{(i)}= \frac{z^{(i)} - \mu}{\sqrt{\sigma^{2} + \varepsilon}} znorm(i)=σ2+ε z(i)μ中的 μ \mu μ,那么 γ z norm ( i ) + β \gamma z_{\text{norm}}^{(i)} +\beta γznorm(i)+β的作用在于,它会精确转化这个方程,如果这些成立( γ = σ 2 + ε , β = μ \gamma =\sqrt{\sigma^{2} + \varepsilon},\beta =\mu γ=σ2+ε ,β=μ),那么 z ~ ( i ) = z ( i ) {\tilde{z}}^{(i)} = z^{(i)} z~(i)=z(i)

通过对 γ \gamma γ β \beta β合理设定,规范化过程,即这四个等式,从根本来说,只是计算恒等函数,通过赋予 γ \gamma γ β \beta β其它值,可以使你构造含其它平均值和方差的隐藏单元值。

在这里插入图片描述

所以,在网络匹配这个单元的方式,之前可能是用 z ( 1 ) z^{(1)} z(1) z ( 2 ) z^{(2)} z(2)等等,现在则会用 z ~ ( i ) {\tilde{z}}^{(i)} z~(i)取代 z ( i ) z^{(i)} z(i),方便神经网络中的后续计算。如果你想放回 [ l ] [l] [l],以清楚的表明它位于哪层,你可以把它放这。

在这里插入图片描述

所以我希望你学到的是,归一化输入特征 X X X是怎样有助于神经网络中的学习,Batch归一化的作用是它适用的归一化过程,不只是输入层,甚至同样适用于神经网络中的深度隐藏层。你应用Batch归一化了一些隐藏单元值中的平均值和方差,不过训练输入和这些隐藏单元值的一个区别是,你也许不想隐藏单元值必须是平均值0和方差1。

在这里插入图片描述

比如,如果你有sigmoid激活函数,你不想让你的值总是全部集中在这里,你想使它们有更大的方差,或不是0的平均值,以便更好的利用非线性的sigmoid函数,而不是使所有的值都集中于这个线性版本中,这就是为什么有了 γ \gamma γ β \beta β两个参数后,你可以确保所有的 z ( i ) z^{(i)} z(i)值可以是你想赋予的任意值,或者它的作用是保证隐藏的单元已使均值和方差标准化。那里,均值和方差由两参数控制,即 γ \gamma γ β \beta β,学习算法可以设置为任何值,所以它真正的作用是,使隐藏单元值的均值和方差标准化,即 z ( i ) z^{(i)} z(i)有固定的均值和方差,均值和方差可以是0和1,也可以是其它值,它是由 γ \gamma γ β \beta β两参数控制的。

我希望你能学会怎样使用Batch归一化,至少就神经网络的单一层而言,在下一个视频中,我会教你如何将Batch归一化与神经网络甚至是深度神经网络相匹配。对于神经网络许多不同层而言,又该如何使它适用,之后,我会告诉你,Batch归一化有助于训练神经网络的原因。所以如果觉得Batch归一化起作用的原因还显得有点神秘,那跟着我走,在接下来的两个视频中,我们会弄清楚。

3.5 将 Batch Norm 拟合进神经网络(Fitting Batch Norm into a neural network)

你已经看到那些等式,它可以在单一隐藏层进行Batch归一化,接下来,让我们看看它是怎样在深度网络训练中拟合的吧。

在这里插入图片描述

假设你有一个这样的神经网络,我之前说过,你可以认为每个单元负责计算两件事。第一,它先计算z,然后应用其到激活函数中再计算a,所以我可以认为,每个圆圈代表着两步的计算过程。同样的,对于下一层而言,那就是 z 1 [ 2 ] z_{1}^{[2]} z1[2] a 1 [ 2 ] a_{1}^{[2]} a1[2]等。所以如果你没有应用Batch归一化,你会把输入 X X X拟合到第一隐藏层,然后首先计算 z [ 1 ] z^{[1]} z[1],这是由 w [ 1 ] w^{[1]} w[1] b [ 1 ] b^{[1]} b[1]两个参数控制的。接着,通常而言,你会把 z [ 1 ] z^{[1]} z[1]拟合到激活函数以计算 a [ 1 ] a^{[1]} a[1]。但Batch归一化的做法是将 z [ 1 ] z^{[1]} z[1]值进行Batch归一化,简称BN,此过程将由 β [ 1 ] {\beta}^{[1]} β[1] γ [ 1 ] \gamma^{[1]} γ[1]两参数控制,这一操作会给你一个新的规范化的 z [ 1 ] z^{[1]} z[1]值( z ~ [ 1 ] {\tilde{z}}^{[1]} z~[1]),然后将其输入激活函数中得到 a [ 1 ] a^{[1]} a[1],即 a [ 1 ] = g [ 1 ] ( z ~ [ l ] ) a^{[1]} = g^{[1]}({\tilde{z}}^{[ l]}) a[1]=g[1](z~[l])

在这里插入图片描述

现在,你已在第一层进行了计算,此时Batch归一化发生在z的计算和 a a a之间,接下来,你需要应用 a [ 1 ] a^{[1]} a[1]值来计算 z [ 2 ] z^{[2]} z[2],此过程是由 w [ 2 ] w^{[2]} w[2] b [ 2 ] b^{[2]} b[2]控制的。与你在第一层所做的类似,你会将 z [ 2 ] z^{[2]} z[2]进行Batch归一化,现在我们简称BN,这是由下一层的Batch归一化参数所管制的,即 β [ 2 ] {\beta}^{[2]} β[2] γ [ 2 ] \gamma^{[2]} γ[2],现在你得到 z ~ [ 2 ] {\tilde{z}}^{[2]} z~[2],再通过激活函数计算出 a [ 2 ] a^{[2]} a[2]等等。

所以需要强调的是Batch归一化是发生在计算 z z z a a a之间的。直觉就是,与其应用没有归一化的 z z z值,不如用归一过的 z ~ \tilde{z} z~,这是第一层( z ~ [ 1 ] {\tilde{z}}^{[1]} z~[1])。第二层同理,与其应用没有规范过的 z [ 2 ] z^{[2]} z[2]值,不如用经过方差和均值归一后的 z ~ [ 2 ] {\tilde{z}}^{[2]} z~[2]。所以,你网络的参数就会是 w [ 1 ] w^{[1]} w[1] b [ 1 ] b^{[1]} b[1] w [ 2 ] w^{[2]} w[2] b [ 2 ] b^{[2]} b[2]等等,我们将要去掉这些参数。但现在,想象参数 w [ 1 ] w^{[1]} w[1] b [ 1 ] b^{[1]} b[1] w [ l ] w^{[l]} w[l] b [ l ] b^{[l]} b[l],我们将另一些参数加入到此新网络中 β [ 1 ] {\beta}^{[1]} β[1] β [ 2 ] {\beta}^{[2]} β[2] γ [ 1 ] \gamma^{[1]} γ[1] γ [ 2 ] \gamma^{[2]} γ[2]等等。对于应用Batch归一化的每一层而言。需要澄清的是,请注意,这里的这些 β \beta β β [ 1 ] {\beta}^{[1]} β[1] β [ 2 ] {\beta}^{[2]} β[2]等等)和超参数 β \beta β没有任何关系,下一张幻灯片中会解释原因,后者是用于Momentum或计算各个指数的加权平均值。Adam论文的作者,在论文里用 β \beta β代表超参数。Batch归一化论文的作者,则使用 β \beta β代表此参数( β [ 1 ] {\beta}^{[1]} β[1] β [ 2 ] {\beta}^{[2]} β[2]等等),但这是两个完全不同的 β \beta β。我在两种情况下都决定使用 β \beta β,以便你阅读那些原创的论文,但Batch归一化学习参数 β [ 1 ] {\beta}^{[1]} β[1] β [ 2 ] {\beta}^{\left\lbrack2 \right\rbrack} β[2]等等和用于MomentumAdamRMSprop算法中的 β \beta β不同。

在这里插入图片描述

所以现在,这是你算法的新参数,接下来你可以使用想用的任何一种优化算法,比如使用梯度下降法来执行它。

举个例子,对于给定层,你会计算 d β [ l ] d{\beta}^{[l]} dβ[l],接着更新参数 β \beta β β [ l ] = β [ l ] − α d β [ l ] {\beta}^{[l]} = {\beta}^{[l]} - \alpha d{\beta}^{[l]} β[l]=β[l]αdβ[l]。你也可以使用AdamRMSpropMomentum,以更新参数 β \beta β γ \gamma γ,并不是只应用梯度下降法。

即使在之前的视频中,我已经解释过Batch归一化是怎么操作的,计算均值和方差,减去均值,再除以方差,如果它们使用的是深度学习编程框架,通常你不必自己把Batch归一化步骤应用于Batch归一化层。因此,探究框架,可写成一行代码,比如说,在TensorFlow框架中,你可以用这个函数(tf.nn.batch_normalization)来实现Batch归一化,我们稍后讲解,但实践中,你不必自己操作所有这些具体的细节,但知道它是如何作用的,你可以更好的理解代码的作用。但在深度学习框架中,Batch归一化的过程,经常是类似一行代码的东西。

所以,到目前为止,我们已经讲了Batch归一化,就像你在整个训练站点上训练一样,或就像你正在使用Batch梯度下降法。

在这里插入图片描述

实践中,Batch归一化通常和训练集的mini-batch一起使用。你应用Batch归一化的方式就是,你用第一个mini-batch( X { 1 } X^{\{1\}} X{1}),然后计算 z [ 1 ] z^{[1]} z[1],这和上张幻灯片上我们所做的一样,应用参数 w [ 1 ] w^{[1]} w[1] b [ 1 ] b^{[1]} b[1],使用这个mini-batch( X { 1 } X^{\{1\}} X{1})。接着,继续第二个mini-batch( X { 2 } X^{\{2\}} X{2}),接着Batch归一化会减去均值,除以标准差,由 β [ 1 ] {\beta}^{[1]} β[1] γ [ 1 ] \gamma^{[1]} γ[1]重新缩放,这样就得到了 z ~ [ 1 ] {\tilde{z}}^{[1]} z~[1],而所有的这些都是在第一个mini-batch的基础上,你再应用激活函数得到 a [ 1 ] a^{[1]} a[1]。然后用 w [ 2 ] w^{[2]} w[2] b [ 2 ] b^{[2]} b[2]计算 z [ 2 ] z^{[2]} z[2],等等,所以你做的这一切都是为了在第一个mini-batch( X { 1 } X^{\{1\}} X{1})上进行一步梯度下降法。

在这里插入图片描述

类似的工作,你会在第二个mini-batch X { 2 } X^{\left\{2 \right\}} X{2})上计算 z [ 1 ] z^{[1]} z[1],然后用Batch归一化来计算 z ~ [ 1 ] {\tilde{z}}^{[1]} z~[1],所以Batch归一化的此步中,你用第二个mini-batch X { 2 } X^{\left\{2 \right\}} X{2})中的数据使 z ~ [ 1 ] {\tilde{z}}^{[1]} z~[1]归一化,这里的Batch归一化步骤也是如此,让我们来看看在第二个mini-batch X { 2 } X^{\left\{2 \right\}} X{2})中的例子,在mini-batch上计算 z [ 1 ] z^{[1]} z[1]的均值和方差,重新缩放的 β \beta β γ \gamma γ得到 z [ 1 ] z^{[1]} z[1],等等。

在这里插入图片描述

然后在第三个mini-batch X { 3 } X^{\left\{ 3 \right\}} X{3})上同样这样做,继续训练。

现在,我想澄清此参数的一个细节。先前我说过每层的参数是 w [ l ] w^{[l]} w[l] b [ l ] b^{[l]} b[l],还有 β [ l ] {\beta}^{[l]} β[l] γ [ l ] \gamma^{[l]} γ[l],请注意计算 z z z的方式如下, z [ l ] = w [ l ] a [ l − 1 ] + b [ l ] z^{[l]} =w^{[l]}a^{\left\lbrack l - 1 \right\rbrack} +b^{[l]} z[l]=w[l]a[l1]+b[l],但Batch归一化做的是,它要看这个mini-batch,先将 z [ l ] z^{[l]} z[l]归一化,结果为均值0和标准方差,再由 β \beta β γ \gamma γ重缩放,但这意味着,无论 b [ l ] b^{[l]} b[l]的值是多少,都是要被减去的,因为在Batch归一化的过程中,你要计算 z [ l ] z^{[l]} z[l]的均值,再减去平均值,在此例中的mini-batch中增加任何常数,数值都不会改变,因为加上的任何常数都将会被均值减去所抵消。

在这里插入图片描述

所以,如果你在使用Batch归一化,其实你可以消除这个参数( b [ l ] b^{[l]} b[l]),或者你也可以,暂时把它设置为0,那么,参数变成 z [ l ] = w [ l ] a [ l − 1 ] z^{[l]} = w^{[l]}a^{\left\lbrack l - 1 \right\rbrack} z[l]=w[l]a[l1],然后你计算归一化的 z [ l ] z^{[l]} z[l] z ~ [ l ] = γ [ l ] z [ l ] + β [ l ] {\tilde{z}}^{[l]} = \gamma^{[l]}z^{[l]} + {\beta}^{[l]} z~[l]=γ[l]z[l]+β[l],你最后会用参数 β [ l ] {\beta}^{[l]} β[l],以便决定 z ~ [ l ] {\tilde{z}}^{[l]} z~[l]的取值,这就是原因。

在这里插入图片描述

所以总结一下,因为Batch归一化超过了此层 z [ l ] z^{[l]} z[l]的均值, b [ l ] b^{[l]} b[l]这个参数没有意义,所以,你必须去掉它,由 β [ l ] {\beta}^{[l]} β[l]代替,这是个控制参数,会影响转移或偏置条件。

最后,请记住 z [ l ] z^{[l]} z[l]的维数,因为在这个例子中,维数会是 ( n [ l ] , 1 ) (n^{[l]},1) (n[l],1) b [ l ] b^{[l]} b[l]的尺寸为 ( n [ l ] , 1 ) (n^{[l]},1) (n[l],1),如果是l层隐藏单元的数量,那 β [ l ] {\beta}^{[l]} β[l] γ [ l ] \gamma^{[l]} γ[l]的维度也是 ( n [ l ] , 1 ) (n^{[l]},1) (n[l],1),因为这是你隐藏层的数量,你有 n [ l ] n^{[l]} n[l]隐藏单元,所以 β [ l ] {\beta}^{[l]} β[l] γ [ l ] \gamma^{[l]} γ[l]用来将每个隐藏层的均值和方差缩放为网络想要的值。

在这里插入图片描述

让我们总结一下关于如何用Batch归一化来应用梯度下降法,假设你在使用mini-batch梯度下降法,你运行 t = 1 t=1 t=1batch数量的for循环,你会在mini-batch X { t } X^{\left\{ t\right\}} X{t}上应用正向prop,每个隐藏层都应用正向prop,用Batch归一化代替 z [ l ] z^{[l]} z[l] z ~ [ l ] {\tilde{z}}^{[l]} z~[l]。接下来,它确保在这个mini-batch中, z z z值有归一化的均值和方差,归一化均值和方差后是 z ~ [ l ] {\tilde{z}}^{[l]} z~[l],然后,你用反向prop计算 d w [ l ] dw^{[l]} dw[l] d b [ l ] db^{[l]} db[l],及所有l层所有的参数, d β [ l ] d{\beta}^{[l]} dβ[l] d γ [ l ] d\gamma^{[l]} dγ[l]。尽管严格来说,因为你要去掉 b b b,这部分其实已经去掉了。最后,你更新这些参数: w [ l ] = w [ l ] − αd w [ l ] w^{[l]} = w^{[l]} -\text{αd}w^{[l]} w[l]=w[l]αdw[l],和以前一样, β [ l ] = β [ l ] − α d β [ l ] {\beta}^{[l]} = {\beta}^{[l]} - {αd}{\beta}^{[l]} β[l]=β[l]αdβ[l],对于 γ \gamma γ也是如此 γ [ l ] = γ [ l ] − α d γ [ l ] \gamma^{[l]} = \gamma^{[l]} -{αd}\gamma^{[l]} γ[l]=γ[l]αdγ[l]

如果你已将梯度计算如下,你就可以使用梯度下降法了,这就是我写到这里的,但也适用于有MomentumRMSpropAdam的梯度下降法。与其使用梯度下降法更新mini-batch,你可以使用这些其它算法来更新,我们在之前几个星期中的视频中讨论过的,也可以应用其它的一些优化算法来更新由Batch归一化添加到算法中的 β \beta β γ \gamma γ 参数。

在这里插入图片描述

我希望,你能学会如何从头开始应用Batch归一化,如果你想的话。如果你使用深度学习编程框架之一,我们之后会谈。,希望,你可以直接调用别人的编程框架,这会使Batch归一化的使用变得很容易。

现在,以防Batch归一化仍然看起来有些神秘,尤其是你还不清楚为什么其能如此显著的加速训练,我们进入下一个视频,详细讨论Batch归一化为何效果如此显著,它到底在做什么。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值