您的位置:首页 > 理论基础 > 计算机网络

Coursera deeplearning.ai 深度学习笔记1-3-Shallow Neural Networks-浅层神经网络原理推导与代码实现

2017-12-11 20:17 971 查看
在掌握了逻辑回归算法后,先来学习浅层神经网络,之后再对深度神经网络进行学习。

1. 原理推导

1.1 神经网络表示

神经网络由输入层、隐含层和输出层构成。L层神经网络,隐含层为第1 ~ (L - 1)层,输出层为第L层。为了方便,将输入层写成第0层。

定义:上标[l]表示第l层,下标j表示第j个节点。

例如,下图为2层神经网络,包含1个隐藏层:



输入层和隐含层可以写成:

a[0]=x=⎡⎣⎢x1x2x3⎤⎦⎥,a[1]=⎡⎣⎢⎢⎢⎢⎢⎢a[1]1a[1]2a[1]3a[1]4⎤⎦⎥⎥⎥⎥⎥⎥(1)

1.2 正向传播(Forward Propagation)

计算过程与逻辑回归类似,只是多了隐含层,如下:

z[1]1=w[1]T1x+b[1]1,a[1]1=g(z[1]1)z[1]2=w[1]T2x+b[1]2,a[1]2=g(z[1]2)z[1]3=w[1]T3x+b[1]3,a[1]3=g(z[1]3)z[1]4=w[1]T4x+b[1]4,a[1]4=g(z[1]4)(2)

式中,g(z)为激活函数。可将上式向量化为:

⎡⎣⎢⎢⎢⎢⎢⎢z[1]1z[1]2z[1]3z[1]4⎤⎦⎥⎥⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢⎢⎢−−−−w[1]T1w[1]T2w[1]T3w[1]T4−−−−⎤⎦⎥⎥⎥⎥⎥⎥⎡⎣⎢x1x2x3⎤⎦⎥+⎡⎣⎢⎢⎢⎢⎢⎢b[1]1b[1]2b[1]3b[1]4⎤⎦⎥⎥⎥⎥⎥⎥,⎡⎣⎢⎢⎢⎢⎢⎢a[1]1a[1]2a[1]3a[1]4⎤⎦⎥⎥⎥⎥⎥⎥=g⎛⎝⎜⎜⎜⎜⎜⎜⎡⎣⎢⎢⎢⎢⎢⎢z[1]1z[1]2z[1]3z[1]4⎤⎦⎥⎥⎥⎥⎥⎥⎞⎠⎟⎟⎟⎟⎟⎟(3)

即:

z[1]=W[1]x+b[1],a[1]=g(z[1])(4)

式中,

z[1]=⎡⎣⎢⎢⎢⎢⎢⎢z[1]1z[1]2z[1]3z[1]4⎤⎦⎥⎥⎥⎥⎥⎥,W[1]=⎡⎣⎢⎢⎢⎢⎢⎢−−−−w[1]T1w[1]T2w[1]T3w[1]T4−−−−⎤⎦⎥⎥⎥⎥⎥⎥,b[1]=⎡⎣⎢⎢⎢⎢⎢⎢b[1]1b[1]2b[1]3b[1]4⎤⎦⎥⎥⎥⎥⎥⎥,a[1]=⎡⎣⎢⎢⎢⎢⎢⎢a[1]1a[1]2a[1]3a[1]4⎤⎦⎥⎥⎥⎥⎥⎥(5)

因此,对于该2层神经网络的每个样本,给定a[0] = x,正向传播计算流程如下:

z[1]=W[1]a[0]+b[1]a[1]=g(z[1])z[2]=W[2]a[1]+b[2]a[2]=g(z[2])(6)

各矩阵维度如下表:

矩阵a[0]W[1]b[1]z[1]a[1]W[2]b[2]z[2]a[2]
维度(3, 1)(4, 3)(4, 1)(4, 1)(4, 1)(1, 4)(1, 1)(1, 1)(1, 1)
以上推导仅仅针对单个样本,对于m个样本,以上标(m)表示第m个样本。则可以将公式改写为:

⎡⎣⎢|z[1](1)||z[1](2)||⋯||z[1](m)|⎤⎦⎥=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢−−−−w[1]1Tw[1]2Tw[1]3Tw[1]4T−−−−⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎡⎣⎢|x(1)||x(2)||⋯||x(m)|⎤⎦⎥+b[1](7)

⎡⎣⎢|a[1](1)||a[1](2)||⋯||a[1](m)|⎤⎦⎥=g⎛⎝⎜⎡⎣⎢|z[1](1)||z[1](2)||⋯||z[1](m)|⎤⎦⎥⎞⎠⎟(8)

即:

Z[1]=W[1]X+b[1],A[1]=g(Z[1])(9)

式中,

Z[1]=⎡⎣⎢|z[1](1)||z[1](2)||⋯||z[1](m)|⎤⎦⎥,A[1]=⎡⎣⎢|a[1](1)||a[1](2)||⋯||a[1](m)|⎤⎦⎥(10)

因此,对于以上2层神经网络,针对m个样本,给定A[0] = X,正向传播计算流程如下:

Z[1]=W[1]A[0]+b[1]A[1]=g(Z[1])Z[2]=W[2]A[1]+b[2]A[2]=g(Z[2])(11)

各矩阵维度如下表:

矩阵A[0]W[1]b[1]Z[1]A[1]W[2]b[2]Z[2]A[2]
维度(3, m)(4, 3)(4, 1)(4, m)(4, m)(1, 4)(1, 1)(1, m)(1, m)
从式中可以看出,矩阵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:

则正向传播化简为:

z[1]=W[1]a[0]+b[1]a[1]=g(z[1])=z[1]z[2]=W[2]a[1]+b[2]=W[2]z[1]+b[2]a[2]=g(z[2])=z[2]=W[2](W[1]a[0]+b[1])+b[2]=(W[2]W[1])a[0]+(W[2]b[1]+b[2])=W′a[0]+b′(12)

可以看出,a[2]与z[1]等效,如果使用线性激活函数,就无法发挥隐含层的作用。在深度神经网络中,使用线性激活函数,多个隐含层与没有隐含层的效果相同。

因此,必须使用非线性激活函数。

1.5 梯度下降(Gradient Descent)

以n[l]表示第l层的节点数,对于以上的2层神经网络:

n[0]=nx=3,n[1]=4,n[2]=1(13)

代价函数:

J(w,b)=1m∑i=1mL(a(i),y(i))=−1m∑i=1m[y(i)loga(i)+(1−y(i))log(1−a(i))](14)

梯度下降法流程如下:

Computeactivationa(i),i=1,⋯,mComputecostfunctionJdW[1]=dJdW[1],db[1]=dJdb[1],⋯W[1]=W[1]−αdW[1],b[1]=b[1]−αdb[1],⋯(15)

式中,α为学习因子。为了更新参数W和b,关键在于求解导数dW和db,可以通过反向传播来求解。

1.6 反向传播(Backward Propagation)

在正向传播中,已经计算得到了Z[1]、A[1]、Z[2]、A[2]。此处使用sigmoid函数来推导。对于2层神经网络,针对单个样本,正向传播为:

z[1]=W[1]a[0]+b[1]a[1]=g(z[1])z[2]=W[2]a[1]+b[2]a[2]=g(z[2])(16)

与逻辑回归类似,反向传播计算如下:

dz[2]=a[2]−ydW[2]=dz[2]a[1]Tdb[2]=dz[2]dz[1]=dJdz[2]⋅dz[2]da[1]⋅da[1]dz[1]=W[2]Tdz[2]∗g[1]′(z[1])dW[1]=dz[1]a[0]Tdb[1]=dz[1](17)

拓展到m个样本得到:

dZ[2]=A[2]−YdW[2]=1mdZ[2]A[1]Tdb[2]=1mnp.sum(dZ[2],axis=1,keepdims=True)dz[1]=W[2]TdZ[2]∗g[1]′(Z[1])dW[1]=1mdZ[1]A[0]Tdb[1]=1mnp.sum(dZ[1],axis=1,keepdims=True)(18)

式中,“*”表示元素点乘。通过上式求出梯度dW和db,并代入梯度下降法中,即可对参数W和b进行更新。

1.7 随机初始化

对于如下的2层神经网络。



如果将参数全部初始化为0:

W[1]=[0000],b[1]=[00](19)

那么,无论采用什么样本来训练,都会得到:

a[1]1=a[1]2,dz[1]1=dz[1]2(20)

在更新参数的过程中,W始终保持如下的对称形式:

W=[uuvv](21)

这样,a[1]1和a[1]2具体相同的功能,实际上只需要一个就够了。

所以,在初始化神经网络参数时,应当避免以上情况,将参数W随机初始化,为了方便,可以将b全部初始化为0。

另外,根据sigmoid或者tanh函数的特点,当输入较大时,函数的导数较大,会导致学习速度较慢。因此,通常将参数随机初始化为较小的参数:

W=np.random.randn(l,l−1)∗0.01b=np.zeros((l,1))(22)

2. 代码实现

案例:采用2层神经网络实现色点的二分类。



计算流程如下:



2.1 初始化initialize

对参数W进行随机初始化,将参数b初始化为0。核心代码如下:



2.2 正向传播forward

按照下式计算各个节点的Z和A:

Z[1]=W[1]A[0]+b[1]A[1]=g(Z[1])Z[2]=W[2]A[1]+b[2]A[2]=g(Z[2])(23)

核心代码如下:



2.3 计算代价函数compute_cost

采用下式计算代价函数:

J(w,b)=1m∑i=1mL(a(i),y(i))=−1m∑i=1m[y(i)loga(i)+(1−y(i))log(1−a(i))](24)

核心代码如下:



2.4 反向传播backward

按照下式计算参数的梯度dW和db:

dZ[2]=A[2]−YdW[2]=1mdZ[2]A[1]Tdb[2]=1mnp.sum(dZ[2],axis=1,keepdims=True)dz[1]=W[2]TdZ[2]∗g[1]′(Z[1])dW[1]=1mdZ[1]A[0]Tdb[1]=1mnp.sum(dZ[1],axis=1,keepdims=True)(25)

核心代码如下:



2.5 参数更新update_parameters

按照下式对参数W和b进行更新:

W[1]=W[1]−αdW[1],b[1]=b[1]−αdb[1]W[2]=W[2]−αdW[2],b[2]=b[2]−αdb[2](26)

核心代码如下:



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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐