吴恩达深度学习笔记01——神经网络和深度学习2浅层神经网络
一、神经网络表示
竖向堆叠起来的输入特征被称作神经网络的输入层(the input layer)。
神经网络的隐藏层(a hidden layer)。“隐藏”的含义是在训练集中,这些中间节点的真正数值是无法看到的。
输出层(the output layer)负责输出预测值。
如图是一个双层神经网络,也称作单隐层神经网络(a single hidden layer neural network)。当我们计算网络的层数时,通常不考虑输入层,因此图中隐藏层是第一层,输出层是第二层。
约定俗成的符号表示是:
- 输入层的**值为 a[0];
- 同样,隐藏层也会产生一些**值,记作 a[1] 隐藏层的第一个单元(或者说节点)就记作 a[1]1输出层同理。
- 另外,隐藏层和输出层都是带有参数 W 和 b 的。它们都使用上标[1]来表示是和第一个隐藏层有关,或者上标[2]来表示是和输出层有关。
二、计算神经网络的输出
实际上,神经网络只不过将 Logistic 回归的计算步骤重复很多次。对于隐藏层的第一个节点,有
我们可以类推得到,对于第一个隐藏层有下列公式:
其中,a[0]可以是一个列向量,也可以将多个列向量堆叠起来得到矩阵。如果是后者的话,得到的 z[1]和 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),和输出层的神经元个数相同。
向量化实现
三、**函数
有一个问题是神经网络的隐藏层和输出单元用什么**函数。之前我们都是选用 sigmoid 函数,但有时其他函数的效果会好得多。
可供选用的**函数有:
-
tanh 函数(the hyperbolic tangent function,双曲正切函数):
效果几乎总比 sigmoid 函数好(除开二元分类的输出层,因为我们希望输出的结果介于 0 到 1 之间),因为函数输出介于 -1 和 1 之间,**函数的平均值就更接近 0,有类似数据中心化的效果。然而,tanh 函数存在和 sigmoid 函数一样的缺点:当 z 趋紧无穷大(或无穷小),导数的梯度(即函数的斜率)就趋紧于 0,这使得梯度算法的速度大大减缓。 -
ReLU 函数(the rectified linear unit,修正线性单元):
当 z > 0 时,梯度始终为 1,从而提高神经网络基于梯度算法的运算速度,收敛速度远大于 sigmoid 和 tanh。然而当 z < 0 时,梯度一直为 0,但是实际的运用中,该缺陷的影响不是很大。 -
Leaky ReLU(带泄漏的 ReLU):
Leaky ReLU 保证在 z < 0 的时候,梯度仍然不为 0。理论上来说,Leaky ReLU 有 ReLU 的所有优点,但在实际操作中没有证明总是好于 ReLU,因此不常用。
在选择**函数的时候,如果在不知道该选什么的时候就选择 ReLU,当然也没有固定答案,要依据实际问题在交叉验证集合中进行验证分析。当然,我们可以在不同层选用不同的**函数。
使用非线性**函数的原因
使用线性**函数和不使用**函数、直接使用 Logistic 回归没有区别,那么无论神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,就成了最原始的感知器了。
**函数的导数
-
sigmoid 函数:
-
tanh 函数:
四、神经网络的梯度下降法
首先注意各个参数的维度:
1、正向传播
2、反向传播
神经网络反向梯度下降公式(左)和其代码向量化(右):
keepdims=True确保输出的是矩阵
五、随机初始化
如果在初始时将两个隐藏神经元的参数设置为相同的大小,那么两个隐藏神经元对输出单元的影响也是相同的,通过反向梯度下降去进行计算的时候,会得到同样的梯度大小,所以在经过多次迭代后,两个隐藏层单位仍然是对称的。无论设置多少个隐藏单元,其最终的影响都是相同的,那么多个隐藏神经元就没有了意义。
在初始化的时候,W 参数要进行随机初始化,不可以设置为 0。而 b 因为不存在对称性的问题,可以设置为 0。
以 2 个输入,2 个隐藏神经元为例:
这里将 W 的值乘以 0.01(或者其他的常数值)的原因是为了使得权重 W 初始化为较小的值,这是因为使用 sigmoid 函数或者 tanh 函数作为**函数时,W 比较小,则 Z=WX+b 所得的值趋近于 0,梯度较大,能够提高算法的更新速度。而如果 W 设置的太大的话,得到的梯度较小,训练过程因此会变得很慢。
ReLU 和 Leaky ReLU 作为**函数时不存在这种问题,因为在大于 0 的时候,梯度均为 1。