深度学习吴恩达课程系列(2)

第三周、浅层神经网络

3.1神经网络概述

深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)
同样,在神经网络中我们也有从后向前的计算,看起来就像这样,最后会计算????????[2] 、????????[2],计算出来之后,然后计算计算????????[2]、????????[2]

3.2神经网络的表示

当我们计算网络的层数时,输入层是不算入总层数内,所以隐藏层是第一层,输出层是第二层。
深度学习吴恩达课程系列(2)
我们要看到的隐藏层以及最后的输出层是带有参数的,这里的隐藏层将拥有两个参数????和????,我将给它们加上上标 [1](????[1],????[1]),表示这些参数是和第一层这个隐藏层有关系的。之后在这个例子中我们会看到????是一个 4x3 的矩阵,而????是一个 4x1 的向量,第一个数字 4 源自于我们有四个结点或隐藏层单元,然后数字 3 源自于这里有三个输入特征。

相似的输出层也有一些与之关联的参数????[2]以及????[2]。从维数上来看,它们的规模分别是 1x4 以及 1x1。1x4 是因为隐藏层有四个隐藏层单元而输出层只有一个单元。

3.3计算一个神经网络的输出

逻辑回归的计算有两个步骤,首先你按步骤计算出????,然后在第二步中你以 sigmoid 函数为**函数计算????(得出????),一个神经网络只是这样子做了好多次重复计算。
深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)

隐藏层的第二个以及后面两个神经元的计算过程一样,只是注意符号表示不同,最终分别得到????2[1]、????3[1]、????4[1],详细结果见下:
深度学习吴恩达课程系列(2)
向量????,把这四个向量堆积在一起,你会得出这 4×3 的矩阵。因此,公式 3.8: ????[????] = ????[????]???? + ????[????]
深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)

3.4多样本向量化

????【2](i),(????)是指第????个训练样本而[2]是指第二层。
深度学习吴恩达课程系列(2)

3.5向量化实现的解释

深度学习吴恩达课程系列(2)
这里,为了描述的简便,我们先忽略掉 ????[1]后面你将会看到利用 Python 的广播机制,可以很容易的将????[1] 加进来。

以上就是对神经网络向量化实现的正确性的解释,到目前为止,我们仅使用 sigmoid 函数作为**函数,事实上这并非最好的选择。

3.6**函数

深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)
????(????[1]) = ????????????ℎ(????[1]) 效果总是优于 sigmoid 函数。因为函数值域在-1 和+1的**函数,其均值是更接近零均值的。在训练一个算法模型时,如果使用 tanh 函数代替sigmoid 函数中心化数据,使得数据的平均值更接近 0 而不是 0.5.

在讨论优化算法时,有一点要说明:我基本已经不用 sigmoid **函数了,tanh 函数在所有场合都优于 sigmoid 函数。
但有一个例外:在二分类的问题中,对于输出层,因为????的值是 0 或 1,所以想让????^的数值介于 0 和 1 之间,而不是在-1 和+1 之间。所以需要使用 sigmoid **函数。

在这个例子里看到的是,对隐藏层使用 tanh **函数,输出层使用 sigmoid 函数。

sigmoid 函数和 tanh 函数两者共同的缺点是,在????特别大或者特别小的情况下,导数的梯度或者函数的斜率会变得特别小,最后就会接近于 0,导致降低梯度下降的速度。

这有一些选择**函数的经验法则:

如果输出是 0、1 值(二分类问题),则输出层选择 sigmoid 函数,然后其它的所有单元都选择 Relu 函数。

这是很多**函数的默认选择,如果在隐藏层上不确定使用哪个**函数,那么通常会使用 Relu **函数。有时,也会使用 tanh **函数,但 Relu 的一个优点是:当????是负值的时候,导数等于 0。

这里也有另一个版本的 Relu 被称为 Leaky Relu。

当????是负值时,这个函数的值不是等于 0,而是轻微的倾斜,如图
深度学习吴恩达课程系列(2)
而 Relu 和 Leaky ReLu 函数大于 0 部分都为常数,不会产生梯度弥散现象。(同时应该注意到的是,Relu 进入负半区的时候,梯度为 0,神经元此时不会训练,产生所谓的稀疏性

???? = ????????????(0.01????, ????)
为什么常数是 0.01?当然,可以为学习算法选择不同的参数。

3.7为什么需要非线性**函数

如果你是用线性**函数或者叫恒等激励函数,那么神经网络只是把输入线性组合再输出。

事实证明如果你在隐藏层用线性**函数,在输出层用 sigmoid 函数,那么这个模型的复杂度和没有任何隐藏层的标准 Logistic 回归是一样的

所以除非你引入非线性,否则你无法计算更有趣的函数,即使你的网络层数再多也不行;

总而言之,不能在隐藏层用线性**函数,可以用 ReLU 或者 tanh 或者 leaky ReLU 或者其他的非线性**函数,唯一可以用线性**函数的通常就是输出层;除了这种情况,会在隐层用线性函数的,除了一些特殊情况,比如与压缩有关的,那方面在这里将不深入讨论。
在这之外,在隐层使用线性**函数非常少见。因为房价都是非负数,所以我们也可以在输出层使用 ReLU 函数这样你的????^都大于等于 0

3.8**函数的导数

深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)

3.9神经网络的梯度下降

深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)
axis=1 表示水平相加求和,keepdims 是防止python 输出那些古怪的秩数(????, ),加上这个确保阵矩阵????????[2]这个向量输出的维度为(????, 1)这样标准的形式

3.10直观理解反向传播

深度学习吴恩达课程系列(2)
初始化你的神经网络的权重,不要都是 0,而是随机初始化,下一章将详细介绍原因。

3.11随机初始化

深度学习吴恩达课程系列(2)

如果你要初始化成 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。

回顾一下:如果????很大,那么你很可能最终停在(甚至在训练刚刚开始的时候)????很大的值,这会造成tanh/Sigmoid **函数饱和在龟速的学习上。

但当你训练一个非常非常深的神经网络,你可能会选择一个不同于的常数而不是 0.01。下一节课我们会讨论怎么并且何时去选择一个不同于 0.01 的常数,但是无论如何它通常都会是个相对小的数。

第四周、深层神经网络

4.1深层神经网络

我们用 L 表示层数,在不同层所拥有的神经元的数目,对于每层 l 都用????[????]来记作 l 层**后结果。

通过用**函数 ???? 计算????[????],**函数也被索引为层数????,然后我们用????[????]来记作在 l 层计算????[????]值的权重。类似的,????[????]里的方程????[????]也一样。

输入的特征记作????,但是????同样也是 0 层的**函数,所以???? = ????[0]

最后一层的**函数,所以????[L]是等于这个神经网络所预测的输出结果。

4.2前向传播和后向传播

深度学习吴恩达课程系列(2)
前向传播需要喂入????[0]也就是????,来初始化;
深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)

4.3深层网络中的前向传播

深度学习吴恩达课程系列(2)
深度学习吴恩达课程系列(2)

4.4核对矩阵的维数

当实现深度神经网络的时候,其中一个我常用的检查代码是否有错的方法就是拿出一张纸过一遍算法中矩阵的维数。
深度学习吴恩达课程系列(2)

4.5为什么使用深层表示

所以深度神经网络的这许多隐藏层中,较早的前几层能学习一些低层次的简单特征,等到后几层,就能把简单的特征结合起来,去探测更加复杂的东西。

有些人喜欢把深度神经网络和人类大脑做类比,这些神经科学家觉得人的大脑也是先探测简单的东西,比如你眼睛看得到的边缘,然后组合起来才能探测复杂的物体,比如脸。

但是当我开始解决一个新问题时,我通常会从 logistic 回归开始,再试试一到两个隐层,把隐藏层数量当作参数、超参数一样去调试,这样去找比较合适的深度。但是近几年以来,有一些人会趋向于使用非常非常深邃的神经网络,比如好几打的层数,某些问题中只有这种网络才是最佳模型。

4.6搭建神经网络模块

总结起来就是,在 l 层,你会有正向函数,输入????[????−1]并且输出????[????],为了计算结果你需要用????[????]和????[????],以及输出到缓存的????[????]。然后用作反向传播的反向函数,是另一个函数,输入????????[????],输出????????[????−1],你就会得到对**函数的导数,也就是希望的导数值????????[????]。????[????−1]是会变的,前一层算出的**函数导数。
深度学习吴恩达课程系列(2)
把输入特征????[0],放入第一层并计算第一层的**函数,用????[1]表示,你需要????[1]和????[1]来计算,之后也缓存????[????]值。之后喂到第二层,第二层里,需要用到????[2]和????[2],你会需要计算第二层的**函数????[2]。后面几层以此类推,直到最后你算出了????[????],第????层的最终输出值
????^。在这些过程里我们缓存了所有的????值,这就是正向传播的步骤。

要把????????[????]的值放在这里,然后这个方块会给我们????????[????−1]的值,以此类推,直到我们得到????????[2] 和????????[1],你还可以计算多一个输出值,就是????????[0]

反向传播步骤中也会输出????????[????]和????????[????],这会输出????????[3]和????????[3]

现在你就有所有的导数项了,????也会在每一层被更新为???? = ???? − ????????????,????也一样,???? = ???? − ????????????,反向传播就都计算完毕,我们有所有的导数值,那么这是神经网络一个梯度下降循环。
继续下去之前再补充一个细节,概念上会非常有帮助,那就是把反向函数计算出来的????

我认为是一个很方便的方法,可以将参数复制到你在计算反向传播时所需要的地方。

4.7参数VS超参数

什么是超参数?
比如算法中的 learning rate ????(学习率)、iterations(梯度下降法循环的数量)、????(隐藏层数目)、????[????](隐藏层单元数目)、choice of activation function(**函数的选择)都需要你来设置,这些数字实际上控制了最后的参数????和????的值,所以它们被称作超参数。

如何寻找超参数的最优值?
深度学习吴恩达课程系列(2)
走 Idea—Code—Experiment—Idea 这个循环,尝试各种不同的参数,实现模型并观察是否成功,然后再迭代。

如果你不确定什么值是最好的,你大可以先试试一个学习率????,再看看损失函数 J的值有没有下降。然后你可以试一试大一些的值,然后发现损失函数的值增加并发散了。然后可能试试其他数,看结果是否下降的很快或者收敛到在更高的位置。你可能尝试不同的????并观察损失函数????这么变了,试试一组值,然后可能损失函数变成这样,这个????值会加快学习过程,并且收敛在更低的损失函数值上(箭头标识),我就用这个????值了。

如果你所解决的问题需要很多年时间,只要经常试试不同的超参数,勤于检验结果,看看有没有更好的超参数数值,相信你慢慢会得到设定超参数的直觉,知道你的问题
最好用什么数值