吴恩达-深度学习(第三章)

  • 神经网络

本章开始首先快速了解如何实现神经网络,在之前的课程中,曾讨论了逻辑回归,并且了解了逻辑回归和下面的流程图的关系。

在这里你需要输入特征x,参数w和b,用来计算z,然后用z计算出a,而后用a同时表示输出ŷ,之后可以计算损失函数L。

    1. 正向传播

神经网络看起来是上图这样,可以将许多sigmoid单元堆叠起来构成一个神经网络。神经网络的结构与逻辑回归类似,只是神经网络的层数比逻辑回归多一层,多出来的中间那层称为隐藏层或中间层。这样从计算上来说,神经网络的正向传播过程分成两层而之前,对应两个计算步骤:

  1. 输入层到隐藏层,用上标[1]来表示:首先计算出z[1]值,然后计算a[1]值,在这个神经网络中这些节点将会对应一个类似z[1]的计算,同时对应一个类似a[1]的计算。
  2. 隐藏层到输出层,用上标[2]来表示:然后这个节点会对应另一个类似z[1]和a[1]的计算。

【注】:方括号上标[i]表示当前所处的层数;圆括号上标(i)表示第i个样本。

 

我们需要学会一种直觉:从一个逻辑回归中,先得到z,后计算a,在这个神经网络中,我们需要多次计算反复计算z和a,最后计算损失函数。

    1. 反向传播

同样,反向传播过程也分成两层。第一层是输出层到隐藏层,第二层是隐藏层到输入层。就像红色箭头这样次右向左反向计算。

  • 神经网络的表现形式

这一小节具体讨论神经网络究竟代表着什么,以集中于神经网络的单隐藏层案例进行讨论。

x1,x2,x3时神经网络输入层,中间节点这是神经网络隐藏层,后一个节点则时神经网络输出层。

在神经网络中,带有监督学习的训练集包含输入的x值,以及输出y值,所以术语隐藏层是指在训练集中,中间这一层节点的真实值并没有所观察。这就是你看不到他们为什么应该在训练集里,你看到的输入是什么,你看到的输出层就是什么,但训练集中间隐藏层的东西是看不见的,这就是‘隐藏’的意思。因为你训练集中看不见这些,让我们进一步了解下这些符号。

在写法上,我们通常把输入矩阵X记为a[0],把隐藏层输出记为a[1],上标从0开始。用下标表示第几个神经元,注意下标从1开始。例如a[1]1表示隐藏层第1个神经元,表示隐藏层第2个神经元等等。这样,隐藏层有4个神经元就可以将其输出a[1]写成矩阵的形式:

 最后,相应的输出层记为a[2],ŷ.这种单隐藏层神经网络也被称为两层神经网络(2 layer NN)。之所以叫两层神经网络是因为,通常我们只会计算隐藏层输出和输出层的输出,输入层是不用计算的。这也是我们把输入层层数上标记为0的原因(a[0])。

关于隐藏层对应的权重W[1]和常数项b[1],W[1]的维度是(4,3)。这里的4对应着隐藏层神经元个数,3对应着输入层x特征向量包含元素个数。常数项b[1]的维度是(4,1),这里的4同样对应着隐藏层神经元个数。关于输出层对应的权重W[2]和常数项b[2],W[2]的维度是(1,4),这里的1对应着输出层神经元个数,4对应着输出层神经元个数。常数项b[2]的维度是(1,1),因为输出只有一个神经元。总结一下,第i层的权重W[i]维度的行等于i层神经元的个数,列等于i-1层神经元的个数;第i层常数项b[i]维度的行等于i层神经元的个数,列始终为1。

  • 计算神经网络的输出

回顾一下逻辑回归,在逻辑回归中曾讲过一个圆代表了两步计算,首先你可以按照这种方式计算z,然后计算z作为激活函数,神经网络只是把这个过程做了多次。

 

首先我们注意隐藏层里面的一个节点,我们先看隐藏层的第一个节点,和左边的逻辑回归类似,从输层到隐藏层进行了两步计算:

 

 

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

 其中a[1]为:

 上述每个节点的计算都对应着一次逻辑运算的过程,分别由计算z和a两部分组成。

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

 

之前也介绍过,这里顺便提一下,W[1]的维度是(4,3),b[1]的维度是(4,1),W[2]的维度是(1,4),b[2]的维度是(1,1)。这点需要特别注意。

 ·多样本向量化

在这节课中我们主要学习如何对多个训练实例矢量化,这个结果会和我们之前看到的逻辑回归的结果很相似,通过把不同的训练实例按列堆叠在一个矩阵里面,我们就可以拿来之前的视频里的等式,做一些很小的改动,使得神经网络在同时计算所有训练实例的预测。

 由上图所示,给定一个特征矢量x,我们可以用它们来取得一个训练实例的a[2]=ŷ。对于m个训练样本,我们需要重复这个过程,使用激活函数的标记法,可以得到:对于给定的X(1)有:a[2](1)=ŷ(1);对于给定的X(2)有:a[2](2)=ŷ(2);以此类推,对于给定的X(1)有:a[2](n)=ŷ(n)。其中圆括号(i)代表第i个训练实例,方括号[2]代表第二层。

对于未矢量化的实现,当你想要计算所有训练实例的预测时,你需要用一个for循环i从1到m实现上图这四个等式。

不使用for循环,利用矩阵运算的思想,输入矩阵X的维度为(nx,m)。这样,我们可以把上面的for循环写成矩阵运算的形式:

其中,Z[1]的维度是(4,m),4是隐藏层神经元的个数;A[1]的维度与Z[1]相同;Z[2]和A[2]的维度均为(1,m)。对上面这四个矩阵来说,均可以这样来理解:行表示神经元个数,列表示样本数目m。

  • 向量化实现的解释

该小节利用第二章向量化基础和python广播机制,对m个样本的神经网络矩阵运算过程进行推导,证明其实现过程。

  • 激活函数

建立神经网络,首要是确定隐藏层中应当使用哪种激活函数,以及神经网络的输出单位,回归之前所学,我们使用的是sigmoid激活函数,但是其他激活函数也各有其适用的运用场景。下面是常见的几种激活函数:

·sigmoid函数(不推荐使用

-- 函数的最左端和最右端都有种区域饱和的趋势,也就是若输入过小sigmoid函数得到的值会趋于0,输入过大得到的值也会趋于0,很容易造成梯度消失。

-- 对于输出层的激活函数,因为二分类问题的输出取值为{0,+1},所以一般会选择sigmoid作为激活函数。

 ·tanh函数

-- 几乎总是比sigmoid函数性能更好

-- 具有居中数据的效果

-- 函数的最左端和最右端都有种区域饱和的趋势,很容易造成梯度消失。

 ·ReLU函数(推荐使用)

-- 非二元分类问题(输出0或1),都很适用

-- 缺点:z为负数的时候导数等于0

-- 对于隐藏层,选择ReLU作为激活函数能够保证z大于零时梯度始终为1,从而提高神经网络梯度下降算法运算速度。

 ·Leaky ReLU函数

-- ReLU改进,z为负数时,导数不为0,略有倾斜,通常表现比ReLU好,但在实践中并没有被使用

 【注】:

·如果是分类问题,输出层的激活函数一般会选择sigmoid函数。但是隐藏层的激活函数通常不会选择sigmoid函数,tanh函数的表现会比sigmoid函数好一些。

·实际应用中,通常会会选择使用ReLU或者Leaky ReLU函数,保证梯度下降速度不会太小。

  • 为什么需要非线性激活函数?

上小节讲的四种激活函数都是非线性(non-linear)的。那是否可以使用线性激活函数呢?其实并不可以。下面给出简要解释与说明。

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

 对上式中a[2]进行化简计算

 经过推导发现a[2]仍是输入变量x的线性组合。这表明,使用神经网络与直接使用线性模型的效果并没有什么两样。即便是包含多层隐藏层的神经网络,如果使用线性函数作为激活函数,最终的输出仍然是输入x的线性模型。这样的话神经网络就没有任何作用了。因此,隐藏层的激活函数必须要是非线性的。

如果所有的隐藏层全部使用线性激活函数,只有输出层使用非线性激活函数,那么整个神经网络的结构就类似于一个简单的逻辑回归模型,而失去了神经网络模型本身的优势和价值。

值得一提的是,如果是预测问题而不是分类问题,输出y是连续的情况下,输出层的激活函数可以使用线性函数。如果输出y恒为正值,则也可以使用ReLU激活函数,具体情况,具体分析。

  • 激活函数的导数

当在神经网络中使用反向传播算法时,需要计算激活函数的导数(斜率)。本小姐主要介绍有哪些可选择的激活函数以及如何计算这些函数的导数。

·sigmoid函数

其导数计算如下:

·tanh函数

其导数计算如下:

·RuLU函数

其导数计算如下:

·leaky RuLU函数

其导数计算如下:

  • 神经网络的梯度下降

本小节将学习如何在神经网络中使用一个隐含层实现梯度下降。

仍以浅层神经网络为例,包含的参数为W[1],b[1],W[2],b[2]。令输入层的特征向量个数nx=n[0],隐藏层神经元个数为n[1],输出层神经元个数为n[2]=1。则W[1]的维度为(n[1],n[0]),b[1]的维度为(n[1],1),W[2]的维度为(n[2],n[1]),b[2]的维度为(n[2],1)。

该神经网络正向传播过程为:

 其中,g(·)表示激活函数。

反向传播是计算导数(梯度)的过程,这里先列出来Cost function对各个参数的梯度

 ·第三行的np.sum()表示水平方向求和,keepdim防止输出奇怪的一阶数组,也就是说保证数组db[2]的维度会是(n,1)。

具体的推导过程在第十节中。

  • 反向传播的直觉(选)

  • 随机初始化

将权重参数进行随机初始化非常重要,在逻辑回归问题一种,吧权重参数初始化为0是可行的,但是将其全部初始化为0,并使用梯度下降,将无法取得预期的效果。

举例说明:一个浅层神经网络包含两个输入,隐藏层包含两个神经元。如果权重W[1]和W[2]都初始化为零,即:

 

这样使得隐藏层第一个神经元的输出等于第二个神经元的输出,即a[1]1=a[1]2。在反向传播过程中,通过推导可以得到d=d,以及d=d。因此,使用这样的初始化会导致隐藏层两个神经元对应的权重行向量和在每次迭代更新后都会得到完全相同的结果,始终等于,完全对称。这样隐藏层设置多个神经元就没有任何意义了。然而,参数b可以全部初始化为零,并且不会影响神经网络训练效果。

 基于上述分析,只有进行随机初始化能解决这样的问题。在python中使用如下语句进行初始化:

        W[1] = np.random.randn((2,2))*0.01

        b[1] = np.zero((2,1))

        W[2] = np.random.randn((1,2))*0.01

        b[2] = 0

将W[1]1和W[1]2乘以0.01的目的是尽量使得权重W初始化比较小的值。其原因是:在使用sigmoid函数或者tanh函数时,如果步长过大,当计算激活值时,z的绝对值可能是非常大的数,就会导致在函数两侧部分的梯度斜率非常小,即会导致梯度下降会很缓慢,影响学习效率。

【注】:当在训练仅含一个隐藏层的神经网络时,显而易见0.01这个数值在类似于这样不含过多隐藏层的浅层神经网络中是非常非常合适的;但当训练一个非常复杂的深度神经网络时,通常会使用一个不同的数值,这一点在下一章中会有涉及。无论如何,通常情况我们的计算结果都会是个相对小的数值。

  • 小结

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值