在掌握了逻辑回归算法后,先来学习浅层神经网络,之后再对深度神经网络进行学习。
1. 原理推导
1.1 神经网络表示
神经网络由输入层、隐含层和输出层构成。L层神经网络,隐含层为第1 ~ (L - 1)层,输出层为第L层。为了方便,将输入层写成第0层。
定义:上标[l]表示第l层,下标j表示第j个节点。
例如,下图为2层神经网络,包含1个隐藏层:
输入层和隐含层可以写成:
1.2 正向传播(Forward Propagation)
计算过程与逻辑回归类似,只是多了隐含层,如下:
式中,g(z)为激活函数。可将上式向量化为:
即:
式中,
因此,对于该2层神经网络的每个样本,给定a[0] = x,正向传播计算流程如下:
各矩阵维度如下表:
|
|
|
|
|
|
|
|
|
|
---|---|---|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
以上推导仅仅针对单个样本,对于m个样本,以上标(m)表示第m个样本。则可以将公式改写为:
即:
式中,
因此,对于以上2层神经网络,针对m个样本,给定A[0] = X,正向传播计算流程如下:
各矩阵维度如下表:
|
|
|
|
|
|
|
|
|
|
---|---|---|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
从式中可以看出,矩阵Z和A在计算过程中,水平索引遍历所有样本集,垂直索引遍历神经网络每一层的各个节点。
1.3 激活函数(Activation Function)
常见的4种激活函数如下:
sigmoid函数:在0 ~ 1之间,很少用到,仅仅用于二分类问题。
tanh函数,在-1 ~ 1之间,均值为0,使得数据更集中。
sigmoid和tanh函数的一个共同缺点:当z很大或者很小时,函数的斜率都很小且接近0,从而使得梯度下降法的速度较慢。
ReLU(Rectified Linear Units)函数:通常比sigmoid和tanh函数效果好,是最常用的激活函数。缺点在于,当很大的梯度经过一个ReLU神经元,更新过参数后,这个神经元再也不会对任何数据有激活现象。对于较大的学习因子,经常会发生这个问题。因此,需要设置合适的、较小的学习因子。
Leaky ReLU函数:相比ReLU函数,设置了一个很小的常数α,保留了一些负轴的值,使得负轴信息不会全部丢失。
1.4 为什么激活函数使用非线性函数?
假如使用线性函数g(z) = z:
则正向传播化简为:
可以看出,a[2]与z[1]等效,如果使用线性激活函数,就无法发挥隐含层的作用。在深度神经网络中,使用线性激活函数,多个隐含层与没有隐含层的效果相同。
因此,必须使用非线性激活函数。
1.5 梯度下降(Gradient Descent)
以n[l]表示第l层的节点数,对于以上的2层神经网络:
代价函数:
梯度下降法流程如下:
式中,α为学习因子。为了更新参数W和b,关键在于求解导数dW和db,可以通过反向传播来求解。
1.6 反向传播(Backward Propagation)
在正向传播中,已经计算得到了Z[1]、A[1]、Z[2]、A[2]。此处使用sigmoid函数来推导。对于2层神经网络,针对单个样本,正向传播为:
与逻辑回归类似,反向传播计算如下:
拓展到m个样本得到:
式中,“*”表示元素点乘。通过上式求出梯度dW和db,并代入梯度下降法中,即可对参数W和b进行更新。
1.7 随机初始化
对于如下的2层神经网络。
如果将参数全部初始化为0:
那么,无论采用什么样本来训练,都会得到:
在更新参数的过程中,W始终保持如下的对称形式:
这样,
所以,在初始化神经网络参数时,应当避免以上情况,将参数W随机初始化,为了方便,可以将b全部初始化为0。
另外,根据sigmoid或者tanh函数的特点,当输入较大时,函数的导数较大,会导致学习速度较慢。因此,通常将参数随机初始化为较小的参数:
2. 代码实现
案例:采用2层神经网络实现色点的二分类。
计算流程如下:
2.1 初始化initialize
对参数W进行随机初始化,将参数b初始化为0。核心代码如下:
2.2 正向传播forward
按照下式计算各个节点的Z和A:
核心代码如下:
2.3 计算代价函数compute_cost
采用下式计算代价函数:
核心代码如下:
2.4 反向传播backward
按照下式计算参数的梯度dW和db:
核心代码如下:
2.5 参数更新update_parameters
按照下式对参数W和b进行更新:
核心代码如下:
2.6 模型构建nn_model
将以上几个模块进行整合,输入训练样本,得到最优参数W和b。关键代码如下:
2.7 预测predict
根据优化得到的参数W和b,输入样本x,得到预测值,如果预测概率大于0.5,则预测值为1,否则为0。关键代码如下:
2.8 样本测试
代码如下:
可得到如下输出,分类准确率为90.50%。
此外,对隐含层节点数量的影响作了分析,核心代码如下:
得到如下结果。可以看出,较多的隐含层节点无法提升分类准确率,甚至存在过拟合现象,5个隐含层节点是比较理想的结果。
代码下载地址:https://gitee.com/tuzhen301/Coursera-deeplearning.ai1-3