深层神经网络
深层神经网络
目前只学习了只有一个隐藏层的神经网络的正向和反向传播。还有逻辑回归,向量化,以及如何初始化权重。
这部分把上述内容集合起来,构建深层神经网络。
上图是一个有3个隐藏层的4层神经网络。
先给出神经网络的符号定义:
使用L
表示层数,例如上图L=4
。
使用n[i]表示第i层的神经元个数,例如n[1]=n[2]=5,n[3]=3。
特殊地,n[0]=nx=3。
对于每层,使用a[i]表示第i层激活后的结果。
对于每层,使用W[i]表示第i层的权重矩阵。b[i]类似。
最后,输入的特征记做x,但x同样也是0层的激活函数,所以x=a[0]。
最后一层的激活函数输出,a[L]是这个神经网络的预测输出结果。
深层网络中的前向传播
首先讨论一个训练样本x的前向传播,然后再讨论多个训练样本。
以上面给出的神经网络为例。
第一层:z[1]=w[1]a[0]+b[1]a[1]=g[1](z[1])
第二层:z[2]=w[2]a[1]+b[2]a[2]=g[2](z[2])
以此类推,第四层为:
第四层:z[4]=w[4]a[3]+b[4]a[4]=g[4](z[4])
因此,前向传播可以归纳为多次迭代:
z[l]=w[l]a[l−1]+b[l]a[l]=g[l]∗z[l]
那么多个训练样本,使用向量化技术写为:
Z[l]=W[l]A[l−1]+b[l]A[l]=g[l](Z[l])(A[0]=X)
核对矩阵维数
当实现深度神经网络时,需要仔细检查算法中各个矩阵的维数。
有m
个训练样本,深度神经网络层数为L
。
对于参数:
- W的维度是:W[l]:(n[l],n[l−1]),即
(这层维数,前一层维数)
。 - b的维度是:b[l]:(n[l],1),即
(这层维数,1)
在反向传播时,
dW[l]和W[l]维度相同,db[l]和b[l]维度相同。
- Z的维度是:Z[l]:(n[l],m)。即
(这层维数,样本数量)
。 - A的维度是:A[l]:(n[l],m)。
(这层维数,样本数量)
。 - X的维度是:X=A[0]:(n[0],m)。
即Z和A的维度是相同的。因为A=g(Z)。(g为激活函数)
在反向传播时,
dZ[l]和Z[l]维度相同,dA[l]和A[l]维度相同。
对于上图神经网络,以第一层为例。
W[1]维度为(3,2)
,b[1]维度为(3,1)
,X维度为(2,m)
。
Z[1]维度为(3, m)
。
W[1]X的维度是(3,m)
,而b[1]维度是(3,1)
。但可以相加是因为Python的广播机制,会自动复制列向量b[1]m次,变成维度是(3, m)
的矩阵再相加。
总结,在做深度神经网络的正向和反向传播时,一定要确认所有的矩阵维数是相一致的。
为什么要使用深层神经网络
简单来说,在深度神经网络的隐藏层中,较早的前几层可以学一些些低层次的简单特征,等到后几层,就能将简单的特征结合起来,去探测更加复杂的东西。
例如在图像处理中,可能在计算的前几层,是相对简单的输入函数,例如图像单元的边缘等,等到了网络中的深层,就可以做很多复杂的事情,例如探测人脸等。
总结来说就是,有多个隐藏层的神经网络可以解决更为复杂的问题,做一些更复杂的问题。
但是,当开始解决一个新问题时,并不一定非常去用很多隐层,可以先从逻辑回归开始,尝试一两个隐藏层,把隐藏层当成参数、超参数一样去调试,来找到一个比较合适的深度。
搭建神经网络块
如上图,是训练神经网络的正向和反向传播过程。
每一层都可以看做一个小方块,第i层的输入是a[l−1],通过参数w,b,计算输出a[l]。输出层的输出a[L]是最终输出。
同时将每一层计算出的z保存下来,反向传播时使用。
从第一层的输入到输出层的输出,是一个完整的正向传播,中间涉及到的函数是正向函数。
根据输出层的输出计算da[L],然后开始反向传播的过程,首先根据da[L]和参数w[L],b[L]计算dW[L],db[L],并更新参数,并将计算结果作为左边一层的输入,以此计算。最后到第一层(第一层不需要再输出,因为d[0]是输入特征的偏导,没有意义,不需要更新)。
然后更新所有参数,即完成了一次反向传播。
总上,这就是一次完整的正向和反向传播过程。
正向和反向传播
接下来讨论上面图中的具体函数和公式。
正向传播有:
z[l]=W[l]⋅A[l−1]+b[l]A[l]=g[l](z[l])
反向传播有:
dZ[l]=dA[l]∗g[l]′(Z[l])dW[l]=m1dZ[l]⋅A[l−1]Tdb[l]=m1np.sum(dz[l],axis=1)dA[l−1]=W[l]TdZ[l]
需要注意:
在正向传播时,使用输入数据作为a[0]开始。
但是在反向传播时,需要对A[L](也就是反向传播的初始值)求导,这与代价函数有关系。
如果是二分类问题,代价函数是:
L(a,y)=−ylog(a)−(1−y)log(1−a)J(a,y)=m1i=1∑mL(a,y)
那么就有:
dA[L]=[−ay(1)+1−a1−y(1),−ay(2)+1−a1−y(2),⋯,−ay(m)+1−a1−y(m)]
然后其他的dA[l]就可以以此类推通过这个初始值dA[L]计算出来。
这里再解释一下反向传播的第一个公式:
dZ[l]=dA[l]∗g[l]′(Z[l])
首先知道A[l]=g[l](Z[l]),而代价函数J(a,y)是关于自变量a,y的函数,y是训练样本的标记,不考虑。那么代价函数对Z求导,根据链式法则有:
dZ[l]=dZ[l]dJ=dA[l]dJdZ[l]dA[l]=dA[l]dJ∗g[l]′(Z[l])=dA[l]∗g[l]′(Z[l])
*
是点乘。
参数和超参数
想要深度神经网络起到很好的作用,还需要规划好参数和超参数。
什么是参数:
W[1],b[1],W[2],b[2],W[3],b[3],⋯
即神经网络的每一层权重和偏置都是参数。
那么什么是超参数(hyper parameter)
learning rate
:学习率αiterations
:梯度下降法的迭代次数L
:隐藏层的数目,或者称为神经网络深度- n[l]:神经网络每一层的神经元个数
- 激活函数的选择
这些数字实际上控制了最后的参数W,b的值。即“控制参数的参数”,也就被称为超参数。
除此之外,深度学习也有很多其他的参数,在后面会学习到。
在深度学习领域,有一条经验规律就是:
经常试试不同的超参数,并且检查结果,看看有没有更好的超参数取值。