吴恩达神经网络与深度学习章节笔记(二)——神经网络和激活函数


视频课程链接:
https://www.bilibili.com/video/BV1FT4y1E74V?
笔记参考链接:
https://blog.csdn.net/weixin_36815313/article/details/105728919
课程作业链接:
https://download.csdn.net/download/baoli8425/19821557?spm=1001.2014.3001.5503

1. 神经网络概览 (Neural Networks Overview)

在这里插入图片描述
神经网络模型与逻辑回归公式之间的关系如上图。
输入特征 x x x,参数 w w w b b b ,从而计算出 z z z,最后输出预测值 y ^ \hat{y} y^,同时计算损失函数 L ( y ^ , y ) L(\hat{y},y) L(y^,y)

我们会使用符号 [ m ] ^{[m]} [m]表示 m \pmb{m} mmm层网络中节点相关的数,这些节点的集合被称为 m \pmb{m} mmm层网络。这样可以保证 [ m ] ^{[m]} [m]不会和我们之前用来表示单个的训练样本的 ( i ) ^{(i)} (i)(即我们使用表示第 i i i个训练样本)混淆。
在这里插入图片描述

在这个神经网络对应的3个节点,首先计算第一层网络中的各个节点相关的数 z [ 1 ] z^{[1]} z[1],接着计算 a [ 1 ] a^{[1]} a[1]
在这里插入图片描述

使用另外一个线性方程对应的参数计算 z [ 2 ] z^{[2]} z[2],计算 a [ 2 ] a^{[2]} a[2],此时 a [ 2 ] a^{[2]} a[2]就是整个神经网络最终的输出,用 y ^ \hat{y} y^表示网络的输出。

2. 神经网络表示 (Neural Network Representation)

在这里插入图片描述

我们有输入特征 x 1 、 x 2 、 x 3 x_1、x_2、x_3 x1x2x3,它们被竖直地堆叠起来,这叫做神经网络的输入层(Input Layer)。它包含了神经网络的输入;这里还有另外一层我们称之为隐藏层(Hidden Layer)。在一个神经网络中,当你使用监督学习训练它的时候,训练集既包含了输入 x x x,也包含了目标输出 y y y,而这些中间结点的准确值我们是不知道的,你能看见输入的值,也能看见输出的值,但是隐藏层中的东西,在训练集中你是无法看到的;最后一层只由一个结点构成,而这个只有一个结点的层被称为输出层(Output Layer),它负责产生预测值 y ^ \hat{y} y^
按照约定俗成的符号传统,在这个例子中,只能叫做一个两层的神经网络。输入层是不算入总层数内,我们将输入层称为第零层,因此在这个例子中隐藏层是第一层,输出层是第二层。
在前面的逻辑回归中,我们用向量 X X X表示输入特征。在神经网络中 a [ 0 ] a^{[0]} a[0]可以用来表示输入特征,a表示激活的意思,它意味着网络中不同层的值会传递到它们后面的层中,输入层将 X X X传递给隐藏层,所以我们将输入层的激活值称为 a [ 0 ] a^{[0]} a[0];下一层即隐藏层也同样会产生一些激活值,那么我将其记作 a [ 1 ] a^{[1]} a[1],所以具体地,这里的第一个单元或结点我们将其表示为 a 1 [ 1 ] a^{[1]}_1 a1[1],第二个结点的值我们记为 a 2 [ 1 ] a^{[1]}_2 a2[1],以此类推。在本例中,我们有四个结点或者单元,或者称为四个隐藏层单元。写成如下的Python代码,那么它是一个规模为4x1的矩阵或一个大小为4的列向量。
a [ 1 ] = [ a 1 [ 1 ] a 2 [ 1 ] a 3 [ 1 ] a 4 [ 1 ] ] a^{[1]}=\begin{bmatrix} {a^{[1]}_{1}}\\ {a^{[1]}_{2}}\\ {a^{[1]}_{3}}\\ {a^{[1]}_{4}}\\ \end{bmatrix} a[1]=a1[1]a2[1]a3[1]a4[1]最后输出层将产生某个数值 a a a,它只是一个单独的实数,所以 y ^ \hat{y} y^的值将取为 a [ 2 ] a^{[2]} a[2]
隐藏层拥有两个参数 W W W b b b,给它们加上上标 ( W [ 1 ] , b [ 1 ] ) (W^{[1]},b^{[1]}) (W[1],b[1]),表示这些参数是和第一层这个隐藏层有关系的。在这个例子中 W W W是一个4×3的矩阵,而 b b b是一个4×1的向量。输出层也有一些与之关联的参数 W [ 2 ] W^{[2]} W[2]以及 b [ 2 ] b^{[2]} b[2] 。从维数上来看,它们的规模分别是1×4以及1×1,1×4是因为隐藏层有四个隐藏层单元而输出层只有一个单元。
在这里插入图片描述

3. 计算神经网络的输出 (Computing a Neural Network’s Output)

3.1 神经网络的计算

在这里插入图片描述
用圆圈表示神经网络的计算单元,逻辑回归的计算有两个步骤,首先按步骤计算出 z z z,然后第二步再以sigmoid函数为激活函数计算 z z z,得出 a a a,一个神经网络只是这样子做了好多次重复计算。
在这里插入图片描述
回到两层的神经网络,我们从隐藏层的第一个神经元开始计算(如上图)。这个神经元的计算与逻辑回归一样分为两步,小圆圈代表了计算的两个步骤。
第一步:计算 z 1 [ 1 ] = w 1 [ 1 ] T x + b 1 [ 1 ] z^{[1]}_1=w^{[1]T}_1x+b^{[1]}_1 z1[1]=w1[1]Tx+b1[1]
第二步:通过激活函数计算 a 1 [ 1 ] = σ ( z 1 [ 1 ] ) a^{[1]}_1=\sigma(z^{[1]}_1) a1[1]=σ(z1[1])
隐藏层的其余三个神经元的计算过程一样,只是注意符号表示不同,最终分别得到:
z 2 [ 1 ] = w 2 [ 1 ] T x + b 2 [ 1 ] , a 2 [ 1 ] = σ ( z 2 [ 1 ] ) z_2^{[1]}=w_2^{[1]}Tx+b_2^{[1]},a_2^{[1]}=σ(z_2^{[1]}) z2[1]=w2[1]Tx+b2[1],a2[1]=σ(z2[1]) z 3 [ 1 ] = w 3 [ 1 ] T x + b 3 [ 1 ] , a 3 [ 1 ] = σ ( z 3 [ 1 ] ) z_3^{[1]}=w_3^{[1]}Tx+b_3^{[1]},a_3^{[1]}=σ(z_3^{[1]}) z3[1]=w3[1]Tx+b3[1],a3[1]=σ(z3[1]) z 4 [ 1 ] = w 4 [ 1 ] T x + b 4 [ 1 ] , a 4 [ 1 ] = σ ( z 4 [ 1 ] ) z_4^{[1]}=w_4^{[1]}Tx+b_4^{[1]},a_4^{[1]}=σ(z_4^{[1]}) z4[1]=w4[1]Tx+b4[1],a4[1]=σ(z4[1])

3.2 向量化计算

向量化的过程是将神经网络中的一层神经元参数纵向堆积起来,例如隐藏层中的 W W W纵向堆积起来变成一个4×3的矩阵,用符号 W [ 1 ] W^{[1]} W[1]表示。其中这里的数字4是因为我们有四个结点或隐藏层单元,数字3是因为这里有三个输入特征
对于神经网络的第一层,即隐藏层,给予一个输入 x x x,通过如下两步计算得到 a [ 1 ] a^{[1]} a[1]
z [ 1 ] = [ z 1 [ 1 ] z 2 [ 1 ] z 3 [ 1 ] z 4 [ 1 ] ] = [ W 1 [ 1 ]   W 1 [ 1 ]   W 1 [ 1 ] W 2 [ 1 ]   W 2 [ 1 ]   W 2 [ 1 ] W 4 [ 1 ]   W 3 [ 1 ]   W 3 [ 1 ] W 4 [ 1 ]   W 4 [ 1 ]   W 4 [ 1 ] ] ∗ [ x 1 x 2 x 3 ] + [ b 1 [ 1 ] b 2 [ 1 ] b 3 [ 1 ] b 4 [ 1 ] ] z^{[1]}=\begin{bmatrix} {z^{[1]}_{1}}\\ {z^{[1]}_{2}}\\ {z^{[1]}_{3}}\\ {z^{[1]}_{4}}\\ \end{bmatrix}=\begin{bmatrix} {W^{[1]}_{1}}\ {W^{[1]}_{1}}\ {W^{[1]}_{1}}\\ {W^{[1]}_{2}}\ {W^{[1]}_{2}}\ {W^{[1]}_{2}}\\ {W^{[1]}_{4}}\ {W^{[1]}_{3}}\ {W^{[1]}_{3}}\\ {W^{[1]}_{4}}\ {W^{[1]}_{4}}\ {W^{[1]}_{4}}\\ \end{bmatrix}*\begin{bmatrix} {x_{1}}\\ {x_{2}}\\ {x_{3}}\\ \end{bmatrix}+\begin{bmatrix} {b^{[1]}_{1}}\\ {b^{[1]}_{2}}\\ {b^{[1]}_{3}}\\ {b^{[1]}_{4}}\\ \end{bmatrix} z[1]=z1[1]z2[1]z3[1]z4[1]=W1[1] W1[1] W1[1]W2[1] W2[1] W2[1]W4[1] W3[1] W3[1]W4[1] W4[1] W4[1]x1x2x3+b1[1]b2[1]b3[1]b4[1] a [ 1 ] = [ a 1 [ 1 ] a 2 [ 1 ] a 3 [ 1 ] a 4 [ 1 ] ] = σ ( z [ 1 ] ) a^{[1]}=\begin{bmatrix} {a^{[1]}_{1}}\\ {a^{[1]}_{2}}\\ {a^{[1]}_{3}}\\ {a^{[1]}_{4}}\\ \end{bmatrix}=σ(z^{[1]}) a[1]=a1[1]a2[1]a3[1]a4[1]=σ(z[1])下一层输出层的表示同样可以写成类似的形式,以 a [ 1 ] a^{[1]} a[1]作为输入,通过如下两步计算得到 a [ 2 ] a^{[2]} a[2]
z [ 2 ] = [ z 1 [ 2 ] z 2 [ 2 ] z 3 [ 2 ] z 4 [ 2 ] ] = [ W 1 [ 2 ]   W 1 [ 2 ]   W 1 [ 2 ]   W 1 [ 2 ] ] ∗ [ a 1 [ 1 ] a 2 [ 1 ] a 3 [ 1 ] a 4 [ 1 ] ] + [ b 1 [ 2 ] ] z^{[2]}=\begin{bmatrix} {z^{[2]}_{1}}\\ {z^{[2]}_{2}}\\ {z^{[2]}_{3}}\\ {z^{[2]}_{4}}\\ \end{bmatrix}=\begin{bmatrix} {W^{[2]}_{1}}\ {W^{[2]}_{1}}\ {W^{[2]}_{1}}\ {W^{[2]}_{1}}\\ \end{bmatrix}*\begin{bmatrix} {a_{1}^{[1]}}\\ {a_{2}^{[1]}}\\ {a_{3}^{[1]}}\\ {a_{4}^{[1]}}\\ \end{bmatrix}+\begin{bmatrix} {b^{[2]}_{1}}\\ \end{bmatrix} z[2]=z1[2]z2[2]z3[2]z4[2]=[W1[2] W1[2] W1[2] W1[2]]a1[1]a2[1]a3[1]a4[1]+[b1[2]] a [ 2 ] = σ ( z [ 2 ] ) a^{[2]}=σ(z^{[2]}) a[2]=σ(z[2])

4. 多个例子中的向量化 (Vectorizing across Multiple Examples)

上一节是针对单一的训练样本,在神经网络上计算出预测值 y ^ \hat{y} y^。而在本节中,我们将会了解到如何向量化多个训练样本,并计算出结果。
首先引入一种新的符号定义,以 a [ 2 ] ( i ) a^{[2](i)} a[2](i)为例,其中 ( i ) (i) (i)是指第 i i i个训练样本, [ 2 ] [2] [2]是指第二层。
对于所有的训练样本,如果采用非向量化的方法实现,需要让 i i i从1到 m m m遍历这四个等式(此处 W \pmb{W} WWW没有转置)。
在这里插入图片描述

而采用向量化的方式则是将训练样本在横向上堆叠到矩阵的各列,形成一个 n x × m n_x×m nx×m维的矩阵。
将小写的 x x x向量堆叠到矩阵的各列中,形成矩阵 X X X(如下图)。
X = [ ⋮ ⋮ ⋮ ⋮ x ( 1 ) x ( 2 ) ⋯ x ( m ) ⋮ ⋮ ⋮ ⋮ ] X=\begin{bmatrix} \vdots & \vdots & \vdots & \vdots \\ x^{(1)} & x^{(2)} & \cdots & x^{(m)} \\ \vdots & \vdots & \vdots & \vdots \\ \end{bmatrix} X=x(1)x(2)x(m) z [ 1 ] ( 1 ) z^{[1](1)} z[1](1) z [ 1 ] ( 2 ) z^{[1](2)} z[1](2)、……、 z [ 1 ] ( m ) z^{[1](m)} z[1](m) m m m个列向量堆叠到各列中,就得到了矩阵 Z [ 1 ] Z^{[1]} Z[1](如下图)。
Z [ 1 ] = [ ⋮ ⋮ ⋮ ⋮ z [ 1 ] ( 1 ) z [ 1 ] ( 2 ) ⋯ z [ 1 ] ( m ) ⋮ ⋮ ⋮ ⋮ ] Z^{[1]}=\begin{bmatrix} \vdots & \vdots & \vdots & \vdots \\ z^{[1](1)} & z^{[1](2)} & \cdots & z^{[1](m)} \\ \vdots & \vdots & \vdots & \vdots \\ \end{bmatrix} Z[1]=z[1](1)z[1](2)z[1](m) a [ 1 ] ( 1 ) a^{[1](1)} a[1](1) a [ 1 ] ( 2 ) a^{[1](2)} a[1](2)、……、 a [ 1 ] ( m ) a^{[1](m)} a[1](m)组合到矩阵的各列中,就得到了矩阵 A [ 1 ] A^{[1]} A[1](如下图)。 A [ 1 ] = [ ⋮ ⋮ ⋮ ⋮ a [ 1 ] ( 1 ) a [ 1 ] ( 2 ) ⋯ a [ 1 ] ( m ) ⋮ ⋮ ⋮ ⋮ ] A^{[1]}=\begin{bmatrix} \vdots & \vdots & \vdots & \vdots \\ a^{[1](1)} & a^{[1](2)} & \cdots & a^{[1](m)} \\ \vdots & \vdots & \vdots & \vdots \\ \end{bmatrix} A[1]=a[1](1)a[1](2)a[1](m)同理可得第二层中对应的矩阵 Z [ 2 ] Z^{[2]} Z[2] A [ 2 ] A^{[2]} A[2]
对于矩阵 A A A来说,从水平方向上看,代表了 m m m个不同的训练样本。从垂直方向上看,对应于同一层中不同的隐藏单元(神经元)。
而对于矩阵 Z Z Z X X X也是类似的。在水平方向上,对应于 m m m个不同的训练样本;在竖直方向上,对应不同的输入特征,即神经网络输入层中的各个节点。
因此采用向量化的方式实际按照如下四个公式计算。 Z [ 1 ] = W [ 1 ] X + b [ 1 ] Z^{[1]}=W^{[1]}X+b^{[1]} Z[1]=W[1]X+b[1] A [ 1 ] = σ ( Z [ 1 ] ) A^{[1]}=σ(Z^{[1]}) A[1]=σ(Z[1]) Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]} Z[2]=W[2]A[1]+b[2] A [ 2 ] = σ ( Z [ 2 ] ) A^{[2]}=σ(Z^{[2]}) A[2]=σ(Z[2])

5. 激活函数 (Activation Function)

5.1 sigmoid函数

在这里插入图片描述

a = σ ( z ) = 1 1 + e − z a=σ(z)=\frac{1}{1+e^{−z}} a=σ(z)=1+ez1在神经网络的前向传播中,在 a [ 1 ] = σ ( z [ 1 ] ) a^{[1]}=\sigma(z^{[1]}) a[1]=σ(z[1]) a [ 2 ] = σ ( z [ 2 ] ) a^{[2]}=\sigma(z^{[2]}) a[2]=σ(z[2])这两步中会使用到sigmoid函数。如果是二分类问题,即输出是0和1,要想让 y ^ \hat{y} y^的数值介于0和1之间,则输出层选择sigmoid函数,然后其它的所有单元都选择tanh函数或者ReLu函数。

5.2 tanh函数​

在这里插入图片描述

a = g ( z ) = e z + e − z e z − e − z a=g(z)=\frac{e^{z}+e^{−z}}{e^z−e^{−z}} a=g(z)=ezezez+eztanh函数是sigmoid函数向下平移和伸缩后的结果。
如果在隐藏层上使用tanh函数,效果总是优于sigmoid函数。因为函数值域在-1和+1之间,其均值更接近于零。在训练一个算法模型时,如果使用tanh函数代替sigmoid函数中心化数据,使得数据的平均值更接近0而不是0.5,这会使下一层学习简单一点。
sigmoid函数和tanh函数两者共同的缺点是,在 z z z特别大或者特别小的情况下,导数的梯度或者函数的斜率会变得特别小,最后就会接近于0,导致降低梯度下降的速度。

5.3 ReLu函数

在这里插入图片描述

a = m a x ( 0 , z ) a=max(0,z) a=max(0,z) z z z是正值的时候,导数恒等于1,当 z z z是负值的时候,导数恒等于0,而当 z = 0 z = 0 z=0的时候,导数是没有意义的。但是在编程实现的时候, z z z刚好等于0的概率很低,因此在实践中不需要担心这个问题。当 z z z等于0的时候,可以直接给导数赋值为0或1。

5.4 Leaky ReLu函数

在这里插入图片描述

a = m a x ( 0.1 z , z ) a=max(0.1z,z) a=max(0.1z,z)这个函数通常比ReLu激活函数效果要好,尽管在实际中Leaky ReLu使用的并不多。至于为什么常数是0.1?在实际应用中,你可以为学习算法选择不同的参数。

5.5 激活函数选择的经验总结

(1) 在 z z z的区间变动很大的情况下,激活函数的导数或者激活函数的斜率都会远大于0,在程序实现就是一个if-else语句,而sigmoid函数需要进行浮点四则运算。在实践中,使用ReLu激活函数的神经网络通常会比使用sigmoid或者tanh激活函数学习的更快。
(2) sigmoid和tanh函数的导数在正负饱和区的梯度都会接近于0,这会造成梯度弥散,而ReLu和Leaky ReLu函数大于0部分都为常数,不会产生梯度弥散现象。同时应该注意到的是,ReLu进入负半区的时候,梯度为0,神经元此时不会训练,产生所谓的稀疏性,而Leaky ReLu不会有这问题。
(3) 如果在隐藏层上不确定使用哪个激活函数,那么通常会使用Relu激活函数,有时也会使用tanh激活函数,但ReLu的一个优点是,当 z z z是负值的时候,导数等于0。
在编写神经网络的时候,会有很多的选择,例如隐藏层单元的个数激活函数的选择初始化权值等,但是自己的神经网络的应用以及其特殊性,是很难提前知道选择哪些效果更好,所以通常的建议是如果不确定哪一个激活函数效果更好,可以把它们都试试,然后在验证集或者发展集上进行评价,看哪一种表现的更好,就去使用它

6. 为什么需要非线性激活函数? (Why do you need non-linear activation function?)

如下是神经网络正向传播的方程。
在这里插入图片描述

假设 g ( z ) = z g(z)=z g(z)=z,这被称为线性激励函数或恒等激励函数,即把输入值直接输出。 a [ 1 ] = z [ 1 ] = W [ 1 ] x + b [ 1 ] (1) a^{[1]}=z^{[1]}=W^{[1]}x+b^{[1]} \tag{1} a[1]=z[1]=W[1]x+b[1](1) a [ 2 ] = z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] (2) a^{[2]}=z^{[2]}=W^{[2]}a^{[1]}+b^{[2]} \tag{2} a[2]=z[2]=W[2]a[1]+b[2](2)将公式(1)代入到公式(2)中得 z [ 2 ] = W [ 2 ] ( W [ 1 ] x + b [ 1 ] ) + b [ 2 ] = W [ 2 ] W [ 1 ] x + W [ 2 ] b [ 1 ] + b [ 2 ] (3) z^{[2]}=W^{[2]}(W^{[1]}x+b^{[1]})+b^{[2]}=W^{[2]}W^{[1]}x+W^{[2]}b^{[1]}+b^{[2]} \tag{3} z[2]=W[2](W[1]x+b[1])+b[2]=W[2]W[1]x+W[2]b[1]+b[2](3)简化多项式得 a [ 2 ] = z [ 2 ] = W ′ x + b ′ a^{[2]}=z^{[2]}=W^{'}x+b^{'} a[2]=z[2]=Wx+b因此如果用线性激活函数或者恒等激励函数,那么神经网络只是把输入线性组合再输出。如果你使用线性激活函数或者没有使用一个激活函数,那么无论你的神经网络有多少层,一直在做的只是计算线性函数,所以不如直接去掉全部隐藏层。
总而言之,可以在隐藏层使用ReLU函数、tanh函数、Leaky ReLU函数或者其他的非线性激活函数,但不能使用线性激活函数,唯一可以用线性激活函数的通常就是输出层

7. 激活函数的导数 (Derivatives of Activation Functions)

7.1 sigmoid函数的导数

在这里插入图片描述

已知sigmoid函数的表达式为 g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z}} g(z)=1+ez1对sigmoid函数求导可得 g ′ ( z ) = d d z g ( z ) = 1 1 + e − z ( 1 + 1 1 − e − z ) = g ( z ) ⋅ ( 1 − g ( z ) ) \begin{aligned} g'(z)&=\frac{d}{dz}g(z) \\ &=\frac{1}{1+e^{-z}}(1+\frac{1}{1-e^{-z}}) \\ &=g(z) \cdot (1-g(z)) \end{aligned} g(z)=dzdg(z)=1+ez1(1+1ez1)=g(z)(1g(z)) z z z较大时,假设 z = 10 z=10 z=10 g ( z ) ≈ 1 g(z) \approx 1 g(z)1,那么sigmoid函数的导数 g ′ ( z ) ≈ 1 ⋅ ( 1 − 1 ) ≈ 0 g'(z) \approx 1 \cdot (1-1) \approx 0 g(z)1(11)0;当 z z z较小时,假设 z = − 10 z=-10 z=10 g ( z ) ≈ 0 g(z) \approx 0 g(z)0,那么sigmoid函数的导数 g ′ ( z ) ≈ 0 ⋅ ( 1 − 0 ) ≈ 0 g'(z) \approx 0 \cdot (1-0) \approx 0 g(z)0(10)0

7.2 tanh函数的导数

在这里插入图片描述

已知tanh函数的表达式为 g ( z ) = e z + e − z e z − e − z g(z)=\frac{e^{z}+e^{−z}}{e^z−e^{−z}} g(z)=ezezez+ez对tanh函数求导可得 g ′ ( z ) = d d z g ( z ) = 1 − ( t a n h ( z ) ) 2 = 1 − g ( z ) 2 \begin{aligned} g'(z)&=\frac{d}{dz}g(z) \\ &=1-(tanh(z))^2 \\ &=1-g(z)^2 \end{aligned} g(z)=dzdg(z)=1(tanh(z))2=1g(z)2 z z z较大时,假设 z = 10 z=10 z=10 g ( z ) ≈ 1 g(z) \approx 1 g(z)1,那么tanh函数的导数 g ′ ( z ) ≈ 0 g'(z) \approx 0 g(z)0;当 z z z较小时,假设 z = − 10 z=-10 z=10 g ( z ) ≈ 0 g(z) \approx 0 g(z)0,那么tanh函数的导数 g ′ ( z ) ≈ 0 ⋅ ( 1 − 0 ) ≈ 0 g'(z) \approx 0 \cdot (1-0) \approx 0 g(z)0(10)0

7.3 ReLu函数的导数

在这里插入图片描述

已知ReLu函数的表达式为 g ( z ) = m a x ( 0 , z ) g(z)=max(0,z) g(z)=max(0,z)对ReLu函数求导可得 g ′ ( z ) = { 0 z < 0 1 z > 0 u n d e f i n e d z = 0 g'(z)=\begin{cases} 0& z<0 \\ 1& z>0 \\ undefined& z=0 \end{cases} g(z)=01undefinedz<0z>0z=0在实际编程中, z = 0 z=0 z=0的时候可以自定义为0或1,因为通常 z = 0 z=0 z=0的情况很少遇到。

7.4 Leaky ReLu函数的导数

在这里插入图片描述

已知Leaky ReLu函数的表达式为 g ( z ) = m a x ( 0.01 z , z ) g(z)=max(0.01z,z) g(z)=max(0.01z,z)对Leaky ReLu函数求导可得 g ′ ( z ) = { 0.01 z < 0 1 z > 0 u n d e f i n e d z = 0 g'(z)=\begin{cases} 0.01& z<0 \\ 1& z>0 \\ undefined& z=0 \end{cases} g(z)=0.011undefinedz<0z>0z=0在实际编程中, z = 0 z=0 z=0的时候可以自定义为0.01或1,因为通常 z = 0 z=0 z=0的情况很少遇到。

8. 神经网络的梯度下降法 (Gradient Descent for Neural Networks)

8.1 参数定义

在单隐层神经网络中有 W [ 1 ] W^{[1]} W[1] b [ 1 ] b^{[1]} b[1]表示隐藏层参数, W [ 2 ] W^{[2]} W[2] b [ 2 ] b^{[2]} b[2]表示输出层参数, n x n_x nx n [ 0 ] n^{[0]} n[0]表示输入特征的个数, n [ 1 ] n^{[1]} n[1]表示隐藏层的单元个数, n [ 2 ] n^{[2]} n[2]表示输出层的单元个数。因此 W [ 1 ] W^{[1]} W[1]是维度 ( n [ 1 ] , n [ 0 ] ) (n^{[1]},n^{[0]}) (n[1],n[0])的矩阵, b [ 1 ] b^{[1]} b[1] n [ 1 ] n^{[1]} n[1]维向量, W [ 1 ] W^{[1]} W[1]是维度 ( n [ 2 ] , n [ 1 ] ) (n^{[2]},n^{[1]}) (n[2],n[1])的矩阵, b [ 1 ] b^{[1]} b[1] n [ 2 ] n^{[2]} n[2]维向量。
在二元分类问题中,成本函数为 J ( W [ 1 ] , b [ 1 ] , W [ 2 ] , b [ 2 ] ) = 1 m ∑ i = 1 m L ( y ^ , y ) J(W^{[1]},b^{[1]},W^{[2]},b^{[2]})=\frac1m\sum_{i=1}^mL(\hat{y},y) J(W[1],b[1],W[2],b[2])=m1i=1mL(y^,y),其中损失函数 L ( y ^ , y ) L(\hat{y},y) L(y^,y)可能与逻辑回归中的损失函数完全一样, y ^ \hat{y} y^即为输出值 a [ 2 ] a^{[2]} a[2]

8.2 参数训练

参数训练需要算法做梯度下降,在训练神经网络的时候,随机初始化参数很重要,而不是初始化成全零。当初始化参数后,每次梯度下降都会循环计算预测值 y ^ ( i ) ( i = 1 , 2 , . . . , m ) \hat{y}^{(i)}(i = 1,2,...,m) y^(i)(i=1,2,...,m) d W [ 1 ] = d J d W [ 1 ] , d b [ 1 ] = d J d b [ 1 ] dW^{[1]}=\frac{dJ}{dW^{[1]}},db^{[1]}=\frac{dJ}{db^{[1]}} dW[1]=dW[1]dJ,db[1]=db[1]dJ d W [ 2 ] = d J d W [ 2 ] , d b [ 2 ] = d J d b [ 2 ] dW^{[2]}=\frac{dJ}{dW^{[2]}},db^{[2]}=\frac{dJ}{db^{[2]}} dW[2]=dW[2]dJ,db[2]=db[2]dJ W [ 1 ] : = W [ 1 ] − α d W [ 1 ] , b [ 1 ] : = b [ 1 ] − α d b [ 1 ] W^{[1]}:=W^{[1]}−αdW^{[1]},b^{[1]}:=b^{[1]}−αdb^{[1]} W[1]:=W[1]αdW[1],b[1]:=b[1]αdb[1] W [ 2 ] : = W [ 2 ] − α d W [ 2 ] , b [ 2 ] : = b [ 2 ] − α d b [ 2 ] W^{[2]}:=W^{[2]}−αdW^{[2]},b^{[2]}:=b^{[2]}−αdb^{[2]} W[2]:=W[2]αdW[2],b[2]:=b[2]αdb[2]

8.3 计算步骤

在这里插入图片描述

神经网络正向传播(forward propagation)的步骤如下:
(1) Z [ 1 ] = W [ 1 ] X + b [ 1 ] Z^{[1]}=W^{[1]}X+b^{[1]} Z[1]=W[1]X+b[1]
(2) A [ 1 ] = g [ 1 ] ( Z [ 1 ] ) A^{[1]}=g^{[1]}(Z^{[1]}) A[1]=g[1](Z[1])
(3) Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]} Z[2]=W[2]A[1]+b[2]
(4) A [ 2 ] = σ ( Z [ 2 ] ) A^{[2]}=\sigma(Z^{[2]}) A[2]=σ(Z[2])
神经网络反向传播(backward propagation)的步骤如下:
(1) d Z [ 2 ] = A [ 2 ] − Y dZ^{[2]}=A^{[2]}-Y dZ[2]=A[2]Y,其中 Y = [ y [ 1 ]   y [ 2 ]   ⋯   y [ m ] ] Y=[y^{[1]}\ y^{[2]}\ ⋯\ y^{[m]}] Y=[y[1] y[2]  y[m]]
(2) d W [ 2 ] = 1 m d Z [ 2 ] A [ 1 ] T dW^{[2]}=\frac{1}{m}dZ^{[2]}A^{[1]T} dW[2]=m1dZ[2]A[1]T
(3) d b [ 2 ] = 1 m n p . s u m ( d Z [ 2 ] ) db^{[2]}=\frac{1}{m}np.sum(dZ^{[2]}) db[2]=m1np.sum(dZ[2])
(4) d Z [ 1 ] = d L d A [ 2 ] ⋅ d A [ 2 ] d Z [ 2 ] ⋅ d Z [ 2 ] d A [ 1 ] ⋅ d A [ 1 ] d Z [ 1 ] = ( − Y A [ 2 ] + 1 − Y 1 − A [ 2 ] ) ⋅ ( A [ 2 ] ⋅ ( 1 − A [ 2 ] ) ) ⋅ W [ 2 ] ⋅ g [ 1 ] ′ ( Z [ 1 ] ) = W [ 2 ] T d Z [ 2 ]   ∗   g [ 1 ] ′ ( Z [ 1 ] ) dZ^{[1]}=\frac{dL}{dA^{[2]}}\cdot \frac{dA^{[2]}}{dZ^{[2]}}\cdot \frac{dZ^{[2]}}{dA^{[1]}}\cdot \frac{dA^{[1]}}{dZ^{[1]}}=(\frac{-Y}{A^{[2]}}+\frac{1-Y}{1-A^{[2]}})\cdot (A^{[2]}\cdot (1-A^{[2]}))\cdot W^{[2]}\cdot g^{[1]′}(Z^{[1]})=W^{[2]T}dZ^{[2]}\ ∗\ g^{[1]′}(Z^{[1]}) dZ[1]=dA[2]dLdZ[2]dA[2]dA[1]dZ[2]dZ[1]dA[1]=(A[2]Y+1A[2]1Y)(A[2](1A[2]))W[2]g[1](Z[1])=W[2]TdZ[2]  g[1](Z[1])
(5) d W [ 1 ] = 1 m d Z [ 1 ] x T dW^{[1]}=\frac1mdZ^{[1]}x^T dW[1]=m1dZ[1]xT
(6) d b [ 1 ] = 1 m n p . s u m ( d Z [ 1 ] ) db^{[1]}=\frac{1}{m}np.sum(dZ^{[1]}) db[1]=m1np.sum(dZ[1])
以上矩阵的维度如下:
(1) W [ 2 ] W^{[2]} W[2]的维度是 ( n [ 2 ] , n [ 1 ] ) (n^{[2]},n^{[1]}) (n[2],n[1])
(2) Z [ 2 ] Z^{[2]} Z[2] d Z [ 2 ] dZ^{[2]} dZ[2]的维度都是 ( n [ 2 ] , 1 ) (n^{[2]},1) (n[2],1)。如果是二元分类,那么维度就是 ( 1 , 1 ) (1,1) (1,1)
(3) Z [ 1 ] Z^{[1]} Z[1] d Z [ 1 ] dZ^{[1]} dZ[1]的维度都是 ( n [ 1 ] , 1 ) (n^{[1]},1) (n[1],1)
实现反向传播的技巧就是要保证矩阵的维度相互匹配

9. 随机初始化 (Radom Initialization)

当你训练神经网络时,权重随机初始化是很重要的。对于逻辑回归,把权重初始化为0当然也是可以的。但是对于一个神经网络,如果把权重或者参数都初始化为0,那么梯度下降将不会起作用。
在这里插入图片描述

以上图为例,该神经网络有两个输入特征,因此 n [ 0 ] n^{[0]} n[0]=2,而隐藏层有两个隐藏单元,因此 n [ 1 ] n^{[1]} n[1]=2。假设将 W [ 1 ] W^{[1]} W[1]初始化为零,即 W [ 1 ] = [ 0 0 0 0 ] W^{[1]}=\begin{bmatrix}{0}&{0}\\{0}&{0}\\ \end{bmatrix} W[1]=[0000] b [ 1 ] b^{[1]} b[1]也初始化为零,即 b [ 1 ] = [ 0 , 0 ] T b^{[1]}=[0,0]^T b[1]=[0,0]T
如果按照这样子初始化的话,给网络输入任何样本, a [ 1 ] = g [ 1 ] ( w 1 [ 1 ] x + b [ 1 ] ) a^{[1]}=g^{[1]}(w^{[1]}_1x+b^{[1]}) a[1]=g[1](w1[1]x+b[1])两个隐藏单元 a 1 [ 1 ] a^{[1]}_1 a1[1] a 2 [ 1 ] a^{[1]}_2 a2[1]都计算同样的函数,则两个值相等。做反向传播计算的时候,由于对称性,这会导致 d z 1 [ 1 ] dz^{[1]}_1 dz1[1] d z 2 [ 1 ] dz^{[1]}_2 dz2[1]也相等,并且最终经过多次训练迭代,这两个隐藏单元仍然计算着同一个函数。因为大部分情况下 d W = [ u v u v ] dW=\begin{bmatrix}{u}&{v}\\{u}&{v}\\ \end{bmatrix} dW=[uuvv]会是这样的矩阵形式,每一行的数值都一样,因此我们执行权重更新 W [ 1 ] : = W [ 1 ] − α d W W^{[1]}:=W^{[1]}−\alpha dW W[1]:=W[1]αdW,每次迭代后 W [ 1 ] W^{[1]} W[1]的第一行都等于第二行。
以此类推,根据归纳法可以得到结论,无论多少次迭代,不管训练网络多长时间,隐藏单元仍然计算的是同样的函数,所有的隐藏单元就会对输出单元有同样的影响,这样是没有意义的。解决这个问题的方法就是随机初始化所有参数
随机初始化的Python代码如下:

W1 = np.random.randn(2,2)∗0.01
b1 = np.zeros((2,1))
W2 = np.random.randn(2,2)∗0.01
b2 = 0

w w w设为np.random.randn(2,2),从而生成参数为(2,2)的高斯分布随机变量,然后再乘上一个很小的系数,比如0.01,这样把它初始化为很小的随机数。 b b b不存在这个对称性的问题,因此可以把 b b b初始化为0。
至于这里的系数0.01,我们通常倾向于初始化为很小的随机数,因为如果使用tanh或者sigmoid激活函数,或者只在输出层有一个sigmoid激活函数,当你在计算激活函数的值时,若 w w w较大,则 z z z也会较大或者较小,这种情况下你很可能停在tanh或sigmoid函数较为平缓的地方,这意味着梯度下降会很慢,因此学习速度也就很慢。
在这里插入图片描述

事实上有时有比0.01更好的常数,当你训练一个单隐层神经网络(这是相对浅的神经网络,没有太多的隐藏层)时,设为0.01也是可以,但当你要训练一个非常深的神经网络,你可能要试试0.01以外的常数。

猜你喜欢

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