深度学习(5)

3.7 为什么需要非线性激活函数?(why need a nonlinear activation function? )

为什么神经网络需要非线性激活函数?事实证明:要让你的神经网络能够计算出有趣的函数,你必须使用非线性激活函数,证明如下:
这是神经网络正向传播的方程,现在我们去掉函数g,然后令a[1] = z [1] ,或者我们也可以令g(z) = z,这个有时被叫做线性激活函数(更学术点的名字是恒等激励函数,因为它们就是把输入值输出)。为了说明问题我们把a [2] = z [2] ,那么这个模型的输出𝑧或仅仅只是输入特征𝑦的线性组合。
如果我们改变前面的式子,令:
(1) 𝑏 [1] = 𝑨 [1] = 𝑋 [1] 𝑦 + 𝑐 [1]
(2) 𝑏 [2] = 𝑨 [2] = 𝑋 [2] 𝑏 [1] + 𝑐 [2] 将 式 子 (1) 代 入 式 子 (2) 中 , 则 : 𝑏 [2] = 𝑨 [2] =
𝑋 [2] (𝑋 [1] 𝑦 + 𝑐 [1] ) + 𝑐 [2]
(3) 𝑏 [2] = 𝑨 [2] = 𝑋 [2] 𝑋 [1] 𝑦 + 𝑋 [2] 𝑐 [1] + 𝑐 [2]
简化多项式得 𝑏 [2] = 𝑨 [2] = 𝑋 ′ 𝑦 + 𝑐 ′
如果你是用线性激活函数或者叫恒等激励函数,那么神经网络只是把输入线性组合再输出。
我们稍后会谈到深度网络,有很多层的神经网络,很多隐藏层。事实证明,如果你使用线性激活函数或者没有使用一个激活函数,那么无论你的神经网络有多少层一直在做的只是计算线性函数,所以不如直接去掉全部隐藏层。在我们的简明案例中,事实证明如果你在隐藏层用线性激活函数,在输出层用 sigmoid 函数,那么这个模型的复杂度和没有任何隐藏层的标准 Logistic 回归是一样的,如果你愿意的话,可以证明一下。
在这里线性隐层一点用也没有,因为这两个线性函数的组合本身就是线性函数,所以除非你引入非线性,否则你无法计算更有趣的函数,即使你的网络层数再多也不行;只有一个地方可以使用线性激活函数------g(𝑨) = 𝑨,就是你在做机器学习中的回归问题。𝑧 是一个实数,举个例子,比如你想预测房地产价格,𝑧 就不是二分类任务 0 或 1,而是一个实数,从0 到正无穷。如果𝑧 是个实数,那么在输出层用线性激活函数也许可行,你的输出也是一个
实数,从负无穷到正无穷。
总而言之,不能在隐藏层用线性激活函数,可以用 ReLU 或者 tanh 或者 leaky ReLU 或者其他的非线性激活函数,唯一可以用线性激活函数的通常就是输出层;除了这种情况,会在隐层用线性函数的,除了一些特殊情况,比如与压缩有关的,那方面在这里将不深入讨论。
在这之外,在隐层使用线性激活函数非常少见。因为房价都是非负数,所以我们也可以在输出层使用 ReLU 函数这样你的𝑧^ 都大于等于 0。
理解为什么使用非线性激活函数对于神经网络十分关键,接下来我们讨论梯度下降,并在下一个视频中开始讨论梯度下降的基础——激活函数的导数。

3.8 激活函数的导数(Derivatives of activation functions )

在神经网络中使用反向传播的时候,你真的需要计算激活函数的斜率或者导数。针对以
下四种激活,求其导数如下:
1)sigmoid activation function
在这里插入图片描述

图 3.8.1
其具体的求导如下:
公式 3.25:在这里插入图片描述
在神经网络中
在这里插入图片描述

  1. Tanh activation function
    在这里插入图片描述

其具体的求导如下:
公式 3.26:
在这里插入图片描述
在这里插入图片描述

在神经网络中;
3)Rectified Linear Unit (ReLU)
在这里插入图片描述
注:通常在𝑨= 0 的时候给定其导数 1,0;当然𝑨=0 的情况很少
4)Leaky linear unit (Leaky ReLU)
与 ReLU 类似
在这里插入图片描述

注:通常在𝑨 = 0的时候给定其导数 1,0.01;当然𝑨 = 0的情况很少

3.9 神经网络的梯度下降(Gradient descent for neural networks )

在这个视频中,我会给你实现反向传播或者说梯度下降算法的方程组,在下一个视频我们会介绍为什么这几个特定的方程是针对你的神经网络实现梯度下降的正确方程。
你的单隐层神经网络会有𝑋 [1] ,𝑐 [1] ,𝑋 [2] ,𝑐 [2] 这些参数,还有个𝑜 𝑦 表示输入特征的个数,𝑜 [1] 表示隐藏单元个数,𝑜 [2] 表示输出单元个数。
在我们的例子中,我们只介绍过的这种情况,那么参数:
矩阵𝑋 [1] 的维度就是(𝑜 [1] ,𝑜 [0] ),𝑐 [1] 就是𝑜 [1] 维向量,可以写成(𝑜 [1] ,1),就是一个的列向量。 矩阵𝑋 [2] 的维度就是(𝑜 [2] ,𝑜 [1] ),𝑐 [2] 的维度就是(𝑜 [2] ,1)维度。
你还有一个神经网络的成本函数,假设你在做二分类任务,那么你的成本函数等于:
Cost function:
公式:
在这里插入图片描述

loss function 和之前做 logistic 回归完全一样。
训练参数需要做梯度下降,在训练神经网络的时候,随机初始化参数很重要,而不是初
始化成全零。当你参数初始化成某些值后,每次梯度下降都会循环计算以下预测值:
在这里插入图片描述
在这里插入图片描述

正向传播方程如下:
forward propagation:
(1) 𝑨 [1] = 𝑋 [1] 𝑦 + 𝑐 [1]
(2) 𝑏 [1] = 𝜎(𝑨 [1] )
(3) 𝑨 [2] = 𝑋 [2] 𝑏 [1] + 𝑐 [2]
(4) 𝑏 [2] = g[2] (𝑨 [𝑨] ) = 𝜎(𝑨 [2] )
反向传播方程如下:
back propagation:
公式 3.32:
在这里插入图片描述

上述是反向传播的步骤,注:这些都是针对所有样本进行过向量化,𝑍是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 )

这个视频主要是推导反向传播。
下图是逻辑回归的推导:
回想一下逻辑回归的公式(参考公式 3.2、公式 3.5、公式 3.6、公式 3.15) 公式 3.38:
在这里插入图片描述

所以回想当时我们讨论逻辑回归的时候,我们有这个正向传播步骤,其中我们计算𝑨,
然后𝑏,然后损失函数𝑀。
公式 3.39:
在这里插入图片描述

神经网络的计算中,与逻辑回归十分类似,但中间会有多层的计算。下图是一个双层神经网络,有一个输入层,一个隐藏层和一个输出层。
前向传播:
计算𝑨 [1] ,𝑏 [1] ,再计算𝑨 [2] ,𝑏 [2] ,最后得到 loss function。
反向传播:
向后推算出𝑒𝑏 [2] ,然后推算出𝑒𝑨 [2] ,接着推算出𝑒𝑏 [1] ,然后推算出𝑒𝑨 [1] 。我们不需要对𝑦求导,因为𝑦是固定的,我们也不是想优化𝑦。向后推算出𝑒𝑏 [2] ,然后推算出𝑒𝑨 [2] 的步骤可以合为一步:
公式 3.40: 𝑒𝑨 [2] = 𝑏 [2] − 𝑧  ,  𝑒𝑋 [2] = 𝑒𝑨 [2] 𝑏 [1]
𝑈 (注意:逻辑回归中;为什么𝑏 [1]𝑈 多
了个转置:𝑒𝑥中的𝑋(视频里是𝑋𝑗[2] )是一个列向量,而𝑋 [2] 是个行向量,故需要加个转置);
公式 3.41: 𝑒𝑐 [2] = 𝑒𝑨 [2]
公式3.42: 𝑒𝑨 [1] = 𝑋 [2]𝑈 𝑒𝑨 [2] ∗ 𝑕[1] ′ (𝑨 [1] ) 注意:这里的矩阵:𝑋 [2] 的维度是:(𝑜 [2] ,𝑜 [1] )。
𝑨 [2] , 𝑒𝑨 [2] 的维度都是:(𝑜 [2] ,1),如果是二分类,那维度就是(1,1)。
𝑨 [1] ,𝑒𝑨 [1] 的维度都是:(𝑜 [1] ,1)。
证明过程: 见公式 3.42,
其中𝑋 [2]𝑈 𝑒𝑨 [2] 维度为:(𝑜 [1] ,𝑜 [2] )、(𝑜 [2] ,1)相乘得到(𝑜 [1] ,1),和𝑨 [1] 维度相同,𝑕[1] ′ (𝑨 [1] )
的维度为(𝑜 [1] ,1),这就变成了两个都是(𝑜 [1] ,1)向量逐元素乘积。
实现后向传播有个技巧,就是要保证矩阵的维度相互匹配。最后得到𝑒𝑋 [1] 和𝑒𝑐 [1] ,公
式 3.43: 𝑒𝑋 [1] = 𝑒𝑨 [1] 𝑦 𝑈 ,𝑒𝑐 [1] = 𝑒𝑨 [1]
可以看出𝑒𝑋 [1] 和𝑒𝑋 [2] 非常相似,其中𝑦扮演了𝑏 [0] 的角色,𝑦 𝑈 等同于𝑏 [0]𝑈 。
由: 𝑎 [1] = 𝑋 [1] 𝑦 + 𝑐 [1]  , 𝑏 [1] = 𝑕 [1] (𝑎 [1] ) 得到: 𝑎 [1] = 𝑋 [1] 𝑦 + 𝑐 [1] ,𝐵 [1] = 𝑕 [1] (𝑎 [1] )
在这里插入图片描述

注意:大写的𝑎 [1] 表示𝑨 1 ,𝑨 1 ,𝑨 1 …𝑨 1 的列向量堆叠成的矩阵,以下类同。
下图写了主要的推导过程:
在这里插入图片描述

吴恩达老师认为反向传播的推导是机器学习领域最难的数学推导之一,矩阵的导数要用链式法则来求,如果这章内容掌握不了也没大的关系,只要有这种直觉就可以了。还有一点,就是初始化你的神经网络的权重,不要都是 0,而是随机初始化,下一章将详细介绍原因。

3.11 随机初始化(Random+Initialization )

当你训练神经网络时,权重随机初始化是很重要的。对于逻辑回归,把权重初始化为 0
当然也是可以的。但是对于一个神经网络,如果你把权重或者参数都初始化为 0,那么梯度
下降将不会起作用。
让我们看看这是为什么。有两个输入特征,𝑜 [0] = 2,2 个隐藏层单元𝑜 [1] 就等于 2。 因
此与一个隐藏层相关的矩阵,或者说𝑋 [1] 是 22 的矩阵,假设把它初始化为 0 的 22 矩阵,𝑐 [1] 也等于 [0 0] 𝑈 ,把偏置项𝑐初始化为 0 是合理的,但是把𝑥初始化为 0 就有问题了。 那这个问题如果按照这样初始化的话,你总是会发现𝑏 1[1] 和 𝑏2[1] 相等,这个激活单元和这个激活单元就会一样。因为两个隐含单元计算同样的函数,当你做反向传播计算时,这会导致dz 1[1] 和 dz2[1] 也会一样,对称这些隐含单元会初始化得一样,这样输出的权值也会一模一样,由此𝑋 [2] 等于[0 0];
在这里插入图片描述

图 3.11.1 但是如果你这样初始化这个神经网络,那么这两个隐含单元就会完全一样,因此他们完全对称,也就意味着计算同样的函数,并且肯定的是最终经过每次训练的迭代,这两个隐含单元仍然是同一个函数,令人困惑。𝑒𝑋会是一个这样的矩阵,每一行有同样的值因此我们做权重更新把权重𝑋 [1] ⟹ 𝑋 [1] − 𝑏𝑒𝑋每次迭代后的𝑋 [1] ,第一行等于第二行。
由此可以推导,如果你把权重都初始化为 0,那么由于隐含单元开始计算同一个函数,所有的隐含单元就会对输出单元有同样的影响。一次迭代后同样的表达式结果仍然是相同的,即隐含单元仍是对称的。通过推导,两次、三次、无论多少次迭代,不管你训练网络多长时间,隐含单元仍然计算的是同样的函数。因此这种情况下超过 1 个隐含单元也没什么意义,因为他们计算同样的东西。当然更大的网络,比如你有 3 个特征,还有相当多的隐含单
元。如果你要初始化成 0,由于所有的隐含单元都是对称的,无论你运行梯度下降多久,他们一直计算同样的函数。这没有任何帮助,因为你想要两个不同的隐含单元计算不同的函数,这 个 问 题 的 解 决 方 法 就 是 随 机 初 始 化 参 数 。 你 应 该 这 么 做 : 把 𝑋 [1] 设 为np.random.randn(2,2) (生成高斯分布),通常再乘上一个小的数,比如 0.01,这样把它初始化为很小的随机数。然后𝑐没有这个对称的问题(叫做 symmetry breaking problem),所以可以把 𝑐 初始化为 0,因为只要随机初始化𝑋你就有不同的隐含单元计算不同的东西,因此不会有 symmetry breaking 问题了。相似的,对于𝑋 [2] 你可以随机初始化,𝑐 [2] 可以初始
化为 0。
𝑋 [1] = 𝑜𝑞.𝑠𝑏𝑜𝑒𝑝𝑛.𝑠𝑏𝑜𝑒𝑜(2,2) ∗  0.01 ,
 𝑐 [1] = 𝑜𝑞.𝑨𝑓𝑠𝑝𝑡((2,1))
𝑋 [2] = 𝑜𝑞.𝑠𝑏𝑜𝑒𝑝𝑛.𝑠𝑏𝑜𝑒𝑜(2,2) ∗  0.01 , 𝑐 [2] = 0
你也许会疑惑,这个常数从哪里来,为什么是 0.01,而不是 100 或者 1000。我们通常倾向于初始化为很小的随机数。因为如果你用 tanh 或者 sigmoid 激活函数,或者说只在输出层有一个 Sigmoid,如果(数值)波动太大,当你计算激活值时𝑨 [1] = 𝑋 [1] 𝑦 + 𝑐 [1]  , 𝑏 [1] =𝜎(𝑨 [1] ) = 𝑕 [1] (𝑨 [1] )如果𝑋很大,𝑨就会很大。𝑨的一些值𝑏就会很大或者很小,因此这种情况下你很可能停在 tanh/sigmoid 函数的平坦的地方(见图 3.8.2),这些地方梯度很小也就意味着梯度下降会很慢,因此学习也就很慢。
回顾一下:如果𝑥很大,那么你很可能最终停在(甚至在训练刚刚开始的时候)𝑨很大的
值,这会造成 tanh/Sigmoid 激活函数饱和在龟速的学习上,如果你没有 sigmoid/tanh 激活函数在你整个的神经网络里,就不成问题。但如果你做二分类并且你的输出单元是 Sigmoid函数,那么你不会想让初始参数太大,因此这就是为什么乘上0.01 或者其他一些小数是合理的尝试。对于𝑥 [2] 一样,就是 np.random.randn((1,2)) ,我猜会是乘以 0.01。
事实上有时有比 0.01 更好的常数,当你训练一个只有一层隐藏层的网络时(这是相对浅的神经网络,没有太多的隐藏层),设为 0.01 可能也可以。但当你训练一个非常非常深的神经网络,你可能会选择一个不同于的常数而不是 0.01。下一节课我们会讨论怎么并且何时去选择一个不同于 0.01 的常数,但是无论如何它通常都会是个相对小的数。
好了,你现在已经知道如何建立一个一层的神经网络了,初始化参数,用前向传播预测,还有计算导数,结合反向传播用在梯度下降中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值