1.3)深度学习笔记------浅层神经网络

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/cg129054036/article/details/86609250

目录

1)Neural Network Overview

2)Neural Network Representation

3)Computing a Neural Network’s Output(重点)

4)Vectorizing across multiple examples

5)Activation functions

6)Why need a nonlinear activation function

7)Derivatives of activation functions

8)Gradient descent for neural networks(重点)

9)Backpropagation intuition(选修)(掌握)

10)Random Initialization

11)Summary


以下笔记是吴恩达老师深度学习课程第一门课第三周的的学习笔记:Shallow neural networks。笔记参考了黄海广博士的内容,在此表示感谢。 


1)Neural Network Overview

本周我们开始学习如何实现一个神经网络。现在我们开始快速浏览一下如何实现神经网络,上周我们讨论了逻辑回归。神经网络的结构与逻辑回归类似,神经网络可以看作是多个sigmoid单元堆叠而成。下图中上方为单个sigmoid单元,而另一个就是神经网络了。在这个神经网络里首先对应的3个节点,计算第一层网络中各个节点的输出z^{[1]},紧接着计算a^{[1]},位于第二层的节点计算z^{[2]}a^{[2]}。整个过程如下:

第一层:输入层到隐藏层

                                                                             $$z^{[1]} = (w^{[1]})^Tx+b^{[1]}$$

                                                                                          $$a^{[1]} = \sigma(z^{[1]})$$

第一层:隐藏层到输出层

                                                                             $$z^{[2]} = (w^{[2]})^Ta^{[1]}+b^{[2]}$$

                                                                                          $$a^{[2]} = \sigma(z^{[2]})$$

在这里,我们规定方括号上标[i]表示当前所处的层数。


2)Neural Network Representation

我们再来看看我们上节课中的二层神经网络图片(一般规定输入层为零层),下图中的神经网络包含一个隐藏层。输入特征被称作神经网络的输入层(the input layer)。 神经网络的隐藏层(a hidden layer)。“隐藏”的含义是在训练集中,这些中间节点的真正数值是无法看到的。输出层(the output layer)负责输出预测值。

                                                      

在写法上,我们通常把输入特征记为a^{[0]},隐藏层记为a^{[1]},隐藏层包含四个节点,从上往下,下标依次递增。隐藏层写成矩阵向量形式为:

                                                                          

最后,输出层为a^{[2]}。隐藏层和输出层都是带有参数 W 和 b 的。它们都使用上标[1]来表示是和第一个隐藏层有关,或者上标[2]来表示是和输出层有关。


3)Computing a Neural Network’s Output(重点)

介绍完神经网络的表示,现在我们来推导神经网络的推导过程,我们就把两层神经网络看作是两次计算逻辑回归。逻辑回归计算分为两个部分,分别计算z和a。

                                      

回到两层的神经网络,我们从隐藏层的第一个神经元开始计算,如上图第一个最上面的箭头所指。从上图可以看出,输入与逻辑回归相似,这个神经元的计算与逻辑回归一样分为两步,小圆圈代表了计算的两个步骤。

  •  第一步,计算z^{[1]}_1 = w^{[1]T}_1x + b^{[1]}_1$
  •  第二步,通过激活函数计算a^{[1]}_1 = \sigma(z^{[1]}_1)$

隐藏层的第二个以及后面两个神经元的计算过程一样,只是注意符号表示不同,最终分别得到$a^{[1]}_2 ,a^{[1]}_3,a^{[1]}_4$,详细结果见下:

                                                 $z^{[1]}_1 = w^{[1]T}_1x + b^{[1]}_1, a^{[1]}_1 = \sigma(z^{[1]}_1)$

                                                 $z^{[1]}_2 = w^{[1]T}_2x + b^{[1]}_2, a^{[1]}_2 = \sigma(z^{[1]}_2)$

                                                 $z^{[1]}_3 = w^{[1]T}_3x + b^{[1]}_3, a^{[1]}_3 = \sigma(z^{[1]}_3)$

                                                 $z^{[1]}_4 = w^{[1]T}_4x + b^{[1]}_4, a^{[1]}_4 = \sigma(z^{[1]}_4)$

从隐藏层到输出层的计算公式为:

                                                 z^{[2]} = w^{[2]T}a^{[1]} + b^{[2]}, a^{[2]} = \sigma(z^{[2]})

其中a^{[1]}为:

                                                                     

值得注意的是层与层之间参数矩阵的规格大小。

  • 输入层和隐藏层之间:${(w^{[1]})}^T$的 shape 为(4,3),前面的 4 是隐藏层神经元的个数,后面的 3 是输入层神经元的个数;$b^{[1]}$的 shape 为(4,1),和隐藏层的神经元个数相同。
  • 隐藏层和输出层之间:${(w^{[2]})}^T$的 shape 为(1,4),前面的 1 是输出层神经元的个数,后面的 4 是隐藏层神经元的个数;$b^{[2]}$的 shape 为(1,1),和输出层的神经元个数相同。

为了提高程序运算速度,我们引入向量化和矩阵运算的思想,将上述表达式转换成矩阵运算的形式:

                               


4)Vectorizing across multiple examples

上一部分我们只是介绍了单个样本的神经网络正向传播的运算过程。而对于m个训练样本,我们也可以使用矩阵相乘的形式来提高计算效率。而且它的形式与上一部分单个样本的矩阵运算十分相似,比较简单。先来看使用for循环计算多个样本输出:

                              

上图中,我们使用for循环计算了神经网络的输出,现在我们把上面的for循环写成矩阵运算的形式:

                                                 $Z^{[1]} = W^{[1]}X+b^{[1]}$

                                                     A^{[1]}=\sigma(Z^{[1]})

                                               Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]}

                                                       A^{[2]}=\sigma(Z^{[2]})

从水平上看,矩阵A代表了各个训练样本。从竖直上看,矩阵A的不同的索引对应于不同的隐藏单元。对于矩阵Z,X情况也类似,水平方向上,对应于不同的训练样本;竖直方向上,对应不同的输入特征,而这就是神经网络输入层中各个节点。神经网络上通过在多样本情况下的向量化来使用这些等式。


5)Activation functions

之前我们都是选用 sigmoid 函数作为激活函数,但有时其他函数的效果会好得多。 下面我们来总结深度学习中常见的激活函数:

sigmoid函数:对出输出层的激活函数,因为二分类取值范围在(0,1),一般会选择sgmoid函数。

tanh函数:效果几乎总比 sigmoid 函数好(除二元分类的输出层,因为我们希望输出的结果介于 0 到 1 之间),因为函数输出介于 -1 和 1 之间,激活函数的平均值就更接近 0,有类似数据中心化的效果。

然而,tanh 函数存在和 sigmoid 函数一样的缺点:当 z 趋紧无穷大(或无穷小),导数的梯度(即函数的斜率)就趋紧于 0,这使得梯度算法的速度大大减缓。

ReLU函数:当 z > 0 时,梯度始终为 1,从而提高神经网络基于梯度算法的运算速度,收敛速度远大于 sigmoid 和 tanh。然而当 z < 0 时,梯度一直为 0,但是实际的运用中,该缺陷的影响不是很大。

Leaky ReLU函数:Leaky ReLU 保证在 z < 0 的时候,梯度仍然不为 0。理论上来说,Leaky ReLU 有 ReLU 的所有优点,但在实际操作中没有证明总是好于 ReLU,因此不常用。


6)Why need a nonlinear activation function

为什么神经网络需要非线性激活函数?事实证明:要让你的神经网络能够计算出有趣的函数,你必须使用非线性激活函数。

假设所有的激活函数都是线性的,为了简化计算,我们直接令激活函数g(z)=z,即a=z。那么,浅层神经网络的各层输出为:

                                                                                $$z^{[1]} = (w^{[1]})^Tx+b^{[1]}$$

                                                                                          $$a^{[1]} =z^{[1]}$$

                                                                             $$z^{[2]} = (w^{[2]})^Ta^{[1]}+b^{[2]}$$

                                                                                          $$a^{[2]} = z^{[2]}$$

对上式化简得:

            a^{[2]} = z^{[2]} = W^{[2]}(W^{[1]}x + b^{[1]}) + b^{[2]}=W^{[2]}W^{[1]}x + W^{[2]}b^{[1]} + b^{[2]}=W^{'}x + b^{'}

输出仍是输出x的线性组合,使用线性函数作为激活函数,最终的输出仍然是输入x的线性模型。

7)Derivatives of activation functions

在梯度下降反向计算过程中少不了计算激活函数的导数。

我们先来看一下sigmoid函数的导数:

                                      

  •                     g(z) = \frac{1}{1+e^{-z}},g\prime(z)=\frac{dg(z)}{dz} = \frac{1}{1+e^{-z}}(1-\frac{1}{1+e^{-z}})=g(z)(1-g(z))

tanh函数的导数:

                               

                                                                 g(z) = tanh(z) = \frac{e^{z} - e^{-z}}{e^{z} + e^{-z}}

                                                                \frac{d}{{d}z}g(z) = 1 - (tanh(z))^{2}

ReLU函数的导数:

                                          

                                                                       g(z) = max(0, z)

                                                   

Leaky ReLU函数导数:

                                                     

                                                  


8)Gradient descent for neural networks(重点)

现在我们来看卡在神经网络中如何计算梯度。还是我们前面提到的二层神经网络,你的单隐层神经网络会有W^{[1]}b^{[1]}W^{[2]}b^{[2]}这些参数,还有个n_x表示输入特征的个数,n^{[1]}表示隐藏单元个数,n^{[2]}表示输出单元个数。

二层神经网络的正向传播过程为:

                                                          $Z^{[1]} = W^{[1]}X+b^{[1]}$

                                                              A^{[1]}=\sigma(Z^{[1]})

                                                          Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]}

                                                               A^{[2]}=\sigma(Z^{[2]})

反向传播是计算梯度的过程,这里我们直接给出损失函数对各个参数的梯度:左边是梯度下降公式,右边是其向量化代码。

                                 


9)Backpropagation intuition(选修)(掌握)

这一节虽然是选修内容,但还是希望大家掌握,当然不理解也不要紧。

我们仍然使用计算图的方式来推导神经网络反向传播过程。记得之前介绍逻辑回归时,我们就引入了计算图来推导正向传播和反向传播,其过程如下图所示:

                             

由于多了一个隐藏层,神经网络的计算图要比逻辑回归的复杂一些,如下图所示。对于单个训练样本,正向过程很容易,反向过程可以根据梯度计算方法逐一推导。

                                                      

                                    


10)Random Initialization

如果在初始时将两个隐藏神经元的参数设置为相同的大小,那么两个隐藏神经元对输出单元的影响也是相同的,通过反向梯度下降去进行计算的时候,会得到同样的梯度大小,所以在经过多次迭代后,两个隐藏层单位仍然是对称的。无论设置多少个隐藏单元,其最终的影响都是相同的,那么多个隐藏神经元就没有了意义。

在初始化的时候,W 参数要进行随机初始化,不可以设置为 0。而 b 因为不存在对称性的问题,可以设置为 0。

以 2 个输入,2 个隐藏神经元为例:

W = np.random.rand(2,2)* 0.01
b = np.zeros((2,1))

这里将 W 的值乘以 0.01(或者其他的常数值)的原因是为了使得权重 W 初始化为较小的值,这是因为使用 sigmoid 函数或者 tanh 函数作为激活函数时,W 比较小,则 Z所得的值趋近于 0,梯度较大,能够提高算法的更新速度。而如果 W 设置的太大的话,得到的梯度较小,训练过程因此会变得很慢。

ReLU 和 Leaky ReLU 作为激活函数时不存在这种问题,因为在大于 0 的时候,梯度均为 1。


11)Summary

本节课主要介绍了浅层神经网络。

  1. 首先,我们简单概述了神经网络的结构:包括输入层,隐藏层和输出层;
  2. 然后,我们以计算图的方式推导了神经网络的正向传播,并以向量化的形式归纳出来;
  3. 接着,介绍了不同的激活函数并做了比较,实际应用中根据不同需要选择合适的激活函数。激活函数必须是非线性的;
  4. 然后,我们重点介绍了神经网络的反向传播过程以及各个参数的导数推导;
  5. 最后,介绍了权重随机初始化的重要性,必须对权重W进行随机初始化操作。

下面我们就要进行深层神经网络的学习了。

猜你喜欢

转载自blog.csdn.net/cg129054036/article/details/86609250