原创博客,转载请注明出处!

本周讲的是超参数调试、Batch正则化和程序框架

1、调试处理

本节我想和你分享一些指导原则,一些关于如何系统地组织超参调试过程的技巧。

关于训练深度最难的事情之一是你要处理的参数的数量,结果证实一些超参数比其它的更为重要,我认为,最为广泛的学习应用是α,学习速率是需要调试的最重要的超参数

吴恩达老师认为红色圈住的最重要,其次黄色,最后紫色

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

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

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

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

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

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

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

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

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

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

2、为超参数选择合适的范围

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

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

看看这个例子,假设你在搜索超参数α(学习速率),假设你怀疑其值最小是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()

更常见的情况是,如果你在10^a和10^b之间取值

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

最后,另一个棘手的例子是给 β 取值,用于计算指数的加权平均值。假设你认为 β 是0.9到0.999之间的某个值,也许这就是你想搜索的范围。记住这一点,当计算指数的加权平均值时,取0.9就像在10个值中计算平均值,有点类似于计算10天的温度平均值,而取0.999就是在1000个值中取平均。所以就不能用线性轴取值。不要随机均匀在此区间取值,所以考虑这个问题最好的方法就是,我们要探究的是1- β ,此值在0.1到0.001区间内,所以我们会给1- β 取值,大概是从0.1到0.001,用之前介绍的方法,这是10^-1 到 10^-30,所以你要做的就是在[-3,-1]里随机均匀的给r取值,然后这就变成了在特定的选择范围内超参数随机取值。希望用这种方式得到想要的结果,你在0.9到0.99区间探究的资源,和在0.99到0.999区间探究的一样多。

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

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

3、超参数训练的实践:Pandas VS Caviar

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

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

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

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

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

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

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

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

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

4、正则化网络的激活函数

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

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

那么更深的模型呢?问题来了,对任何一个隐藏层而言,我们能否归一化α 值,深度学习文献中有一些争论,关于在激活函数之前是否应该将值 z^[2] 归一化,或是否应该在应用激活函数 a^[2] 后再规范值。实践中,经常做的是归一化z^[2],所以这就是我介绍的版本,我推荐其为默认选择,那下面就是Batch归一化的使用方法

在神经网络中,已知一些中间值,假设你有一些隐藏单元值,你要计算平均值,强调一下,所有这些都是针对$l$层,然后用正如你常用的那个公式计算方差,接着,你会取每个 z^(i) 值,使其规范化,方法如下,减去均值再除以标准偏差,为了使数值稳定,通常将 ε 作为分母,以防 σ=0 的情况。

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

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

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

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

5、将Batch Norm拟合进神经网络

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

假设你有一个这样的神经网络,我之前说过,你可以认为每个单元负责计算两件事。第一,它先计算z,然后应用其到激活函数中再计算a,所以我可以认为,每个圆圈代表着两步的计算过程。Batch归一化的做法是将 z^[1] 值进行Batch归一化,简称BN,此过程将由 β^[1] 和 γ^[1] 两参数控制,这一操作会给你一个新的规范化的 z^[1]值 ,然后将其输入激活函数中得到 a^[1]。其它层同理,需要强调的是Batch归一化是发生在计算 z 和 a 之间的。

对于应用Batch归一化的每一层而言。需要澄清的是,请注意,这里的这些 β( β^[1], β^[2]等等)和超参数 β没有任何关系!

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

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

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

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

类似的工作第二个第三个,上同样这样做,继续训练。

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

所以,如果你在使用Batch归一化,其实你可以消除这个参数( b^[l]),或者你也可以,暂时把它设置为0。

最后,请记住 z^[l] 的维数。

让我们总结一下关于如何用Batch归一化来应用梯度下降法。

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

6、Batch Norm为什么奏效?

为什么Batch归一化会起作用呢?

一个原因是,你已经看到如何归一化输入特征值 x ,使其均值为0,方差1,它又是怎样加速学习的,有一些从0到1而不是从1到1000的特征值,通过归一化所有的输入特征值 x ,以获得类似范围的值,可以加速学习。所以Batch归一化起的作用的原因,直观的一点就是,它在做类似的工作,但不仅仅对于这里的输入值,还有隐藏单元的值,这只是Batch归一化作用的冰山一角,还有些深层的原理,它会有助于你对Batch归一化的作用有更深的理解,让我们一起来看看吧。

Batch归一化有效的第二个原因是,它可以使权重比你的网络更滞后或更深层,比如,第10层的权重更能经受得住变化,相比于神经网络中前层的权重,比如第1层,为了解释我的意思,让我们来看看这个最生动形象的例子。

这是一个网络的训练,也许是个浅层网络,比如logistic回归或是一个神经网络,也许是个浅层网络,像这个回归函数。或一个深层网络,建立在我们著名的猫脸识别检测上,但假设你已经在所有黑猫的图像上训练了数据集,如果现在你要把此网络应用于有色猫,这种情况下,正面的例子不只是左边的黑猫,还有右边其它颜色的猫,那么你的cosfa可能适用的不会很好。

如果图像中,你的训练集是这个样子的,你的正面例子在这儿,反面例子在那儿(左图),但你试图把它们都统一于一个数据集,也许正面例子在这,反面例子在那儿(右图)。你也许无法期待,在左边训练得很好的模块,同样在右边也运行得很好,即使存在运行都很好的同一个函数,但你不会希望你的学习算法去发现绿色的决策边界,如果只看左边数据的话。

所以使你数据改变分布的这个想法,有个有点怪的名字“Covariate shift”,想法是这样的,如果你已经学习了 x 到 y 的映射,如果 x 的分布改变了,那么你可能需要重新训练你的学习算法。这种做法同样适用于,如果真实函数由 x 到 y 映射保持不变,正如此例中,因为真实函数是此图片是否是一只猫,训练你的函数的需要变得更加迫切,如果真实函数也改变,情况就更糟了。

Covariate shift”的问题怎么应用于神经网络呢?试想一个像这样的深度网络,让我们从这层(第三层)来看看学习过程。此网络已经学习了参数 w^[3] 和 b^[3] ,从第三隐藏层的角度来看,它从前层中取得一些值,接着它需要做些什么,使希望输出值 y^ 接近真实值 y 。

让我先遮住左边的部分,从第三隐藏层的角度来看,它得到一些值,称为a_{1}^[2], a_{2}^ [2] , a_{3}^ [2] ,a_{4}^[2] ,但这些值也可以是特征值 x_{1}, x_{2}, x_{3},x_{4} ,第三层隐藏层的工作是找到一种方式,使这些值映射到 y^ ,你可以想象做一些截断,所以这些参数 w^[3] 和 b^[3] 或 w^[4] 和 b^[4] 或 w^[5] 和 b^[5] ,也许是学习这些参数,所以网络做的不错,从左边我用黑色笔写的映射到输出值y^ 。

现在我们把网络的左边揭开,这个网络还有参数 w^[2] , b^[2] 和 w^[1] ,b^[1] ,如果这些参数改变,这些 a^[2]的值也会改变。所以从第三层隐藏层的角度来看,这些隐藏单元的值在不断地改变,所以它就有了“Covariate shift”的问题。

Batch归一化做的,是它减少了这些隐藏值分布变化的数量。如果是绘制这些隐藏的单元值的分布,也许这是重整值 z ,这其实是 z_{1}^[2] , z_{2}^[2] ,我要绘制两个值而不是四个值,以便我们设想为2DBatch归一化讲的是 z_{1}^[2] , z_{2}^[2] 的值可以改变,它们的确会改变,当神经网络在之前层中更新参数,Batch归一化可以确保无论其怎样变化 z_{1}^[2] , z_{2}^[2] 的均值和方差保持不变,所以即使 z_{1}^[2] , z_{2}^[2] 的值改变,至少他们的均值和方差也会是均值0,方差1,或不一定必须是均值0,方差1,而是由β^[2] 和 γ^[2] 决定的值。如果神经网络选择的话,可强制其为均值0,方差1,或其他任何均值和方差。但它做的是,它限制了在前层的参数更新,会影响数值分布的程度,第三层看到的这种情况,因此得到学习。

Batch归一化减少了输入值改变的问题,它的确使这些值变得更稳定,神经网络的之后层就会有更坚实的基础。即使使输入分布改变了一些,它会改变得更少。它做的是当前层保持学习,当改变时,迫使后层适应的程度减小了,你可以这样想,它减弱了前层参数的作用与后层参数的作用之间的联系,它使得网络每层都可以自己学习,稍稍独立于其它层,这有助于加速整个网络的学习。

所以,希望这能带给你更好的直觉,重点是Batch归一化的意思是,尤其从神经网络后层之一的角度而言,前层不会左右移动的那么多,因为它们被同样的均值和方差所限制,所以,这会使得后层的学习工作变得更容易些。

Batch归一化还有一个作用,它有轻微的正则化效果,Batch归一化中非直观的一件事是,每个mini-batch,在mini-batch计算中,由均值和方差缩放的,因为在mini-batch上计算的均值和方差,而不是在整个数据集上,均值和方差有一些小的噪声,因为它只在你的mini-batch上计算,比如64或128或256或更大的训练例子。因为均值和方差有一点小噪音,因为它只是由一小部分数据估计得出的。

所以和dropout相似,它往每个隐藏层的激活值上增加了噪音,dropout有增加噪音的方式,它使一个隐藏的单元,以一定的概率乘以0,以一定的概率乘以1,所以你的dropout含几重噪音,因为它乘以0或1。

对比而言,Batch归一化含几重噪音,因为标准偏差的缩放和减去均值带来的额外噪音。这里的均值和标准差的估计值也是有噪音的,所以类似于dropoutBatch归一化有轻微的正则化效果,因为给隐藏单元添加了噪音,这迫使后部单元不过分依赖任何一个隐藏单元,类似于dropout,它给隐藏层增加了噪音,因此有轻微的正则化效果。因为添加的噪音很微小,所以并不是巨大的正则化效果,你可以将Batch归一化和dropout一起使用,如果你想得到dropout更强大的正则化效果。

也许另一个轻微非直观的效果是,如果你应用了较大的mini-batch,对,比如说,你用了512而不是64,通过应用较大的min-batch,你减少了噪音,因此减少了正则化效果,这是dropout的一个奇怪的性质,就是应用较大的mini-batch可以减少正则化效果。

说到这儿,我会把Batch归一化当成一种正则化,这确实不是其目的,但有时它会对你的算法有额外的期望效应或非期望效应。但是不要把Batch归一化当作正则化,把它当作将你归一化隐藏单元激活值并加速学习的方式,我认为正则化几乎是一个意想不到的副作用。

所以希望这能让你更理解Batch归一化的工作,在我们结束Batch归一化的讨论之前,我想确保你还知道一个细节。Batch归一化一次只能处理一个mini-batch数据,它在mini-batch上计算均值和方差。所以测试时,你试图做出预测,试着评估神经网络,你也许没有mini-batch的例子,你也许一次只能进行一个简单的例子,所以测试时,你需要做一些不同的东西以确保你的预测有意义。

7、测试时的Batch Norm

Batch归一化将你的数据以mini-batch的形式逐一处理,但在测试时,你可能需要对每个样本逐一处理,我们来看一下怎样调整你的网络来做到这一点。

回想一下,在训练时,这些就是用来执行Batch归一化的等式。

请注意用于调节计算的 μ 和 σ 是在整个mini-batch上进行计算,但是在测试时,你可能不能将一个mini-batch中的6428或2056个样本同时处理,因此你需要用其它方式来得到 μ 和 σ ^2 ,而且如果你只有一个样本,一个样本的均值和方差没有意义。那么实际上,为了将你的神经网络运用于测试,就需要单独估算 μ 和 σ ^2 ,在典型的Batch归一化运用中,你需要用一个指数加权平均来估算,这个平均数涵盖了所有mini-batch

我们选择 l 层,假设我们有mini-batch,在为 l 层训练 X^{ 1}时,你就得到了 μ ,我还是把它写做第一个mini-batch和这一层的 μ 吧,。当你训练第二个mini-batch,在这一层和这个mini-batch中,你就会得到第二个 μ 值。然后在这一隐藏层的第三个mini-batch,你得到了第三个 μ 值。正如我们之前用的指数加权平均来计算Θ_1,Θ_2,Θ_3的均值,当时是试着计算当前气温的指数加权平均,你会这样来追踪你看到的这个均值向量的最新平均值,于是这个指数加权平均就成了你对这一隐藏层的 z 均值的估值。同样的,你可以用指数加权平均来追踪你在这一层的第一个mini-batch中所见的 σ^2 的值,以及第二个mini-batch中所见的σ ^2的值等等。因此在用不同的mini-batch训练神经网络的同时,能够得到你所查看的每一层的 μ 和 σ ^2的平均数的实时数值。

最后在测试时,对应这个等式,你只需要用你的 z 值来计算z_norm,用 μ 和 σ^2 的指数加权平均,用你手头的最新数值来做调整,然后你可以用左边我们刚算出来的 z_norm 和你在神经网络训练过程中得到的 β 和 γ 参数来计算你那个测试样本的zN值。

总结一下就是,在训练时, μ 和 σ^2 是在整个mini-batch上计算出来的包含了像是64或28或其它一定数量的样本,但在测试时,你可能需要逐一处理样本,方法是根据你的训练集估算 μ 和 σ^2,估算的方式有很多种,理论上你可以在最终的网络中运行整个训练集来得到 μ 和 σ^2 ,但在实际操作中,我们通常运用指数加权平均来追踪在训练过程中你看到的 μ 和 σ^2 的值。还可以用指数加权平均,有时也叫做流动平均来粗略估算 μ 和 σ^2 ,然后在测试中使用 μ 和 σ^2 的值来进行你所需要的隐藏单元 z 值的调整。在实践中,不管你用什么方式估算 μ 和 σ^2 ,这套过程都是比较稳健的,因此我不太会担心你具体的操作方式,而且如果你使用的是某种深度学习框架,通常会有默认的估算 μ 和 σ^2 的方式,应该一样会起到比较好的效果。但在实践中,任何合理的估算你的隐藏单元 z 值的均值和方差的方式,在测试中应该都会有效。

8、Softmax回归

到目前为止,我们讲到过的分类的例子都使用了二分分类,这种分类只有两种可能的标记0或1,这是一只猫或者不是一只猫,如果我们有多种可能的类型的话呢?有一种logistic回归的一般形式,叫做Softmax回归,能让你在试图识别某一分类时做出预测,或者说是多种分类中的一个,不只是识别两个分类,我们来一起看一下。

假设你不单需要识别猫,而是想识别猫,狗和小鸡,我把猫加做类1,狗为类2,小鸡是类3,如果不属于以上任何一类,就分到“其它”或者说“以上均不符合”这一类,我把它叫做类0。这里显示的图片及其对应的分类就是一个例子,这幅图片上是一只小鸡,所以是类3,猫是类1,狗是类2,我猜这是一只考拉,所以以上均不符合,那就是类0,下一个类3,以此类推。我们将会用符号表示,我会用大写的 C 来表示你的输入会被分入的类别总个数,在这个例子中,我们有4种可能的类别,包括“其它”或“以上均不符合”这一类。当有4个分类时,指示类别的数字,就是从0到 C-1 ,换句话说就是0、1、2、3。

在这个例子中,我们将建立一个神经网络,其输出层有4个,或者说 C 个输出单元,因此 n ,即输出层也就是 L 层的单元数量,等于4,或者一般而言等于 C 。我们想要输出层单元的数字告诉我们这4种类型中每个的概率有多大,所以这里的第一个节点(最后输出的第1个方格+圆圈)输出的应该是或者说我们希望它输出“其它”类的概率。在输入 X 的情况下,这个(最后输出的第2个方格+圆圈)会输出猫的概率。在输入 X  的情况下,这个会输出狗的概率(最后输出的第3个方格+圆圈)。在输入 X 的情况下,输出小鸡的概率(最后输出的第4个方格+圆圈),我把小鸡缩写为bcbaby chick)。因此这里的 y^ 将是一个 4×1 维向量,因为它必须输出四个数字,给你这四种概率,因为它们加起来应该等于1,输出中的四个数字加起来应该等于1。

让你的网络做到这一点的标准模型要用到Softmax层,以及输出层来生成输出,让我把式子写下来,然后回过头来,就会对Softmax的作用有一点感觉了。

在神经网络的最后一层,你将会像往常一样计算各层的线性部分, z^[l] 这是最后一层的 z 变量,记住这是大写 L 层,和往常一样,计算方法是z^[l] = W^[l] a^[L-1] + b^[l],算出了z 之后,你需要应用Softmax激活函数,这个激活函数对于Softmax层而言有些不同,它的作用是这样的。如下

那四个数字就是它属于类0,类1,类2,类3的可能性。它们总和为1

神经网络的输出 a^[l] ,也就是 y^,是一个4×1维向量。

如果我们总结一下从 z^[l] 到a^[l] 的计算步骤,整个计算过程,从计算幂到得出临时变量 t ,再归一化,我们可以将此概括为一个Softmax激活函数。设 a^[l] = g^[l] (z^[l]) ,这一激活函数的与众不同之处在于,这个激活函数 g  需要输入一个4×1维向量,然后输出一个4×1维向量。之前,我们的激活函数都是接受单行数值输入,例如SigmoidReLu激活函数,输入一个实数,输出一个实数。Softmax激活函数的特殊之处在于,因为需要将所有可能的输出归一化,就需要输入一个向量,最后输出一个向量。

那么Softmax分类器还可以代表其它的什么东西么?我来举几个例子,你有两个输入 x_1 ,x_2 ,它们直接输入到Softmax层,它有三四个或者更多的输出节点,输出y^ ,我将向你展示一个没有隐藏层的神经网络,它所做的就是计算 z^[1] = W^[1]x + b^[1],而输出的出a^[l],或者说y^ ,a^{l]  = y = g(z^[1]),就是 z^[1] 的Softmax激活函数,这个没有隐藏层的神经网络应该能让你对Softmax函数能够代表的东西有所了解。

这个例子中(左边图),原始输入只有x_1和x_2,一个C=3个输出分类的Softmax层能够代表这种类型的决策边界,请注意这是几条线性决策边界,但这使得它能够将数据分到3个类别中,在这张图表中,我们所做的是选择这张图中显示的训练集,用数据的3种输出标签来训练Softmax分类器,图中的颜色显示了Softmax分类器的输出的阈值,输入的着色是基于三种输出中概率最高的那种。因此我们可以看到这是logistic回归的一般形式,有类似线性的决策边界,但有超过两个分类,分类不只有0和1,而是可以是0,1或2。

这是(中间图)另一个Softmax分类器可以代表的决策边界的例子,用有三个分类的数据集来训练,这里(右边图)还有一个。对吧,但是直觉告诉我们,任何两个分类之间的决策边界都是线性的,这就是为什么你看到,比如这里黄色和红色分类之间的决策边界是线性边界,紫色和红色之间的也是线性边界,紫色和黄色之间的也是线性决策边界,但它能用这些不同的线性函数来把空间分成三类。

我们来看一下更多分类的例子,这个例子中(左边图) C=4 ,因此这个绿色分类和Softmax仍旧可以代表多种分类之间的这些类型的线性决策边界。另一个例子(中间图)是 C=5 类,最后一个例子(右边图)是 C=6 ,这显示了Softmax分类器在没有隐藏层的情况下能够做到的事情,当然更深的神经网络会有 x ,然后是一些隐藏单元,以及更多隐藏单元等等,你就可以学习更复杂的非线性决策边界,来区分多种不同分类。

9、训练一个Softmax分类器

上节课我们学习了Softmax层和Softmax激活函数,本节课你将更深入地了解Softmax分类,并学习如何训练一个使用了Softmax层的模型。

回忆一下我们之前举的的例子

输出是这样的

简单来说就是用临时变量 t 将它归一化,使总和为1,于是这就变成了 a^[L],你注意到向量 z 中,最大的元素是5,而最大的概率也就是第一种概率。

Softmax这个名称的来源是与所谓hardmax对比,hardmax函数会观察 z 的元素,然后在 z 中最大元素的位置放上1,其它位置放上0,所这是一个hard max,也就是最大的元素的输出为1,其它的输出都为0。与之相反,Softmax所做的从 z 到这些概率的映射更为温和,我不知道这是不是一个好名字,但至少这就是softmax这一名称背后所包含的想法,与hardmax正好相反。

有一点我没有细讲,但之前已经提到过的,就是Softmax回归或Softmax激活函数将logistic激活函数推广到 C 类,而不仅仅是两类,结果就是如果 C=2 ,那么 C=2 的Softmax实际上变回了logistic回归,我不会在这个视频中给出证明,但是大致的证明思路是这样的,如果 C=2 ,并且你应用了Softmax,那么输出层 a^[L] 将会输出两个数字,如果 C=2 的话,也许输出0.842和0.158,对吧?这两个数字加起来要等于1,因为它们的和必须为1,其实它们是冗余的,也许你不需要计算两个,而只需要计算其中一个,结果就是你最终计算那个数字的方式又回到了logistic回归计算单个输出的方式。这算不上是一个证明,但我们可以从中得出结论,Softmax回归将logistic回归推广到了两种分类以上。

接下来我们来看怎样训练带有Softmax输出层的神经网络,具体而言,我们先定义训练神经网络使会用到的损失函数。

这就意味着,如果你的学习算法试图将它变小,因为梯度下降法是用来减少训练集的损失的,要使它变小的唯一方式就是使 y^ 尽可能大,因为这些是概率,所以不可能比1大,但这的确也讲得通,因为在这个例子中 x 是猫的图片,你就需要这项输出的概率尽可能地大

概括来讲,损失函数所做的就是它找到你的训练集中的真实类别,然后试图使该类别相应的概率尽可能地高,如果你熟悉统计学中最大似然估计,这其实就是最大似然估计的一种形式。但如果你不知道那是什么意思,也不用担心,用我们刚刚讲过的算法思维也足够了。

这是单个训练样本的损失,整个训练集的损失 J 又如何呢?也就是设定参数的代价之类的,还有各种形式的偏差的代价,它的定义你大致也能猜到,就是整个训练集损失的总和,把你的训练算法对所有训练样本的预测都加起来,因此你要做的就是用梯度下降法,使这里的损失最小化。

最后还有一个实现细节,注意因为 C=4 , y 是一个4×1向量, y 也是一个4×1向量,

最后我们来看一下,在有Softmax输出层时如何实现梯度下降法,这个输出层会计算 z^[l],它是 C×1 维的,在这个例子中是4×1,然后你用Softmax激活函数来得到 a^[l] 或者说 y ,然后又能由此计算出损失。我们已经讲了如何实现神经网络前向传播的步骤,来得到这些输出,并计算损失,那么反向传播步骤或者梯度下降法又如何呢?其实初始化反向传播所需要的关键步骤或者说关键方程是这个表达式 dz^[l] = y^ -y,你可以用 y^ 这个4×1向量减去 y 这个4×1向量,你可以看到这些都会是4×1向量,当你有4个分类时,在一般情况下就是 C×1 ,这符合我们对 dz 的一般定义,这是对 z^[l] 损失函数的偏导数

在这周的初级练习中,我们将开始使用一种深度学习编程框架,对于这些编程框架,通常你只需要专注于把前向传播做对,只要你将它指明为编程框架,前向传播,它自己会弄明白怎样反向传播,会帮你实现反向传播,所以这个表达式值得牢记(dz^[l] = y^ -y),如果你需要从头开始,实现Softmax回归或者Softmax分类,但其实在这周的初级练习中你不会用到它,因为编程框架会帮你搞定导数计算。

10、深度学习框架

你已经差不多从零开始学习了使用PythonNumPy实现深度学习算法,很高兴你这样做了,因为我希望你理解这些深度学习算法实际上在做什么。但你会发现,除非应用更复杂的模型,例如卷积神经网络,或者循环神经网络,或者当你开始应用很大的模型,否则它就越来越不实用了,至少对大多数人而言,从零开始全部靠自己实现并不现实。

幸运的是,现在有很多好的深度学习软件框架,可以帮助你实现这些模型。类比一下,我猜你知道如何做矩阵乘法,你还应该知道如何编程实现两个矩阵相乘,但是当你在建很大的应用时,你很可能不想用自己的矩阵乘法函数,而是想要访问一个数值线性代数库,它会更高效,但如果你明白两个矩阵相乘是怎么回事还是挺有用的。我认为现在深度学习已经很成熟了,利用一些深度学习框架会更加实用,会使你的工作更加有效,那就让我们来看下有哪些框架。

现在有许多深度学习框架,能让实现神经网络变得更简单,我们来讲主要的几个。每个框架都针对某一用户或开发群体的,我觉得这里的每一个框架都是某类应用的可靠选择,有很多人写文章比较这些深度学习框架,以及这些深度学习框架发展得有多好,而且因为这些框架往往不断进化,每个月都在进步,如果你想看看关于这些框架的优劣之处的讨论,我留给你自己去网上搜索,但我认为很多框架都在很快进步,越来越好,因此我就不做强烈推荐了,而是与你分享推荐一下选择框架的标准。

一个重要的标准就是便于编程,这既包括神经网络的开发和迭代,还包括为产品进行配置,为了成千上百万,甚至上亿用户的实际使用,取决于你想要做什么。

第二个重要的标准是运行速度,特别是训练大数据集时,一些框架能让你更高效地运行和训练神经网络

还有一个标准人们不常提到,但我觉得很重要,那就是这个框架是否真的开放,要是一个框架真的开放,它不仅需要开源,而且需要良好的管理。不幸的是,在软件行业中,一些公司有开源软件的历史,但是公司保持着对软件的全权控制,当几年时间过去,人们开始使用他们的软件时,一些公司开始逐渐关闭曾经开放的资源,或将功能转移到他们专营的云服务中。因此我会注意的一件事就是你能否相信这个框架能长时间保持开源,而不是在一家公司的控制之下,它未来有可能出于某种原因选择停止开源,即便现在这个软件是以开源的形式发布的。但至少在短期内,取决于你对语言的偏好,看你更喜欢PythonJava还是 C++ 或者其它什么,也取决于你在开发的应用,是计算机视觉,还是自然语言处理或者线上广告,等等,我认为这里的多个框架都是很好的选择。

通过提供比数值线性代数库更高程度的抽象化,这里的每一个程序框架都能让你在开发深度机器学习应用时更加高效。

11、TensorFlow

有很多很棒的深度学习编程框架,其中一个是TensorFlow,我很期待帮助你开始学习使用TensorFlow,我想在本节课中向你展示TensorFlow程序的基本结构

先提一个启发性的问题,假设你有一个损失函数 J 需要最小化,在本例中,我将使用这个高度简化的损失函数, Jw= w^2 -10w+25 ,这就是损失函数,也许你已经注意到该函数其实就是 (w -5)^2,如果你把这个二次方式子展开就得到了上面的表达式,所以使它最小的 w 值是5,但假设我们不知道这点,你只有这个函数,我们来看一下怎样用TensorFlow将其最小化,因为一个非常类似的程序结构可以用来训练神经网络。其中可以有一些复杂的损失函数 J(w,b) 取决于你的神经网络的所有参数,然后类似的,你就能用TensorFlow自动找到使损失函数最小的 w 和 b 的值。但让我们先从左边这个更简单的例子入手。

我在我的Jupyter notebook中运行Python

代码如下:

import numpy as np
import tensorflow as tf
#导入TensorFloww = tf.Variable(0,dtype = tf.float32)
#接下来,让我们定义参数w,在TensorFlow中,你要用tf.Variable()来定义参数#然后我们定义损失函数:cost = tf.add(tf.add(w**2,tf.multiply(- 10.,w)),25)
#然后我们定义损失函数J
然后我们再写:train = tf.train.GradientDescentOptimizer(0.01).minimize(cost)
#(让我们用0.01的学习率,目标是最小化损失)。#最后下面的几行是惯用表达式:init = tf.global_variables_initializer()session = tf.Session()#这样就开启了一个TensorFlow session。session.run(init)#来初始化全局变量。#然后让TensorFlow评估一个变量,我们要用到:session.run(w)#上面的这一行将w初始化为0,并定义损失函数,我们定义train为学习算法,它用梯度下降法优化器使损失函数最小化,但实际上我们还没有运行学习算法,所以#上面的这一行将w初始化为0,并定义损失函数,我们定义train为学习算法,它用梯度下降法优化器使损失函数最小化,但实际上我们还没有运行学习算法,所以session.run(w)评估了w,让我::print(session.run(w))

如果我们运行这个,它评估 w 等于0,因为我们什么都还没运行

$session.run(train),它所做的就是运行一步梯度下降法。
#接下来在运行了一步梯度下降法后,让我们评估一下w的值,再print:print(session.run(w))
#在一步梯度下降法之后,w现在是0.1。

这是运行了梯度下降的1000次迭代,最后 w 变成了4.99999,记不记得我们说 (w -5)^2最小化,因此 w 的最优值是5,这个结果已经很接近了。

希望这个让你对TensorFlow程序的大致结构有了了解,当你做编程练习,使用更多TensorFlow代码时,我这里用到的一些函数你会熟悉起来,这里有个地方要注意, w 是我们想要优化的参数,因此将它称为变量,注意我们需要做的就是定义一个损失函数,使用这些add和multiply之类的函数。TensorFlow知道如何对add和mutiply,还有其它函数求导,这就是为什么你只需基本实现前向传播,它能弄明白如何做反向传播和梯度计算,因为它已经内置在add,multiply和平方函数中。

对了,要是觉得这种写法不好看的话,TensorFlow其实还重载了一般的加减运算等等,因此你也可以把$cost$写成更好看的形式,把之前的cost标成注释,重新运行,得到了同样的结果。

一旦 w 被称为TensorFlow变量,平方,乘法和加减运算都重载了,因此你不必使用上面这种不好看的句法。

TensorFlow还有一个特点,我想告诉你,那就是这个例子将 w 的一个固定函数最小化了。如果你想要最小化的函数是训练集函数又如何呢?不管你有什么训练数据 x ,当你训练神经网络时,训练数据 x 会改变,那么如何把训练数据加入TensorFlow程序呢?

我会定义 x ,把它想做扮演训练数据的角色,事实上训练数据有 x 和 y ,但这个例子中只有 x ,把 x 定义为:

x = tf.placeholder(tf.float32,[3,1]),让它成为 [3,1] 数组,我要做的就是,因为 cost 这个二次方程的三项前有固定的系数,它是 w^2 +10w + 25 ,我们可以把这些数字1,-10和25变成数据,我要做的就是把 cost 替换成:

cost = x[0][0]*w**2 +x[1][0]*w + x[2][0],现在 x 变成了控制这个二次函数系数的数据,这个placeholder函数告诉TensorFlow,你稍后会为 x 提供数值。

让我们再定义一个数组,coefficient = np.array([[1.],[-10.],[25.]]),这就是我们要接入 x 的数据。最后我们需要用某种方式把这个系数数组接入变量 x ,做到这一点的句法是,在训练这一步中,要提供给 x 的数值,我在这里设置:

feed_dict = {x:coefficients}

好了,希望没有语法错误,我们重新运行它,希望得到和之前一样的结果。

现在如果你想改变这个二次函数的系数,假设你把:

coefficient = np.array([[1.],[-10.],[25.]])

改为:coefficient = np.array([[1.],[-20.],[100.]])

现在这个函数就变成了(w -10)^2 , 如果我重新运行,希望我得到的使(w -10)^2最小化的 w 值为10,让我们看一下,很好,在梯度下降1000次迭代之后,我们得到接近10的 w 。

在你做编程练习时,见到更多的是,TensorFlow中的placeholder是一个你之后会赋值的变量,这种方式便于把训练数据加入损失方程,把数据加入损失方程用的是这个句法,当你运行训练迭代,用feed_dict来让x=coefficients。如果你在做mini-batch梯度下降,在每次迭代时,你需要插入不同的mini-batch,那么每次迭代,你就用feed_dict来喂入训练集的不同子集,把不同的mini-batch喂入损失函数需要数据的地方。

希望这让你了解了TensorFlow能做什么,让它如此强大的是,你只需说明如何计算损失函数,它就能求导,而且用一两行代码就能运用梯度优化器,Adam优化器或者其他优化器。

还有最后一点我想提一下,这三行(蓝色大括号部分)在TensorFlow里是符合表达习惯的,有些程序员会用这种形式来替代,作用基本上是一样的。

但这个with结构也会在很多TensorFlow程序中用到,它的意思基本上和左边的相同,但是Python中的with命令更方便清理,以防在执行这个内循环时出现错误或例外。所以你也会在编程练习中看到这种写法。那么这个代码到底做了什么呢?让我们看这个等式:

TensorFlow程序的核心是计算损失函数,然后TensorFlow自动计算出导数,以及如何最小化损失,因此这个等式或者这行代码所做的就是让TensorFlow建立计算图,计算图所做的就是取 x[0][0] ,取 w ,然后将它平方,然后 x[0][0] 和 w^2 相乘,你就得到了 x[0][0]*w^2 ,以此类推,最终整个建立起来计算 cost = [0][0]*w**2 + x[1][0]*w + x[2][0] ,最后你得到了损失函数。

TensorFlow的优点在于,通过用这个计算损失,计算图基本实现前向传播,TensorFlow已经内置了所有必要的反向函数,回忆一下训练深度神经网络时的一组前向函数和一组反向函数,而像TensorFlow之类的编程框架已经内置了必要的反向函数,这也是为什么通过内置函数来计算前向函数,它也能自动用反向函数来实现反向传播,即便函数非常复杂,再帮你计算导数,这就是为什么你不需要明确实现反向传播,这是编程框架能帮你变得高效的原因之一。

如果你看TensorFlow的使用说明,我只是指出TensorFlow的说明用了一套和我不太一样的符号来画计算图,它用了 x[0][0]​ , w​ ,然后它不是写出值,想这里的 w^2 ,TensorFlow使用说明倾向于只写运算符,所以这里就是平方运算,而这两者一起指向乘法运算,以此类推,然后在最后的节点,我猜应该是一个将 x[2][0]​ 加上去得到最终值的加法运算。

为本课程起见,我认为计算图用第一种方式会更容易理解,但是如果你去看TensorFlow的使用说明,如果你看到说明里的计算图,你会看到另一种表示方式,节点都用运算来标记而不是值,但这两种呈现方式表达的是同样的计算图。

在编程框架中你可以用一行代码做很多事情,例如,你不想用梯度下降法,而是想用Adam优化器,你只要改变这行代码,就能很快换掉它,换成更好的优化算法。所有现代深度学习编程框架都支持这样的功能,让你很容易就能编写复杂的神经网络。

改善深层神经网络:超参数调试、正则化以及优化(三)相关推荐

  1. 2020-6-9 吴恩达-改善深层NN-w3 超参数调试(3.3 超参数训练的实践:Pandas(资源少,一次一个模型) VS Caviar(资源多,一次多个模型))

    1.视频网站:mooc慕课https://mooc.study.163.com/university/deeplearning_ai#/c 2.详细笔记网站(中文):http://www.ai-sta ...

  2. 02.改善深层神经网络:超参数调试、正则化以及优化 W3. 超参数调试、Batch Norm和程序框架(作业:TensorFlow教程+数字手势预测)

    文章目录 1. 探索TensorFlow库 1.1 线性函数 1.2 计算 sigmoid 1.3 计算损失函数 1.4 One_Hot 编码 1.5 用0,1初始化 2. 用TensorFlow建立 ...

  3. 02.改善深层神经网络:超参数调试、正则化以及优化 W3. 超参数调试、Batch Norm和程序框架

    文章目录 1. 调试处理 2. 为超参数选择合适的范围 3. 超参数调试的实践 4. 归一化网络的激活函数 5. 将 Batch Norm 拟合进神经网络 6. Batch Norm 为什么奏效 7. ...

  4. 02.改善深层神经网络:超参数调试、正则化以及优化 W2.优化算法(作业:优化方法)

    文章目录 1. 梯度下降 2. mini-Batch 梯度下降 3. 动量 4. Adam 5. 不同优化算法下的模型 5.1 Mini-batch梯度下降 5.2 带动量的Mini-batch梯度下 ...

  5. 02.改善深层神经网络:超参数调试、正则化以及优化 W2.优化算法

    文章目录 1. Mini-batch 梯度下降 2. 理解 mini-batch 梯度下降 3. 指数加权平均数 4. 理解指数加权平均数 5. 指数加权平均的偏差修正 6. 动量Momentum梯度 ...

  6. 02.改善深层神经网络:超参数调试、正则化以及优化 W1.深度学习的实践层面(作业:初始化+正则化+梯度检验)

    文章目录 作业1:初始化 1. 神经网络模型 2. 使用 0 初始化 3. 随机初始化 4. He 初始化 作业2:正则化 1. 无正则化模型 2. L2 正则化 3. DropOut 正则化 3.1 ...

  7. 02.改善深层神经网络:超参数调试、正则化以及优化 W1.深度学习的实践层面

    文章目录 1. 训练,验证,测试集 2. 偏差,方差 3. 机器学习基础 4. 正则化 5. 为什么正则化预防过拟合 6. dropout(随机失活)正则化 7. 理解 dropout 8. 其他正则 ...

  8. 吴恩达深度学习之二《改善深层神经网络:超参数调试、正则化以及优化》学习笔记

    一.深度学习的实用层面 1.1 训练/开发/测试集 机器学习时代,数据集很小,可能100.1000.10000条,这种级别.可以按 70%.30% 划分训练集和测试集,训练后直接用测试集评估.或者按 ...

  9. 深度学习笔记第二门课 改善深层神经网络 第三周 超参数调试、Batch正则化和程序框架...

    本文是吴恩达老师的深度学习课程[1]笔记部分. 作者:黄海广[2] 主要编写人员:黄海广.林兴木(第四所有底稿,第五课第一二周,第三周前三节).祝彦森:(第三课所有底稿).贺志尧(第五课第三周底稿). ...

最新文章

  1. 60 Permutation Sequence
  2. 促进新一代人工智能产业发展三年行动计划_浙江提出冷链物流创新发展三年行动计划 力争带动产业投资约1000亿元...
  3. 官方wdpc安装文档,推荐RPM包安装
  4. 获取python包的路径
  5. Linux系统管理(7)——Linux单用户模式详解 及应用场景
  6. 2020 年,嵌入式开发工程师的两大必知必会!
  7. 【手把手】制作一个简单的HTML网页
  8. Matlab——指派问题
  9. JavaScript 注册登录页面的简单实现
  10. python爬取微博内容_python如何抓取新浪微博的微博内容!
  11. 用Python走入史学经典《三国演义》中的社交网络
  12. python tensorflow 文本提取_用RNN构建文本生成器(TensorFlow Eager+ tf.keras)
  13. 徐磊英语语法整理1-3 词性,语序
  14. python Numpy模块汇总(字母排序) 备注:内容很多,用control/command(Mac系统)+ F可以在网页内关键词查找,希望你能找到想要的内容
  15. logistic逻辑回归公式推导及R语言实现
  16. 全自动调节灯光强度的实现(仿真+程序+文档)
  17. Windows 10 安装 Android 13版本的安卓子系统(带 Google Play 商店和 Magisk) 2210.40000.7.0
  18. poi导入excel日期处理_POI处理Excel中各种日期格式问题
  19. Struts.xml中加不加type=redirect
  20. go的beego搭建

热门文章

  1. 树莓派安装teamview
  2. STM32关闭PWM输出时,让IO输出固定高或低电平的方法。
  3. 网络攻防技术——OSI安全体系
  4. 如何开启浏览器硬件加速
  5. 【计算机网络-数据链路层】介质访问控制协议(MAC协议)
  6. code 128 npm
  7. DICOM-RT:放疗系统的坐标系统DICOM-RT Coordinate System
  8. 更改Git 服务器 IP 地址并更新Git项目
  9. Go rpc调用的返回值
  10. 【图像处理】双三次插值(Bicubic interpolation)原理及matlab简易版代码