适合小白的深度神经网络DNN思想及详细推导

导读:网上关于深度神经网络的博文和技术博客数不胜数,但是能够让初学者直接看懂的却是不多,倒不是说别人写的不好而是因为这些大佬大多是站在一定的高度来介绍的,不懂我们这些小白的痛苦啊,以下的内容是我在看了吴恩达老师的教程加以总结之后的文章,想要学习深度学习需要有一点数学功底,当然这不是最重要的,如果你在学习的过程中发现有些知识不懂可以现场查询一下,无需针对DNN特意去报班学习数学,我觉得这是没必要的,真正的学习应该是以目标为导向的扩展式学习,能够帮你快速建立必要的知识储备,我会用尽量简明的言语来介绍,希望能够帮助初学者快速理解和掌握深度神经网络。

博客内容主要参考如下,有兴趣的同学可以看一下:

1.深度神经网络BP算法

2.DNN深度神经网络入门

3.DNN反向传播过程推导

4.矩阵、向量的求导公式

一、DNN是什么?

一句话来简单介绍DNN就是:拥有输入层、输出层和一个隐含层。输入的特征向量通过隐含层变换达到输出层,在输出层得到分类结果的计算模型。如果你想了解更多关于DNN的信息,可以去网上查一下关于DNN的博客,这些内容可以帮你快速建立对深度神经网络的知识,而不需要花费大量时间去看论文。当然这不是我们文章的主要目的,我要介绍的主要是DNN的网络结构,前向算法和反向传播(Back Propagation 即BP)算法思想和详细的推导过程。

二、标准的DNN网络结构

这里我将以逻辑回归算法(LR)的思想为例将其用在DNN中,将上图中的某一个隐藏层的神经元放大,看看这里的一个隐层到底做了什么?

输入层的输入样本的每一个特征与隐藏层的特征方程线性拟合得到一个z值,通过一个激活函数\sigma (z)z值映射到(0,1)之间的激活值a,这就是逻辑回归的基本迭代公式。接下来我将用矩阵的方式推到所有公式,因为通常用矩阵来计算的话,并发性能会大大提升。

三、DNN的前向算法思想

在此之前,我需要介绍一下接下来推到需要用到的符号,上角标 l 表示神经网络的层数。

X^{(0)}\left ( X_{1},X_{1},...,X_{N} \right ) 一个列向量,表示每一个输入的样本特征,通常我们也用A^{0}来表示,也叫初始值

W^{(l)}:weights是一个特征的权重矩阵,也是我们训练的模型重点

b^{(l)}:bias是每个样本训练得到的偏差,在此不再介绍偏差和权重的知识

Z^{(l)}=W^{lT}X^{(l-1)}+b^{(l)} \left (or Z^{(l)}=W^{lT}A^{(l-1)}+b^{(l)} \right ):这里的Z^{(l)}表示一个回归方程得到的回归值

A^{(l)}=\sigma \left ( Z^{(l)} \right ):这里的A^{(l)}表示激活值,通过一个Sigmoid激活函数映射得到的值,其中A^{(l)}也是最终的预测结果

前向迭代的算法思想是,通过前面一层得到的激活值,来计算下一层的Z值,再通过Z值来计算激活值A。在这里可能有人会想计算这些值的作用是什么,如果有同学不明白的可以不用着急,我们先暂且搁置,稍后我会在推到的过程中解释。

正式推导过程:

将样本集  S=\begin{Bmatrix} y_{1} =w_{11}^{(l)}x_{1}+w_{12}^{(l)}x_{1}+w_{13}^{(l)}x_{1} \\ y_{2}=w_{21}^{(l)}x_{1}+w_{22}^{(l)}x_{1}+w_{23}^{(l)}x_{1} \\ ..........................................\\ y_{m}=w_{m1}^{(l)}x_{1}+w_{m2}^{(l)}x_{1}+w_{m3}^{(l)}x_{1} \\ \end{Bmatrix}中样本的每一个特征权重和特征值按列堆叠可以得到W^{(l)}=\begin{bmatrix} w_{11}^{(l)} & w_{21}^{(l)} & ... & w_{m1}^{(l)}\\ w_{12}^{(l)} & w_{22}^{(l)} & ... & w_{m2}^{(l)}\\ w_{13}^{(l)} & w_{23}^{(l)} & ... & w_{m3}^{(l)} \end{bmatrix} , X=\begin{bmatrix} x_{1}\\ x_{2}\\ x_{3} \end{bmatrix},这样是不是就很熟悉了,慢慢看到样本与权重拟合的雏形了,现在需要做一些转换,对线性代数熟悉的同学应该知道矩阵乘法的计算方式AB矩阵相乘需要满足A矩阵的列数要等与B矩阵的行数。

所以有,Z^{(l)}=W^{(l)T}X^{(l-1)}+b^{(l)},用W^{l}的转置矩阵W^{lT}来计算。

Z^{(l)}=\begin{bmatrix} w_{11}^{(l)} & w_{12}^{(l)} & w_{13}^{(l)}\\ w_{21}^{(l)} & w_{22}^{(l)} & w_{23}^{(l)} \\ ... & ... & ... \\ w_{m1}^{(l)} & w_{m2}^{(l)} & w_{m3}^{(l)} \end{bmatrix}*\begin{bmatrix} x_{1}\\ x_{2}\\ x_{3}\\ \end{bmatrix}+b^{(l)} 至此,我们还需要通过给Z^{l}套上一个\sigma函数,来计算最终的激活值。

(1)、初始化

A^{(l)} = X,随机初始化一个服从正太分布W^{(l)}(=np.random.randn(0,1))但是不能为0,否则计算的结果都是0没有意义,b可以是0,有了初始化的值,就可以通过下面的公式一步一步迭代得到最后一层的输出结果,也就是我们需要的预测值A^{l}

(2)计算第一个隐层

\left\{\begin{matrix} Z^{(l)}=W^{(l)T}X+b^{(l)}\\ A^{(l)}=\sigma\left (Z^{(l)} \right ) \end{matrix}\right.,之后你会发现除了第一层的XX,之后的每一层我都是用A^{l}来代替的,这是因为前一层的A^{l}就是下一层计算的X,因为A的值是通过Sigmoid激活函数计算出来的,所以A^{l}也叫激活值。用来激活下一层的计算的。

(3)计算第二个隐层(输出层)

\left\{\begin{matrix} Z^{(2)}=W^{(2)T}A^{1}+b^{(2)}\\ A^{(2)}=\sigma\left (Z^{(2)} \right ) \end{matrix}\right.

将计算推广到 l 层

1. 在 l-1 层,有:

\left\{\begin{matrix} Z^{(l-1)}=W^{(l-1)T}A^{(l-2)}+b^{(l-1)}\\ A^{(l-1)}=\sigma\left (Z^{(l-1)} \right ) \end{matrix}\right.

2. 在 l 层,有:

\left\{\begin{matrix} Z^{(l)}=W^{(l)T}A^{(l-1)}+b^{(l)}\\ \hat{Y} = A^{(l)}=\sigma\left (Z^{(l)} \right )\end{matrix}\right.

(4)、计算损失函数

通常对于二分类问题损失函数主要有交叉熵损失和MSE损失,为了方便计算我们在这里用交叉熵损失函数:

L\left ( \hat{y} ,y\right )=-\left ( yln\hat{y}+(1-y)ln(1-\hat{y}) \right ),由此我们可以得到代价函数,有如下表达:

J(W,b,X,Y)=-\frac{1}{M}\sum \left ( Yln\hat{Y}+(1-Y)ln(1-\hat{Y}) \right )到此,例子中的所有单隐层的所有前向步骤全部结束了,是不是感觉很简单呢。但到这里的计算只是前向的结束,那么如何去迭代更新每一层的参数W^{(l)},b^{(l)}呢?这里纪要再费点时间介绍一下反向传播算法的思想了。

(在这里额外补充一句,标准的最小二乘函数表达式是:l\left ( \hat{y},y \right )=\left ( \hat{y}-y \right )^{2},但有的时候你会发现深度学习中使用的最小二乘的损失函数是这样写的:l\left ( \hat{y},y \right )=\frac{1}{2}\left ( \hat{y}-y \right )^{2},他是在标准的最小二乘前面加了一个\frac{1}{2} 其实也没什么别的意思,就是为了求导的时候消除前面的系数 2,就这个作用,如果你看到这样的写法也不要太惊讶)

四、DNN的反向传播思想

好了,算法走到这里之后,我们需要思考一个问题,反向传播究竟是传播什么?又能得到什么?又能做什么?如果能把这几个问题想清楚,你就理解了BP得到思想精髓了也是整个DNN的思想精髓。

OK,来看一下我们计算的预测值(\hat{Y})与真实值(Y)之间肯定是存在误差J(W,b,X,Y)的,那么要消除误差需要做什么?我们发现贯穿始终的与预测值有关的就是每一层的参数W,b,所以我们必须计算每一层的W,b,通过不断调整W,b,来减小误差,那么有了目标之后我们需要知道怎么做,也就是传播什么的问题了,传播什么回去可以调整W,b,以达到减小误差的目的。

现在再来思考一下,前向传播与反向传播的差别在哪儿?我们是否可以借鉴前向传播的思想,来计算反向传播的公式?

我们把反向的计算过程类比前向的思想,你会发现反向计算的时候,下面这个公式

\left\{\begin{matrix} Z^{(l)}=W^{(l)T}A^{(l-1)}+b^{(l)}\\ \hat{Y} = A^{(l)}=\sigma\left (Z^{(l)} \right )\end{matrix}\right.,计算出来的结果Z^{(l)} ,A^{(l)}是不是类似前向传播中的初始值A^{(0)},Z^{(0)}初始值?当然这里的Z^{(0)}通常不用,因为没有意义,我们需要的是A^{(0)},?这些都是后话,我们来看一下反向传播的推导,看看你能否从中看出一些规律,并将其运用到日后的学习中。

由于时间原因,上图我只画了正向和反向的部分全连接传播示意图,读者在查看的时候需要有一个基本的判断,不要被误导。

BP的正式推导过程:

(1)、伪初始化计算第 l 层

伪初始化可能你在其他文章中看不到这个词,这是我随便写的一个词,主要是对比前向的思想来帮助你了解反向传播,我们通过正向得到的最后一组数据是Z^{(l)},A^{(l)},W^{(l)},b^{(l)},以该数据为初始数据来反推前l-1层所需要的数据。

代价函数:J(W,b,X,Y)=-\left ( Yln\hat{Y}+(1-Y)ln(1-\hat{Y}) \right )

{W^{(l)}}'=\frac{\partial J}{\partial W^{(l)}}=\frac{\partial J}{\partial A^{(l)}}\cdot \frac{\partial A^{(l)}}{\partial Z^{(l)}}\cdot\frac{\partial Z^{(l)}}{\partial W^{(l)}},或写成 {W^{(l)}}'=\frac{\partial J}{\partial W^{(l)}}=\frac{\partial J}{\partial A^{(l)}}\cdot {\sigma}'\left ( Z^{(l)} \right )\cdot\frac{\partial Z^{(l)}}{\partial W^{(l)}}

{b^{(l)}}'=\frac{\partial J}{\partial b^{(l)}}=\frac{\partial J}{\partial A^{(l)}}\cdot \frac{\partial A^{(l)}}{\partial Z^{(l)}}\cdot\frac{\partial Z^{(l)}}{\partial b^{(l)}},或写成  {b^{(l)}}'=\frac{\partial J}{\partial b^{(l)}}=\frac{\partial J}{\partial A^{(l)}}\cdot {\sigma}'\left ( Z^{(l)} \right )\cdot\frac{\partial Z^{(l)}}{\partial b^{(l)}} 为了看的更加清晰我将对上面的两个式子做仔细推导,以方便大家对比学习。

求解的过程中我们发现,两个计算的式子中有一个共有的部分 \frac{\partial J}{\partial A^{(l)}}\cdot {\sigma}'\left ( Z^{(l)} \right ) 可以先将这部分计算出来cache()住,方便后面计算,加快计算速度。

因此,上述的公式可以继续化简,得到:

\begin{align*} {W^{(l)}}'=\frac{\partial J}{\partial W^{(l)}}=\frac{\partial J}{\partial A^{(l)}}\cdot {\sigma}'\left ( Z^{(l)} \right )\cdot\frac{\partial Z^{(l)}}{\partial W^{(l)}}=\frac{\partial J}{\partial Z^{(l)}}\cdot\frac{\partial Z^{(l)}}{\partial W^{(l)}}=(A^{(l)}-Y)A^{(l)-1T} \end{align*}

{b^{(l)}}'=\frac{\partial J}{\partial b^{(l)}}=\frac{\partial J}{\partial A^{(l)}}\cdot {\sigma}'\left ( Z^{(l)} \right )\cdot\frac{\partial Z^{(l)}}{\partial b^{(l)}}=\frac{\partial J}{\partial Z^{(l)}}\cdot\frac{\partial Z^{(l)}}{\partial b^{(l)}}=\frac{\partial J}{\partial Z^{(l)}}=A^{(l)}-Y

(2)、反向求第l-1

根据上面 l 层给出的公式,,来推导 l-1 层的式子,发现有一个公共的式子可以单独求出

我们需要计算出\frac{\partial J}{\partial Z^{(l)}},这样后面的计算就方便了,现在来看一下\frac{\partial J}{\partial Z^{(l)}}能否给出更加简单的推导?根据 l 层的公式,你会发现 l-1 层有如下规律:

\frac{\partial J}{\partial Z^{(l)-1}}=\frac{\partial J}{\partial Z^{(l)}}\cdot\frac{\partial Z^{(l)}}{\partial Z^{(l-1)}}\cdot\frac{\partial Z^{(l-1)}}{\partial Z^{(l-2)}}\cdot\cdot\cdot\cdot\frac{\partial Z^{(3)}}{\partial Z^{(2)}}\cdot\frac{\partial Z^{(2)}}{\partial Z^{(1)}} 

因为在 l 层我们已经计算出了\frac{\partial J}{\partial Z^{(l)}},所以后面的式子我们只需要关注\frac{\partial Z^{(l)}}{\partial Z^{(l-1)}}就行,继续推导\frac{\partial Z^{(l)}}{\partial Z^{(l-1)}}的公式:

A^{(l-1)}=\sigma \left ( Z^{(l-1)} \right )

Z^{(l)}=W^{(l)}A^{(l-1)}+b^{(l)} 

综合两式得:Z^{(l)}=W^{(l)}\sigma \left ( Z^{(l-1)} \right )+b^{(l)}

故而,\frac{\partial Z^{(l)}}{\partial Z^{(l-1)}}=\frac{\partial (W^{(l)}A^{(l-1)}+b^{(l)})}{\partial Z^{(l-1)}}=\frac{\partial (W^{(l)}\sigma (Z^{(l-1)}) +b^{(l)})}{\partial Z^{(l-1)}}=W^{(l)}\sigma' (Z^{(l-1)})

所以,\frac{\partial J}{\partial Z^{(l-1)}}=\frac{\partial J}{\partial Z^{(l)}}\frac{\partial Z^{(l)}}{\partial Z^{(l-1)}}=\frac{\partial J}{\partial Z^{(l)}}W^{(l)}\sigma' (Z^{(l-1)})

由此,我们可以将l-1层的dW,db公式进行化简,得到:

\frac{\partial J}{\partial W^{(l-1)}}=\frac{\partial J}{\partial Z^{(l-1)}}\cdot\frac{\partial Z^{(l-1)}}{\partial W^{(l-1)}}=\frac{\partial J}{\partial Z^{(l-1)}}\cdot A^{(l-2)T}

\frac{\partial J}{\partial b^{(l-1)}}=\frac{\partial J}{\partial Z^{(l-1)}}\cdot\frac{\partial Z^{(l-1)}}{\partial b^{(l-1)}}=\frac{\partial J}{\partial Z^{(l-1)}}

然后再去更新W,b即可

W^{(l-1)}=W^{(l-1)}+\alpha \frac{\partial J}{\partial Z^{(l-1)}}A^{(l-2)T}

b^{(l-1)}=b^{(l-1)}+\alpha \frac{\partial J}{\partial Z^{(l-1)}},因为前面已经计算过第 l 层的W^{(l)},b^{(l)}所以,之后不再计算这层的权重和偏差,只需要根据第 l 层的W^{(l)},b^{(l)}来不断递推后面的数据即可。

至此,所有的计算就全部结束了,我们可以通过将上下层的关系联系起来去迭代dW,db的数据,现在我们回过头来想一下反向传播的思想与前向传播的思想有什么不同,细心的朋友们可能已经发现,二者在计算思路上基本一致,都是通过上层的计算结果来计算下一层的结果,唯一需要注意的是思路的转变。

五、DNN能做什么?(选)

DNN的标准网络可以说是标准的神经网络计算方式,它的出现被认为是里程碑的式的发展,此后的CNN、RNN都是在DNN的基础上演变而来的,DNN能做的事情很多,往往经典学习领域的问题都能通过DNN集成学习实现,比如分类问题,语音识别,计算机视觉等,但是后两者有了更好的计算方式那就是RNN和CNN,他们在不同的领域发挥着不同的功能,CNN更适合图像识别领域,而RNN则更适合处理时间序列问题,这让处理一个问题的选择变得更加广泛和灵活,能够帮助开发者节约大量时间,从而将精力更多的放在研究精确和准确度上。

前面我用了大量的篇幅介绍二分类问题,相信你已经能够充分的理解DNN的算法思想了,下面介绍一个DNN图像识别的例子,我们需要知道DNN为什么能够识别图像?

 你应该知道图像其实就是一个三维的矩阵(1000,1000,3),表示红黄蓝三色的图形数据长宽比分别是1000*1000的图片,也就是1000维数*1000维数的三色图,以灰度图(只有一种颜色1000*1000*1)为例,灰度图识别通常不看第三维,所以当成二维数据来看待,我们以64*64的图片来看,将每一行的色度特征竖向排列成一个列向量,这个列向量就是一张图片的灰度图样本 X=\begin{bmatrix} x_{0}&...&x_{63}&x_{64}&...&x_{127}&...&x_{4095}\end{bmatrix}^{T},样本维度为64*64=4096

机器通过学习样本图的边缘信息(比如横竖排列的小方块),再通过不同的隐层来学习局部信息(比如眼睛,鼻子,嘴巴等),直到学习到全图信息为止(整个脸部特征),最后输出我们想要的结果,这就是隐层的作用。

以上就是我对DNN的理解和总结,希望能够帮助到你,如果文章中有什么不对的地方,请在评论中指出,我会及时修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值