3.1 神经网络概述(Neural Network Overview)
上周我们讨论了逻辑回归,我们了解了 这个模型(
见图
3.1.1)
如何与下面公式
3.1
建立联系。
![](https://img-blog.csdnimg.cn/20200708140207688.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
如上所示,首先你需要输入特征
𝑥,参数𝑤和𝑏
,通过这些你就可以计算出
𝑧
,公式
3.2
:
![](https://img-blog.csdnimg.cn/20200708140310794.png)
![](https://img-blog.csdnimg.cn/20200708140439554.png)
神经网络看起来是如下这个样子(图
3.1.2
)。正如我之前已经提到过,你可以把许多
sigmoid
单元堆叠起来形成一个神经网络。对于图
3.1.1
中的节点,它包含了之前讲的计算的两个步骤:首先通过公式 3.1
计算出值
𝑧
,然后通过
𝜎(𝑧)
计算值
𝑎
。
![](https://img-blog.csdnimg.cn/20200708140949313.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
在这个神经网络(图
3.1.2
)对应的
3
个节点,首先计算第一层网络中的各个节点相关的数𝑧
[1]
,接着计算
𝛼
[1]
,在计算下一层网络同理; 我们会使用符号
[𝑚]
表示第
𝑚
层网络中 节点相关的数,这些节点的集合被称为第𝑚
层网络。这样可以保证
[𝑚]
不会和我们之前用来 表示单个的训练样本的 (𝑖)
(
即我们使用表示第
i
个训练样本
)
混淆; 整个计算过程,公式如下:
公式
3.3
:
![](https://img-blog.csdnimg.cn/2020070814140060.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/2020070814191641.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
我知道这其中有很多细节,其中有一点非常难以理解,即在逻辑回归中,通过直接计算
𝑧
得到结果𝑎
。而这个
神经网络中,我们反复的计算𝑧和𝑎,计算𝑎和𝑧
,最后得到了最终的输出 loss function
。
你应该记得逻辑回归中,有一些从后向前的计算用来计算导数
𝑑𝑎、𝑑𝑧
。同样,在神经网络中我们也有从后向前的计算,看起来就像这样,最后会计算𝑑𝑎
[2]
、
𝑑𝑧
[2]
,计算出来之后, 然后计算计算𝑑𝑊
[2]
、
𝑑𝑏
[2]
等,按公式
3.4
、
3.5
箭头表示的那样,从右到左反向计算。 现在你大概了解了一下什么是神经网络,基于逻辑回归重复使用了两次该模型得到上述 例子的神经网络。我清楚这里面多了很多新符号和细节,如果没有理解也不用担心,在接下来的视频中我们会仔细讨论具体细节。
3.2 神经网络的表示(Neural Network Representation)
我们首先关注一个例子,本例中的神经网络只包含一个隐藏层(图
3.2.1
)。这是一张神经网络的图片,让我们给此图的不同部分取一些名字。
图 3.2.1
输入特征
𝑥
1
、
𝑥
2
、
𝑥
3
,它们被竖直地堆叠起来,这叫做神经网络的
输入层
。它包含了神经网络的输入;然后这里有另外一层我们称之为隐藏层
(图
的四个结点)。
待会儿我会回过头来讲解术语"隐藏"的意义
;在本例中最后一层只由一个结点构成,而这个只 有一个结点的层被称为输出层
,它负责产生预测值。
解释隐藏层的含义:
在一个神经网络中, 当你使用监督学习训练它的时候,训练集包含了输入𝑥
也包含了目标输出
𝑦
,所以术语隐藏层的含义是在训练集中,这些中间结点的准确值我们是不知道到的,也就是说你看不见它们在 训练集中应具有的值。你能看见输入的值,你也能看见输出的值,但是隐藏层中的东西,在训练集中你是无法看到的。所以这也解释了词语隐藏层,只是表示你无法在训练集中看到他 们。
现在我们再引入几个符号,就像我们之前用向量𝑥
表示输入特征。这里有个可代替的记号𝑎
[0]
可以用来表示输入特征。
𝑎
表示激活的意思,它意味着网络中不同层的值会传递到它们后面的层中,输入层将𝑥
传递给隐藏层,所以我们将输入层的激活值称为
𝑎
[0]
;下一层即隐藏层也同样会产生一些激活值,那么我将其记作𝑎
[1]
,所以具体地,这里的第一个单元或结点我们将其表示为𝑎
1[1],第二个结点的值我们记为
𝑎
2[1]以此类推。所以这里的是一个四维的向量如果写成 Python
代码,那么它是一个规模为
4x1
的矩阵或一个大小为
4
的列向量,如下公 式,它是四维的,因为在本例中,我们有四个结点或者单元,或者称为四个隐藏层单元;
![](https://img-blog.csdnimg.cn/20200708143440170.png)
最后,我们要看到的隐藏层以及最后的输出层是带有参数的,这里的隐藏层将拥有两个参数𝑊
和
𝑏
,我将给它们加上上标
[1]
(
𝑊
[1]
,
𝑏
[1]
)
,表示这些参数是和第一层这个隐藏层有关系的。之后在这个例子中我们会看到𝑊
是一个
4x3
的矩阵,而
𝑏
是一个
4x1
的向量,第一个数字 4
源自于我们有四个结点或隐藏层单元,然后数字
3
源自于这里有三个输入特征,我们之后会更加详细地讨论这些矩阵的维数,到那时你可能就更加清楚了。相似的输出层也有一些与之关联的参数𝑊
[2]
以及
𝑏
[2]
。从维数上来看,它们的规模分别是
1x4
以及
1x1
。
1x4 是因为隐藏层有四个隐藏层单元而输出层只有一个单元,之后我们会对这些矩阵和向量的维度做
出更加深入的解释,所以
一个两层的神经网络什么样的了,即它是一个只有 一个隐藏层的神经网络。
3.3 计算一个神经网络的输出(Computing a Neural Network's output)
我们介绍只有一个隐藏层的神经网络的结构与符号表示。在这节的 视频中让我们了解神经网络的输出究竟是如何计算出来的。
首先,回顾下只有一个隐藏层的简单两层
神经网络结构
:
![](https://img-blog.csdnimg.cn/20200708145006158.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
其中,
𝑥
表示输入特征,
𝑎
表示每个神经元的输出,
𝑊
表示特征的权重,
上标表示神经网络的层数(隐藏层为 1),下标表示该层的第几个神经元
。这是神经网络的
符号惯例
,下同。
神经网络的计算
关于神经网络是怎么计算的,从我们之前提及的逻辑回归开始,如下图所示。用圆圈表示神经网络的计算单元,逻辑回归的计算有两个步骤,首先你按步骤计算出𝑧
,然后在第二 步中你以 sigmoid
函数为激活函数计算
𝑧
(得出
𝑎
),一个神经网络只是这样子做了好多次重复计算。
回到两层的神经网络,我们从隐藏层的第一个神经元开始计算,如上图第一个最上面的箭头所指。从上图可以看出,输入与逻辑回归相似,这个神经元的计算与逻辑回归一样分为两步,小圆圈代表了计算的两个步骤。
![](https://img-blog.csdnimg.cn/20200708145554866.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
向量化计算
如果你执行神经网络的程序,用
for
循环来做这些看起来真的很低效。所以接下来我们要做的就是把这四个等式向量化。向量化的过程是将神经网络中的一层神经元参数纵向堆积起来,例如隐藏层中的𝑤
纵向堆积起来变成一个
(4,3)
的矩阵,用符号
𝑊
[1]
表示。 另一个看待这个的方法是我们有四个逻辑回归单元,且每一个逻辑回归单元都有相对应的参数——
向量
𝑤
,把这四个向量堆积在一起,你会得出这
4×3
的矩阵。因此,
公式 3.8: 𝑧[𝑛] = 𝑤[𝑛]𝑥 + 𝑏[𝑛]----向量化就是,向量运算处理
𝑎[𝑛] = 𝜎(𝑧[𝑛])
![](https://img-blog.csdnimg.cn/20200708150203495.png)
![](https://img-blog.csdnimg.cn/2020070815022345.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708150410113.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
如上图左半部分所示为神经网络,把网络左边部分盖住先忽略,那么最后的输出单元就相当于一个逻辑回归的计算单元。当你有一个包含一层隐藏层的神经网络,你需要去实现以计算得到输出的是右边的四个等式,并且可以看成是一个向量化的计算过程,计算出隐藏层的四个逻辑回归单元和整个隐藏层的输出结果,如果编程实现需要的也只是这四行代码。
总结
:你能够根据给出的一个单独的输入特征向量,运用四行代码计算出一个简单神经网络的输出。接下来你将了解的是如何一次能够计算出不止一个样本的神经网络输出,而是能一次性计算整个训练集的输出。
3.4 多样本向量化(Vectorizing across multiple examples)
在这个视频,将会了解到
如何向量化多个训练样本
,并计算出结果。该过程与你在逻辑回归中所做类似。
逻辑回归是将各个训练样本组合成矩阵,对矩阵的各列进行计算。
神经网络是通过对逻辑回归中的等式简单的变形,让神经网络计算出输出值
。这种计算是所有的训练样本同时进行的,以下是实现它具体的步骤:
![](https://img-blog.csdnimg.cn/20200708151029433.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708151231683.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
如果有一个非向量化形式的实现,而且要计算出它的预测值,对于所有训练样本,需要 让
𝑖从 1 到𝑚
实现这四个等式:
![](https://img-blog.csdnimg.cn/20200708151334386.png)
![](https://img-blog.csdnimg.cn/2020070815140289.png)
所以,希望通过这个细节可以更快地正确实现这些算法。接下来讲讲如何向量化这些: 公式 3.12
:
![](https://img-blog.csdnimg.cn/20200708152135630.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708152613578.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
这种符号其中一个作用就是,可以通过训练样本来进行索引。这就是水平索引对应于不同的训练样本的原因,这些训练样本是从左到右扫描训练集而得到的。
在垂直方向,这个垂直索引对应于神经网络中的不同节点。例如,这个节点,该值位于矩阵的最左上角对应于激活单元,它是位于第一个训练样本上的第一个隐藏单元。它的下一 个值对应于第二个隐藏单元的激活值。它是位于第一个训练样本上的,以及第一个训练示例中第三个隐藏单元,等等。
当垂直扫描,是索引到隐藏单位的数字。当水平扫描,将从第一个训练示例中从第一个隐藏的单元到第二个训练样本,第三个训练样本……
直到节点对应于第一个隐藏单元的激活值,且这个隐藏单元是位于这𝑚
个训练样本中的最终训练样本。
从水平上看,
矩阵𝐴代表了各个训练样本
。从竖直上看,矩阵𝐴的不同的索引对应于不同的隐藏单元。 对于矩阵𝑍,
𝑋
情况也类似,水平方向上,对应于不同的训练样本;竖直方向上,对应不同的输入特征,而这就是神经网络输入层中各个节点。
神经网络上通过在多样本情况下的向量化来使用这些等式。
3.5 向 量 化 实 现 的 解 释 ( Justification for vectorized implementation)
在上一个视频中,我们学习到如何将多个训练样本横向堆叠成一个矩阵
𝑋
,然后就可以 推导出神经网络中
前向传播(forward propagation)
部分的向量化实现。 在这个视频中,我们将会继续了解到,为什么上一节中写下的公式就是将多个样本向量
化的正确实现。
![](https://img-blog.csdnimg.cn/20200708155317316.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708155350859.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
为什么之前我们对单个样本的计算要写成 𝑧[1](𝑖) = 𝑊[1]
𝑥(𝑖) + 𝑏[1]
这种形式,因为当有不同的训练样本时,将它们堆到矩阵𝑋的各列中,那么 它们的输出也就会相应的堆叠到矩阵 𝑍[1]
的各列中。现在我们就可以直接计算矩阵 𝑍[1] 加上𝑏[1]
,因为列向量
𝑏
[1]
和矩阵
𝑍
[1]
的列向量有着相同的尺寸,而
Python
的
广播机制
对 于这种矩阵与向量直接相加的处理方式是,将向量与矩阵的每一列相加。 所以这一节只是 说明了为什么公式 𝑍
[1] = 𝑊[1]𝑋 + 𝑏[1]
是前向传播的第一步计算的正确向量化实现,但事实证明,类似的分析可以发现,前向传播的其它步也可以使用非常相似的逻辑,即如果将输入 按列向量横向堆叠进矩阵,那么通过公式计算之后,也能得到成列堆叠的输出。
![](https://img-blog.csdnimg.cn/20200708155931307.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
3.6 激活函数(Activation functions)
![](https://img-blog.csdnimg.cn/202007081603439.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708160441305.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708160621837.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
sigmoid
函数和
tanh
函数两者共同的缺点是,
在𝑧特别大或者特别小的情况下,导数的 梯度或者函数的斜率会变得特别小,最后就会接近于 0,导致降低梯度下降的速度。
在机器学习另一个很流行的函数是:修正线性单元的函数(
ReLu
),
ReLu
函数图像是如 下图。 公式 3.22
:
𝑎 = 𝑚𝑎𝑥(0, 𝑧)
所以,只要
𝑧
是正值的情况下,导数恒等于 1,当
𝑧
是负 值的时候,导数恒等于 0
。从实际上来说,当使用𝑧的导数时,
𝑧
=0
的导数是没有定义的。但 是当编程实现的时候,𝑧
的取值刚好等于
0.00000001
,这个值相当小,所以,在实践中,不需要担心这个值,𝑧
是等于
0
的时候,假设一个导数是
1
或者
0
效果都可以。
这有一些选择激活函数的经验法则:
如果输出是
0
、
1
值(二分类问题),则输出层选择
sigmoid
函数,然后其它的所有单 元都选择 Relu
函数。
这是很多激活函数的默认选择,如果在隐藏层上不确定使用哪个激活函数,那么通常会 使用 Relu
激活函数。有时,也会使用
tanh
激活函数,但
Relu
的一个优点是:
当𝑧是负值的 时候,导数等于 0。
这里也有另一个版本的
Relu
被称为
Leaky Relu
。 当𝑧
是负值时,这个函数的值不是等于
0
,而是轻微的倾斜,如图。
这个函数通常比
Relu
激活函数效果要好,尽管在实际中
Leaky ReLu
使用的并不多。
![](https://img-blog.csdnimg.cn/20200708161612496.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
两者的优点是:
第一,
在
𝑧
的区间变动很大的情况下,激活函数的导数或者激活函数的斜率都会远大于 0,在程序实现就是一个
if-else
语句,而
sigmoid
函数需要进行浮点四则运算,在实践中, 使用 ReLu
激活函数神经网络通常会比使用
sigmoid
或者
tanh
激活函数学习的更快。
第二,
sigmoid
和
tanh
函数的导数在正负饱和区的梯度都会接近于
0,这会造成梯度弥散,而
Relu 和
Leaky ReLu 函数大于 0 部分都为常数,不会产生梯度弥散现象。(同时应该注意到的是,
Relu 进入负半区的时候,梯度为 0,神经元此时不会训练,产生所谓的稀疏性,而
Leaky ReLu 不会有这问题)
𝑧
在
ReLu
的梯度一半都是
0
,但是,有足够的隐藏层使得
z
值大于
0
,所以对大多数的 训练数据来说学习过程仍然可以很快。
快速概括一下不同激活函数的过程和结论。
sigmoid
激活函数:除了输出层是一个二分类问题基本不会用它。
tanh
激活函数:
tanh
是非常优秀的,几乎适合所有场合
。
ReLu
激活函数:最常用的默认函数,,如果不确定用哪个激活函数,就使用
ReLu
或者
Leaky ReLu
。
公式 3.23: 𝑎 = 𝑚𝑎𝑥(0.01𝑧, 𝑧)
为什么常数是 0.01?当然,可以为学习算法选择不同的参数。
在选择自己神经网络的激活函数时,有一定的直观感受,在深度学习中的经常遇到一个
问题:在编写神经网络的时候,会有很多选择:隐藏层单元的个数、激活函数的选择、初始 化权值……这些选择想得到一个对比较好的指导原则是挺困难的。
鉴于以上三个原因,以及在工业界的见闻,提供一种直观的感受,哪一种工业界用的多, 哪一种用的少。但是,自己的神经网络的应用,以及其特殊性,是很难提前知道选择哪些效 果更好。所以通常的建议是:如果不确定哪一个激活函数效果更好,可以把它们都试试,然 后在验证集或者发展集上进行评价。然后看哪一种表现的更好,就去使用它。 为自己的神经网络的应用测试这些不同的选择,会在以后检验自己的神经网络或者评估 算法的时候,看到不同的效果。如果仅仅遵守使用默认的 ReLu
激活函数,而不要用其他的 激励函数,那就可能在近期或者往后,每次解决问题的时候都使用相同的办法。
3.7 为什么需要非线性激活函数?(why need a nonlinear activation function?)
为什么神经网络需要非线性激活函数?
事实证明:要让你的神经网络能够计算出有趣的函数,你必须使用非线性激活函数
,
证明如下: 这是神经网络正向传播的方程,现在我们去掉函数𝑔,然后令
𝑎
[1]
= 𝑧
[1]
,或者我们也可 以令𝑔(𝑧) = 𝑧
,这个有时被叫做线性激活函数(更学术点的名字是恒等激励函数,因为它们 就是把输入值输出)。为了说明问题我们把𝑎[2] = 𝑧
[2]
,那么这个模型的输出𝑦或仅仅只是输 入特征𝑥
的线性组合。
![](https://img-blog.csdnimg.cn/20200708182139914.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
如果你是用线性激活函数或者叫恒等激励函数,那么神经网络只是把输入线性组合再输出。
我们稍后会谈到深度网络,有很多层的神经网络,很多隐藏层。事实证明,如果你使用线性激活函数或者没有使用一个激活函数,那么无论你的神经网络有多少层一直在做的只是计算线性函数,所以不如直接去掉全部隐藏层。在我们的简明案例中,
事实证明如果你在隐藏层用线性激活函数,在输出层用 sigmoid 函数,那么这个模型的复杂度和没有任何隐藏层的标准 Logistic 回归是一样的
,如果你愿意的话,可以证明一下。
在这里线性隐层一点用也没有,因为这两个线性函数的组合本身就是线性函数,所以除非你引入非线性,否则你无法计算更有趣的函数,即使你的网络层数再多也不行;
只有一个地方可以使用线性激活函数------𝑔(𝑧) = 𝑧,就是你在做机器学习中的回归问题。
𝑦 是一个实 数,举个例子,比如你想预测房地产价格,𝑦 就不是二分类任务
0
或
1
,而是一个实数,从 0 到正无穷。如果
𝑦
是个实数,那么在输出层用线性激活函数也许可行,你的输出也是一个 实数,从负无穷到正无穷。
总而言之,
不能在隐藏层用线性激活函数
,可以用
ReLU
或者
tanh
或者
leaky ReLU 或者其他的非线性激活函数,
唯一可以用线性激活函数的通常就是输出层;除了这种情况,会在隐层用线性函数的,除了一些特殊情况,比如与压缩有关的,那方面在这里将不深入讨论。在这之外,在隐层使用线性激活函数非常少见。因为房价都是非负数,所以我们也可以在输出层使用
ReLU 函数这样你的𝑦^都大于等于 0。理解为什么使用非线性激活函数对于神经网络十分关键,接下来我们讨论梯度下降,并在下一个视频中开始讨论梯度下降的基础——激活函数的导数
3.8 激活函数的导数(Derivatives of activation functions)
在
神经网络中使用反向传播的时候,你真的需要计算激活函数的斜率或者导数
。针对以下四种激活,求其导数如下:
![](https://img-blog.csdnimg.cn/20200708182935774.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708183024647.png)
![](https://img-blog.csdnimg.cn/2020070818305675.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708183230958.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
在神经网络中
;
![](https://img-blog.csdnimg.cn/20200708183307952.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708183328859.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
3.9 神 经 网 络 的 梯 度 下 降 ( Gradient descent for neural networks)
![](https://img-blog.csdnimg.cn/20200708183712357.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708183906816.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708184029988.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708184051949.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
上述是反向传播的步骤,注:这些都是针对所有样本进行过向量化,
𝑌
是
1 × 𝑚
的矩阵;
这里
np.sum
是
python
的
numpy
命令,
axis=1
表示水平相加求和,
keepdims
是防止 python 输出那些古怪的秩数
(𝑛, )
,加上这个确保阵矩阵
𝑑𝑏
[2]
这个向量输出的维度为
(𝑛, 1)
这 样标准的形式。
目前为止,我们计算的都和
Logistic
回归十分相似,但当你开始计算反向传播时,你需 要计算,是隐藏层函数的导数,输出在使用 sigmoid
函数进行二元分类。这里是进行逐个元 素乘积,因为𝑊
[2]𝑇
𝑑𝑧
[2]
和
(𝑧
[1]
)
这两个都为
(𝑛
[1]
, 𝑚)
矩阵; 还有一种防止 python
输出奇怪的秩数,需要显式地调用
reshape 把 np.sum 输出结 果写成矩阵形式。
以上就是正向传播的 4 个方程和反向传播的 6 个方程
,这里我是直接给出的,在下个视频中,我会讲如何导出反向传播的这 6
个式子的。如果你要实现这些算法,你必须正确执行正向和反向传播运算,你必须能计算所有需要的导数,用梯度下降来学习神经网络的参数; 你也可以许多成功的深度学习从业者一样直接实现这个算法,不去了解其中的知识。
3.10(选修)直观理解反向传播(Backpropagation intuition)
下图是逻辑回归的推导:
回想一下逻辑回归的公式
![](https://img-blog.csdnimg.cn/20200708184601973.png)
所以回想当时我们讨论逻辑回归的时候,我们有这个正向传播步骤,其中我们计算
𝑧
, 然后𝑎
,然后损失函数
𝐿
。
![](https://img-blog.csdnimg.cn/20200708184724691.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/2020070818493290.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708185330568.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200708185424312.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hsdHQzODM4,size_16,color_FFFFFF,t_70)
吴恩达老师认为反向传播的推导是机器学习领域最难的数学推导之一,矩阵的导数要用链式法则来求,如果这章内容掌握不了也没大的关系,只要有这种直觉就可以了。还有一点,
就是初始化你的神经网络的权重,不要都是 0,而是随机初始化
,下一章将详细介绍原因。
3.11 随机初始化(Random+Initialization)
由此可以推导,如果你把权重都初始化为
0
,那么由于隐含单元开始计算同一个函数, 所有的隐含单元就会对输出单元有同样的影响。一次迭代后同样的表达式结果仍然是相同 的,即隐含单元仍是对称的。通过推导,两次、三次、无论多少次迭代,不管你训练网络多长时间,隐含单元仍然计算的是同样的函数。因此这种情况下超过 1 个隐含单元也没什么意义,因为他们计算同样的东西。当然更大的网络,比如你有 3 个特征,还有相当多的隐含单元。
如果你要初始化成
0
,由于所有的隐含单元都是对称的,无论你运行梯度下降多久,他们一直计算同样的函数。这没有任何帮助,因为你想要两个不同的隐含单元计算不同的函数, 这 个 问 题 的 解 决 方 法 就 是 随 机 初 始 化 参 数 。 你 应 该 这 么 做 : 把 𝑊
[1]
设 为 np.random.randn(2,2)(
生成高斯分布
)
,通常再乘上一个小的数,比如
0.01
,这样把它初 始化为很小的随机数。然后𝑏
没有这个对称的问题(叫做
symmetry breaking problem),所 以可以把 𝑏
初始化为
0
,因为只要随机初始化𝑊你就有不同的隐含单元计算不同的东西, 因此不会有 symmetry breaking
问题了。相似的,对于𝑊[2]你可以随机初始化,
𝑏
[2]
可以初始
化为
0
。
回顾一下:如果
𝑤
很大,那么你很可能最终停在(甚至在训练刚刚开始的时候)
𝑧
很大的 值,这会造成 tanh
/
Sigmoid
激活函数饱和在龟速的学习上,如果你没有
sigmoid
/
tanh
激活 函数在你整个的神经网络里,就不成问题。但如果你做二分类并且你的输出单元是 Sigmoid 函数,那么你不会想让初始参数太大,因此这就是为什么乘上 0.01
或者其他一些小数是合 理的尝试。对于𝑤
[2]
一样,就是
np.random.randn((1,2))
,我猜会是乘以
0.01
。 事实上有时有比 0.01
更好的常数,当你训练一个只有一层隐藏层的网络时(这是相对 浅的神经网络,没有太多的隐藏层),设为 0.01
可能也可以。但当你训练一个非常非常深 的神经网络,你可能会选择一个不同于的常数而不是 0.01
。下一节课我们会讨论怎么并且何 时去选择一个不同于 0.01
的常数,但是无论如何它通常都会是个相对小的数。 好了,这就是这周的视频。你现在已经知道如何建立一个一层的神经网络了,初始化参 数,用前向传播预测,还有计算导数,结合反向传播用在梯度下降中。