吴恩达改善深层神经网络章节笔记(三)——参数调试和Batch Normalize


视频课程链接:
https://www.bilibili.com/video/BV1FT4y1E74V?
笔记参考链接:
https://blog.csdn.net/weixin_36815313/article/details/105728919

1. 调试处理 (Tuning Process)

神经网络的改变会涉及到许多不同超参数的设置。超参数调试的优先级如下:

  • 第一优先级
    • 学习率 α \alpha α
  • 第二优先级
    • Momentum参数 β \beta β(一般取0.9)
    • mini-batch的大小
    • 隐藏单元的数量
  • 第三优先级
    • 神经网络的层数
    • 学习率衰减系数
  • 第四优先级
    • Adam算法参数 β 1 \beta1 β1(一般取0.9)
    • Adam算法参数 β 2 \beta2 β2(一般取0.999)
    • 偏置项 ϵ \epsilon ϵ(一般取 1 0 − 8 10^{-8} 108

在这里插入图片描述

在早一代的机器学习算法中,如果你有两个超参数,这里称之为超参1,超参2,常见的做法是在网格中取样点,然后系统地研究这些数值(如上图)。
在这里插入图片描述

在深度学习领域,我们常用的方法是随机选择点(如上图),你可以选择同等数量的点,接着用这些随机取的点试验超参数的效果。之所以这么做是因为,对于你要解决的问题而言,你很难提前知道哪个超参数最重要。
在这里插入图片描述

实际上,你搜索的超参数可能不止两个。假如你有三个超参数,这时搜索的不是一个方格,而是一个立方体(如上图),超参3代表第三维,接着在三维立方体中取值,你会试验更多的值。
在这里插入图片描述

当你给超参数取值时,另一个惯例是采用由粗糙到精细的策略。
以二维的超参数为例,对超参数进行取值,也许你会发现效果最好的某个点,也许这个点周围的其他一些点效果也很好,那在接下来要做的是放大这块小区域(小蓝色方框),然后在其中更密集得取值或随机取值,聚集更多的资源,在这个蓝色的方格中搜索。如果你怀疑这些超参数在这个区域的最优结果,那在整个的方格中进行粗略搜索后,你会知道接下来应该聚焦到更小的方格中。在更小的方格中,你可以更密集地取点,因此这种从粗到细的搜索也经常使用。
通过试验超参数的不同取值,你可以选择对训练集目标而言的最优值,或对于开发集而言的最优值,或在超参搜索过程中你最想优化的东西。

2. 为超参数选择合适的范围 (Using an Appropriate Scale to Pick Hyperparameters)

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

2.1 线性轴标度

在这里插入图片描述

假设你要选取隐藏单元的数量 n [ l ] n^{[l]} n[l],超参数的取值范围是 [ 50 , 100 ] [50,100] [50,100]。在这种情况下,做一条从50-100的数轴,对其随机取点,这是一个搜索特定超参数较为直观的方式。
在这里插入图片描述

如果你要选取神经网络的层数,假设层数为2到4中的某个值,因此可以按顺序2、3、4随机均匀取样,或者应用网格搜索,你会觉得2、3、4这三个数值是合理的。
这是几个在你考虑范围内随机均匀取值的例子,这些取值还比较合理,但对某些超参数而言不适用。

2.2 对数轴标度

在这里插入图片描述

假设你在搜索超参数 α \alpha α(学习率),其取值范围可能在 [ 0.0001 , 1 ] [0.0001,1] [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之间,就会有更多的搜索资源可用。
对数标尺转化在Python中的实现方法:

r = -4 * np.random.rand()
a = np.power(10,r)

np.random.rand()的作用是返回一个取值范围在 [ 0 , 1 ) [0,1) [0,1)内的随机样本值,从而可以得到 r ∈ [ − 4 , 0 ) r\in[-4,0) r[4,0),那么 a ∈ [ 1 0 − 4 , 1 0 0 ) a\in[10^{-4},10^0) a[104,100),即 a ∈ [ 0.0001 , 1 ) a\in[0.0001,1) a[0.0001,1)
如果你在 1 0 a 10^a 10a 1 0 b 10^b 10b之间取值,在此例中, 1 0 a = 0.0001 10^a=0.0001 10a=0.0001,因此可以通过 a = l g 0.0001 a=lg{0.0001} a=lg0.0001算出 a a a的值,即-4,同理可以算出 b b b的值 b = l g 1 b=lg{1} b=lg1,即0。你要做的就是在 [ a , b ] [a,b] [a,b]区间随机均匀地给 r r r取值,然后设置 a a a的值。
在这里插入图片描述

另一个例子是给 β \beta β取值,用于计算指数的加权平均值。假设 β \beta β的取值范围是 [ 0.9 , 0.999 ] [0.9,0.999] [0.90.999]。当计算指数的加权平均值时, β \beta β取0.9就相当于在10个值中计算平均值,而取0.999则相当于在1000个值中取平均。因此我们要探究的是 1 − β \pmb{1-\beta} 1β1β1β,这个值的取值范围在 [ 0.1 , 0.001 ] [0.1,0.001] [0.1,0.001]内,因此使用对数标尺,0.1对应的是 1 0 − 1 10^{-1} 101,0.001对应的是 1 0 − 3 10^{-3} 103,所以你要做的就是在 [ − 3 , − 1 ] [-3,-1] [3,1]里随机均匀的给 r r 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区间搜索所耗费的一样多。
至于为什么不使用线性轴,这是因为 β \pmb{\beta} βββ接近1时,所得结果的灵敏度会变化,即使 β \pmb{\beta} βββ有微小的变化。假设 β \beta β在0.9到0.9005之间取值,根据公式 1 1 − β \frac{1}{1-\beta} 1β1可知,在这个范围内取值就相当于大概10个值取平均,因此你的结果几乎不会变化。而 β \beta β值如果在0.999到0.9995之间,这会对你的算法产生巨大影响。当 β \beta β取0.999,这相当于对1000个值取平均,当 β \beta β取0.9995,这就相当于对2000个值取平均。所以整个取值过程中,你需要更加密集地取值。

3. 超参数训练实战:Pandas vs. Caviar (Hyperparameters Tuning in Practice: Pandas vs. Caviar)

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

3.1 照看一个模型 (Babysitting one model)

在这里插入图片描述

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

3.2 同时训练多个模型 (Training many models in parallel)

在这里插入图片描述

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

4. 归一化网络的激活函数 (Normalizing Activations in a Network)

4.1 Batch归一化的作用

在深度学习兴起后,最重要的一个思想是它的一种算法,叫做Batch归一化Batch归一化会使你的参数搜索问题变得很容易,使神经网络对超参数的选择更加稳定,超参数的范围会更加庞大,工作效果也很好,也会使你的训练更加容易,甚至是深层网络。
在这里插入图片描述

当你训练一个神经网络模型时,归一化输入特征可以加快学习过程。通过计算平均值 μ = 1 m ∑ x ( i ) \mu=\frac{1}{m}\sum{x^{(i)}} μ=m1x(i),然后从训练集中减去平均值 x = x − μ x=x-\mu x=xμ,计算方差 σ 2 = 1 m ∑ ( x ( i ) ) 2 \sigma^2=\frac{1}{m}\sum{(x^{(i)})^2} σ2=m1(x(i))2,接着根据方差归一化你的输入数据集 x = x / σ 2 x=x / \sigma^2 x=x/σ2。在之前的章节中了解到,通过归一化可以将学习问题的轮廓从扁平状变成圆形,更易于算法优化。所以对于logistic回归和神经网络的归一化输入特征值而言,这是非常有效的。
在这里插入图片描述

但是我们以前在神经网络训练中,只是对输入层数据进行归一化处理,却没有在中间层进行归一化处理。虽然我们对输入数据进行了归一化处理,但是输入数据经过 σ ( W T X + b ) σ(W^TX+b) σ(WTX+b)这样的矩阵乘法以及非线性运算之后,其数据分布很可能被改变,而随着深度网络的多层运算之后,数据分布的变化将越来越大。
因此如果你想训练这些参数,比如 w [ 3 ] , b [ 3 ] w^{[3]},b^{[3]} w[3]b[3],那么归一化 a [ 2 ] a^{[2]} a[2]的平均值和方差,从而使 w [ 3 ] , b [ 3 ] w^{[3]},b^{[3]} w[3]b[3]的训练更有效率。尽管严格来说,我们真正归一化的不是 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],我推荐其为默认选择。

4.2 Batch归一化的使用方法

在神经网络中,假设隐藏层单元 z [ l ] ( i ) z^{[l](i)} z[l](i)已知,其中 i ∈ [ 1 , m ] i\in[1,m] i[1,m]。下面的公式都是针对第 l l l层单元,但为了简化符号,因此省略 [ l ] [l] [l]
首先,取每个 z ( i ) z^{(i)} z(i)值,使其规范化。方法如下,计算 z ( i ) z^{(i)} z(i)的均值,再将每个 z ( i ) z^{(i)} z(i)值减去均值,除以标准差。为了使数值稳定,通常在分母加上 ϵ \epsilon ϵ,以防 σ = 0 \sigma=0 σ=0的情况。 μ = 1 m ∑ i = 0 m z ( i ) \mu=\frac{1}{m}\sum_{i=0}^{m} {z^{(i)}} μ=m1i=0mz(i) σ 2 = 1 m ∑ i = 0 m ( z ( i ) − μ ) 2 \sigma^2=\frac{1}{m} \sum_{i=0}^{m} {(z^{(i)}-\mu)^2} σ2=m1i=0m(z(i)μ)2 z n o r m ( i ) = z ( i ) − μ σ 2 + ϵ z_{norm}^{(i)}=\frac{z^{(i)}-\mu}{\sqrt{\sigma^2+\epsilon}} znorm(i)=σ2+ϵ z(i)μ 该批次的数据 z ( i ) z^{(i)} z(i)经过规范化后,满足正态分布,此时 z z z的每一个分量都满足均值为0和方差为1。但是归一化后的 z z z基本会被限制在正态分布下,使得网络的表达能力下降,所以接下来我们所要做的就是尺度变换和偏移 z ~ ( i ) = γ z n o r m ( i ) + β \tilde{z}^{(i)}=\gamma z^{(i)}_{norm}+\beta z~(i)=γznorm(i)+β 它的直观作用是,将 z n o r m ( i ) z_{norm}^{(i)} znorm(i)乘以 γ γ γ调整数值大小,再加上 β β β增加偏移后得到 z ~ ( i ) \tilde{z}^{(i)} z~(i),这里的 γ γ γ是尺度因子, β β β是平移因子。如果 γ = σ 2 + ϵ \gamma=\sqrt{\sigma^2+\epsilon} γ=σ2+ϵ (即 z n o r m ( i ) = z ( i ) − μ σ 2 + ϵ z^{(i)}_{norm}=\frac{z^{(i)}-\mu}{\sqrt{\sigma^2+\epsilon}} znorm(i)=σ2+ϵ z(i)μ中的分母项), β \beta β等于 μ \mu μ(这里的 μ \mu μ就是 z n o r m ( i ) = z ( i ) − μ σ 2 + ϵ z^{(i)}_{norm}=\frac{z^{(i)}-\mu}{\sqrt{\sigma^2+\epsilon}} znorm(i)=σ2+ϵ z(i)μ中的 μ \mu μ),那么 z ~ ( i ) = z ( i ) \tilde{z}^{(i)}=z^{(i)} z~(i)=z(i)。因此, γ z n o r m ( i ) + β γ \gamma z^{(i)}_{norm}+\betaγ γznorm(i)+βγ的实际作用在于,通过对 γ \pmb{\gamma} γγγ β \pmb{\beta} βββ合理设定,可以构造满足其它均值和方差的隐藏单元值 z ( i ) \pmb{z^{(i)}} z(i)z(i)z(i)

5. 将Batch归一化拟合进神经网络 (Fitting Batch Norm into a Neural Network)

在这里插入图片描述

实践中,Batch归一化通常和训练集的mini-batch一起使用。假设有一个神经网络,你应用Batch归一化的方式就是,将第一个mini-batch X { 1 } X^{\{1\}} X{ 1}作为输入,然后应用参数 w [ 1 ] w^{[1]} w[1] b [ 1 ] b^{[1]} b[1]计算 z [ 1 ] z^{[1]} z[1],接着Batch归一化会减去均值,除以标准差,由 β [ 1 ] \beta^{[1]} β[1] γ [ 1 ] \gamma^{[1]} γ[1]重新缩放,这样就得到了 z ~ [ 1 ] \tilde{z}^{[1]} z~[1],再应用激活函数 g [ 1 ] ( z ~ [ 1 ] ) g^{[1]}(\tilde{z}^{[1]}) g[1](z~[1])得到 a [ 1 ] a^{[1]} a[1]。然后使用参数 w [ 2 ] w^{[2]} w[2] b [ 2 ] b^{[2]} b[2]计算 z [ 2 ] z^{[2]} z[2]Batch归一化得到 z ~ [ 2 ] \tilde{z}^{[2]} z~[2],中间再引入两个参数 β [ 2 ] \beta^{[2]} β[2] γ [ 2 ] \gamma^{[2]} γ[2],最后应用激活函数 g [ 2 ] ( z ~ [ 2 ] ) g^{[2]}(\tilde{z}^{[2]}) g[2](z~[2])得到 a [ 2 ] a^{[2]} a[2]。后面以此类推,第二个mini-batch X { 2 } X^{\{2\}} X{ 2},第三个mini-batch X { 3 } X^{\{3\}} X{ 3}等等也按照这样的方式继续训练。
关于Batch归一化需要强调的是

  • Batch归一化是发生在计算 z z z a a a之间的。
  • 这里的 β [ 1 ] , β [ 2 ] \beta^{[1]},\beta^{[2]} β[1]β[2]等和Momentum超参数 β \beta β没有任何关系。
  • z z z的计算方式是 z ( i ) = w T a ( i ) + b z^{(i)}=w^Ta^{(i)}+b z(i)=wTa(i)+b,而Batch归一化中均值的计算方式 μ = 1 m ∑ i = 0 m z ( i ) = E ( w T a ( i ) ) + b \mu=\frac{1}{m}\sum_{i=0}^{m} {z^{(i)}}=E(w^Ta^{(i)})+b μ=m1i=0mz(i)=E(wTa(i))+b。因此 z n o r m ( i ) = z ( i ) − μ σ 2 + ϵ z_{norm}^{(i)}=\frac{z^{(i)}-\mu}{\sqrt{\sigma^2+\epsilon}} znorm(i)=σ2+ϵ z(i)μ z ( i ) − μ = ( w T a ( i ) + b ) − ( E ( w T a ( i ) ) + b ) = w T a ( i ) − E ( w T a ( i ) z^{(i)}-\mu=(w^Ta^{(i)}+b)-(E(w^Ta^{(i)})+b)=w^Ta^{(i)}-E(w^Ta^{(i)} z(i)μ=(wTa(i)+b)(E(wTa(i))+b)=wTa(i)E(wTa(i)。这意味着,无论偏置项 b b b的值是多少,都是会被消除的。因此在使用Batch归一化时可以不添加偏置项 b \pmb{b} bbb,或将其置为0

总结一下如何使用Batch归一化来应用梯度下降法。假设你在使用mini-batch梯度下降法,运行 t t t从1到batch数量的for循环,在for循环中执行如下操作:

  1. 对mini-batch X { t } X^{\{t\}} X{ t}应用前向传播,并且对每个隐藏层都应用正向传播,计算得到 z [ l ] z^{[l]} z[l]
  2. Batch归一化计算得到 z ~ [ l ] \tilde{z}^{[l]} z~[l],从而替代 z [ l ] z^{[l]} z[l]
  3. 用反向传播计算第 l l l层所有的参数,即 d w [ l ] dw^{[l]} dw[l] d b [ l ] db^{[l]} db[l] d β [ l ] d\beta^{[l]} dβ[l] d γ [ l ] d\gamma^{[l]} dγ[l]
  4. 更新参数: w [ l ] = w [ l ] − α d w [ l ] w^{[l]}=w^{[l]}-\alpha dw^{[l]} w[l]=w[l]αdw[l] β [ l ] = β [ l ] − α d β [ l ] \beta^{[l]}=\beta^{[l]}-\alpha d\beta^{[l]} β[l]=β[l]αdβ[l] γ [ l ] = γ [ l ] − α d γ [ l ] \gamma^{[l]}=\gamma^{[l]}-\alpha d\gamma^{[l]} γ[l]=γ[l]αdγ[l]
    MomentumRMSpropAdam等优化算法在这里也同样适用)

在这里插入图片描述

6. Batch Norm 为什么起作用? (Why does Batch Norm work?)

6.1 Covariate shift

在这里插入图片描述

假设有一个神经网络,建立在猫的识别检测上。假设你已经在所有黑猫的图像上训练了数据集,但是现在将此网络应用于有色猫的识别。在这种情况下,正样本中不只有黑猫,还有其它颜色的猫。
在这里插入图片描述

假设左图是黑猫的训练集正负样本分布情况,右图是黑猫和有色猫混合的训练集正负样本分布情况。在实际中,使用左图这样的训练集作为输入而训练结果不错的神经网络,同样给右图这样的训练集运行,却并不见得会好。即使存在运行都很好的同一个函数,也不希望去使用。
Covariate shift的概念就是由于训练集和测试集,即输入数据存在分布的差异性,给网络的泛化性和训练速度带来了影响。

6.2 Covariate shift如何影响神经网络?

在这里插入图片描述

现在有一个上图这样的深层神经网络,以隐藏层第三层为例,假设此网络已经学习了参数 w [ 3 ] w^{[3]} w[3] b [ 3 ] b^{[3]} b[3]
在这里插入图片描述

然后遮住左边的部分,从隐藏层第三层的角度来看,它从前一层获得一些值,即 a 1 [ 2 ] , a 2 [ 2 ] , a 3 [ 2 ] , a 4 [ 2 ] a_1^{[2]},a_2^{[2]},a_3^{[2]},a_4^{[2]} a1[2]a2[2]a3[2]a4[2],这些值也可以看作是输入值 x 1 , x 2 , x 3 , x 4 x_1,x_2,x_3,x_4 x1x2x3x4。隐藏层第三层的工作是找到一种方式,使这些值映射到 y ^ \hat{y} y^
在这里插入图片描述

现在我们把网络的左边揭开,这个网络还有参数 w [ 1 ] , b [ 1 ] w^{[1]},b^{[1]} w[1]b[1] w [ 2 ] , b [ 2 ] w^{[2]},b^{[2]} w[2]b[2],每一次参数迭代更新后,经过隐藏层第一层和第二层的网络计算后, a 1 [ 2 ] , a 2 [ 2 ] , a 3 [ 2 ] , a 4 [ 2 ] a_1^{[2]},a_2^{[2]},a_3^{[2]},a_4^{[2]} a1[2]a2[2]a3[2]a4[2]的值也会改变,对于隐藏层第三层来说,输入数据的分布会发生变化,因此它就有了Covariate shift问题。

6.3 Batch归一化如何解决Covariate shift问题?

在这里插入图片描述

将第二层的隐藏单元值的分布绘制出来(为了便于理解,这里仅考虑 z 1 [ 2 ] z^{[2]}_1 z1[2] z 2 [ 2 ] z^{[2]}_2 z2[2]两个隐藏单元值),因为 z 1 [ 2 ] z^{[2]}_1 z1[2] z 2 [ 2 ] z^{[2]}_2 z2[2]的值会变化,因此其数据分布也会有所变化。
Batch归一化所做的是,限制这些隐藏单元值分布变化的程度。当神经网络在前一层中更新参数,Batch归一化可以确保无论其怎样变化 z 1 [ 2 ] z^{[2]}_1 z1[2] z 2 [ 2 ] z^{[2]}_2 z2[2]的均值和方差保持不变(均值和方差可以分别为0和1,即符合正态分布,也可以由参数 β \beta β γ \gamma γ决定)。
Batch归一化减少了输入值改变的问题,使输入值变得更稳定,神经网络中后面的层就会有更坚实的基础。即使输入分布改变了一些,也会改变得更少。Batch归一化让当前层保持学习,当输入分布改变时,迫使后面的层对其适应的程度减小了,或者说它减弱了前层参数的作用与后层参数的作用之间的联系,使得网络中每一层都可以自己学习,稍稍独立于其它层,这有助于加速整个网络的学习。

6.4 Batch归一化的其他作用

Batch归一化还有一个作用,它有轻微的正则化效果。Batch归一化通常与mini-batch梯度下降法一起使用,由于每个mini-batch X { t } X^{\{t\}} X{ t}相当于不同的输入数据集,且mini-batch size较小,因此在mini-batch上计算出的均值和方差会有一些小的噪声。同时从 z [ l ] z^{[l]} z[l] z ~ [ l ] \tilde{z}^{[l]} z~[l]的缩放过程中也有一些噪音,因为它是用本身存在噪音的均值和方差计算得出的。
所以和dropout相似,Batch归一化给每个隐藏层的激活值上增加了噪音,这迫使后面的单元不过分依赖任何一个隐藏单元。对于隐藏单元来说,向输入添加方差极小的噪声等价于对权重施加范数惩罚,因此相当于有正则化的作用。但是因为添加的噪音很微小,所以正则化的效果并不是很大。
如果你想得到dropout更强大的正则化效果,你可以将Batch归一化dropout一起使用。另外,通过应用较大的min-batch,可以减少噪音,同时也减少正则化效果。但事实上,不建议把Batch归一化当作正则化
在这里插入图片描述

7. 测试时的 Batch Norm (Batch Norm at Test Time)

Batch归一化将你的数据以mini-batch的形式逐一处理,但在测试时,你可能需要对每个样本逐一处理。
在这里插入图片描述

首先回顾一下在训练阶段,以mini-batch的形式执行Batch归一化的过程。在一个mini-batch中,首先将mini-batch中所有的样本 z ( i ) z^{(i)} z(i)值累加求和,计算均值,这里用 m m m来表示这个mini-batch中的样本数量,而不是整个训练集。然后计算方差,再计算 z n o r m ( i ) z^{(i)}_{norm} znorm(i),即用均值和标准差来调整,分母加上 ϵ \epsilon ϵ是为了数值稳定性。最后是用 γ \gamma γ β \beta β再次调整 z n o r m z_{norm} znorm得到 z ~ \tilde{z} z~
请注意在训练阶段用于调节计算的均值 μ \mu μ和方差 σ 2 \sigma^2 σ2是在整个mini-batch上进行计算,但是在测试阶段,你也许不能对一个mini-batch中所有的样本同时处理,因此你需要用其它方式来得到均值 μ \mu μ和方差 σ 2 \sigma^2 σ2,而且如果你只有一个样本,一个样本的均值和方差没有意义。在典型的Batch归一化应用中,你需要用一个指数加权平均来估算,这个平均数涵盖了所有mini-batch
假设在第 l l l层,首先训练第一个mini-batch X { 1 } X^{\{1\}} X{ 1},得到第一个mini-batch的均值 μ { 1 } [ l ] \mu^{\{1\}[l]} μ{ 1}[l]。然后在这一层继续训练第二个mini-batch X { 2 } X^{\{2\}} X{ 2},得到均值 μ { 2 } [ l ] \mu^{\{2\}[l]} μ{ 2}[l]。接着在这一层训练第三个mini-batch X { 3 } X^{\{3\}} X{ 3},得到均值 μ { 3 } [ l ] \mu^{\{3\}[l]} μ{ 3}[l]。正如之前用的指数加权平均来计算 θ 1 , θ 2 , θ 3 \theta_1,\theta_2,\theta_3 θ1θ2θ3的均值,这里也可以使用指数加权平均来估计这一隐藏层的各隐藏单元 z z z的均值。同样的,你还可以用指数加权平均来追踪这一层的各个mini-batch中的方差 σ 2 \sigma^2 σ2。因此在用不同的mini-batch训练神经网络的同时,能够得到你所查看的每一层的 μ \mu μ σ 2 \sigma^2 σ2的平均数的实时数值。
最后在测试时,对应等式 z n o r m ( i ) = z ( i ) − μ σ 2 + ϵ z_{norm}^{(i)}=\frac{z^{(i)}-\mu}{\sqrt{\sigma^2+\epsilon}} znorm(i)=σ2+ϵ z(i)μ,你只需要用你的 z z z值来计算 z n o r m ( i ) z_{norm}^{(i)} znorm(i),用 μ \mu μ σ 2 \sigma^2 σ2的指数加权平均值来做调整,然后再用刚算出来的 z n o r m z_{norm} znorm和你在神经网络训练过程中得到的参数 β \beta β γ \gamma γ来计算那个测试样本的 z ~ \tilde{z} z~值。

8. Softmax 回归 (Softmax Regression)

到目前为止,我们遇到的所有分类的案例都使用的是二分分类,这种分类只有两种可能的标记,即0或1。有一种logistic回归的一般形式,叫做Softmax回归,用于解决多分类的问题。
在这里插入图片描述

假设你需要识别猫,狗和小鸡,这里我把猫设为类别1,狗为类别2,小鸡为类别3,如果不属于以上任何一类,就设为类别0(如上图)。这里用符号 C C C来表示分类的类别总个数。
在这里插入图片描述

首先建立一个神经网络,其输出层有4个,或者说有 C C C个输出单元,因此 n [ L ] n^{[L]} n[L],即输出层单元数量等于4,或者一般来说等于 C C C
在这里插入图片描述

输出层的每个输出单元会给出每一个类别的概率分别有多大(如上图),即在输入为 X X X时,第一个节点对应的是输出为“其他”类(类别0)的概率 P ( o t h e r ∣ X ) P(other|X) P(otherX),第二个节点对应的是输出为猫(类别1)的概率 P ( c a t ∣ X ) P(cat|X) P(catX),第三个节点对应的是输出为狗(类别2)的概率 P ( d o g ∣ X ) P(dog|X) P(dogX),第四个节点对应的是输出为小鸡(类别3)的概率 P ( b a b y   c h i c k ∣ X ) P(baby\ chick|X) P(baby chickX)。因此 y ^ \hat{y} y^将是一个4×1维向量,且四个输出的概率加起来应该等于1。
让你的网络实现上述功能需要用到Softmax层,以及输出层来生成输出。在神经网络的最后一层,你将会像往常一样计算各层的线性部分,计算流程如下:
(1) 计算 z [ L ] = W [ L ] a [ L − 1 ] + b [ L ] z^{[L]}=W^{[L]}a^{[L-1]}+b^{[L]} z[L]=W[L]a[L1]+b[L]
(2) 应用Softmax激活函数:

  1. 计算一个临时变量 t = e z [ L ] t=e^{z^{[L]}} t=ez[L],这是对所有元素求幂。其中 z [ L ] z^{[L]} z[L]的维度是4×1,因此 t = e z [ l ] t=e^{z^{[l]}} t=ez[l]是一个4×1维向量;
  2. t t t进行归一化,使输出的和为1,然后输出 a [ L ] a^{[L]} a[L]。因此 a [ L ] = e z [ L ] ∑ j = 1 4 t i a^{[L]}=\frac{e^{z^{[L]}}}{\sum_{j=1}^4t_i} a[L]=j=14tiez[L],换句话说, a [ L ] a^{[L]} a[L]也是一个4×1维向量,而这个四维向量的第 i i i个元素 a i [ L ] = t i ∑ j = 1 4 t i a^{[L]}_i=\frac{t_i}{\sum_{j=1}^4t_i} ai[L]=j=14titi

举一个具体的例子来说,假设输出层中 z [ L ] = [ 5 2 − 1 3 ] z^{[L]}=\begin{bmatrix} 5\\ 2\\ -1\\ 3\\ \end{bmatrix} z[L]=5213,然后用元素取幂方法来计算得到 t = e z [ L ] = [ e 5 e 2 e − 1 e 3 ] = [ 148.4 7.4 0.4 20.1 ] t=e^{z^{[L]}}=\begin{bmatrix} e^5\\ e^2\\ e^{-1}\\ e^3\\ \end{bmatrix}=\begin{bmatrix} 148.4\\ 7.4\\ 0.4\\ 20.1\\ \end{bmatrix} t=ez[L]=e5e2e1e3=148.47.40.420.1。从向量 t t t到向量 a [ l ] a^{[l]} a[l]只需要将这些元素归一化,使总和为1,即把向量 t t t中的所有元素加起来,得到176.3,最终 a [ l ] = y ^ = t 176.3 = [ 0.841 0.041 0.002 0.114 ] a^{[l]}=\hat{y}=\frac{t}{176.3}=\begin{bmatrix} 0.841\\ 0.041\\ 0.002\\ 0.114\\ \end{bmatrix} a[l]=y^=176.3t=0.8410.0410.0020.114。因此在输出层,第一个节点的输出是0.842,即输入 X X X为类别0的概率是84.2%。同理,第二个节点的输出是0.041,即输入 X X X为类别1的概率是4.1%。第三个节点的输出是0.002,即输入 X X X为类别2的概率是0.2%。第四个节点的输出是0.114,即输入 X X X为类别3的概率是11.4%。

9. 训练一个 Softmax 分类器 (Training a Softmax Classifier)

关于训练带有Softmax输出层的神经网络,具体而言,我们先定义训练神经网络会用到的损失函数。以上一章节为例,假设输入是一张猫(类别1)的图片,即真实标签是 y = [ 0 1 0 0 ] y=\begin{bmatrix} 0\\ 1\\ 0\\ 0\\ \end{bmatrix} y=0100。假设你的神经网络输出的是 y ^ = a [ L ] = [ 0.3 0.2 0.1 0.4 ] \hat{y}=a^{[L]}=\begin{bmatrix} 0.3\\ 0.2\\ 0.1\\ 0.4\\ \end{bmatrix} y^=a[L]=0.30.20.10.4,其中 y ^ \hat{y} y^是一个元素总和为1的向量。对于这个样本神经网络的表现不佳,这实际上是一只猫,但却只分配到20%是猫的概率,所以在本例中表现不佳。
Softmax分类中,我们一般用到的损失函数是 L ( y ^ , y ) = − ∑ j = 1 4 y j log ⁡ y ^ j L(\hat{y},y)=-\sum_{j=1}^4y_j\log\hat{y}_j L(y^,y)=j=14yjlogy^j 在这个样本中 y 1 = y 3 = y 4 = 0 y_1=y_3=y_4=0 y1=y3=y4=0 y 2 = 1 y_2=1 y2=1,因此损失函数 L ( y ^ , y ) = − y 2 t log ⁡ y ^ 2 = − log ⁡ y ^ 2 L(\hat{y},y)=-y_2t\log\hat{y}_2=-\log\hat{y}_2 L(y^,y)=y2tlogy^2=logy^2 L ( y ^ , y ) = − ∑ j = 1 4 y j log ⁡ y ^ j = − y 2 log ⁡ y ^ 2 = − log ⁡ y ^ 2 L(\hat{y},y)=-\sum_{j=1}^4y_j\log\hat{y}_j=-y_2\log\hat{y}_2=-\log\hat{y}_2 L(y^,y)=j=14yjlogy^j=y2logy^2=logy^2。这就意味着,如果你的学习算法试图将它变小,因为梯度下降法是用来减少训练集的损失的,要让损失函数 L ( y ^ , y ) L(\hat{y},y) L(y^,y)变小,就是让 − log ⁡ y ^ 2 − -\log\hat{y}_2− logy^2变小,而 y ^ 2 \hat{y}_2 y^2要尽可能大。
概括来讲,损失函数所做的就是找到你的训练集中的真实类别,然后试图使该类别相应的概率尽可能地高。
这是单个训练样本的损失,整个训练集的损失 J J J就是将所有训练样本的预测都加起来,即 J ( w [ 1 ] , b [ 1 ] , ⋯   ) = 1 m ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) J(w^{[1]},b^{[1]},\cdots)=\frac1m\sum_{i=1}^mL(\hat{y}^{(i)},y^{(i)}) J(w[1],b[1],)=m1i=1mL(y^(i),y(i)) 因此你要做的就是用梯度下降法,使这里的损失最小化。在有Softmax输出层的神经网络中,实现梯度下降法的流程如下:

  • 前向传播过程:
    • ① 输出层会计算 z [ l ] z^{[l]} z[l],其维度是C×1。
    • ② 用Softmax激活函数来得到 a [ l ] a^{[l]} a[l],或者说 y ^ \hat{y} y^
    • ③ 计算损失。
  • 反向传播过程:
    • d z [ l ] = y ^ − y dz^{[l]}=\hat{y}-y dz[l]=y^y,这是对 z [ l ] z^{[l]} z[l]损失函数的偏导数 d z [ l ] = ∂ J ∂ z [ l ] dz^{[l]}=\frac{\partial J}{\partial z^{[l]}} dz[l]=z[l]J
    • ② 计算整个神经网络中所需要的所有导数。

猜你喜欢

转载自blog.csdn.net/baoli8425/article/details/118970628
今日推荐