一步步手写神经网络

这篇博客主要是一步步的手撸一个神经网络出来,相信看完这篇博客,大家会对神经网络有一个比较深刻的认识。看完后,你可能会发现只要会基本的求导,其实bp(backward propagation)并没有想象中的那么难。下面就来一步步手写一个神经网络。我会先拿一个简单的3层神经网络做demo展示下求解神经网络的整体过程,其实主要就是forward propagation(前向传播)和backward propagation(后向传播/逆向传播)这两个过程。 
一个简单的神经网络: 

一步步手写神经网络的图1

这是一个简单的只有三层的神经网络,先来定义一些notation(这个notation沿用ng的): 

一步步手写神经网络的图2

具体到上面给出的神经网络demo图,这里有: 

一步步手写神经网络的图3

其实这其中最难确定的是参数w,b,a 的维度,其实看上面图中参数的维度,也能够发现参数w,b,a 的维度: 

一步步手写神经网络的图4

        还有就是这个demo中隐藏层激活函数使用的是现在最常用的ReLU当做激活函数,输出层因为是个二元分类就使用sigmoid函数作为激活函数(如果是多分类现在最常用的是softmax函数),关于几种激活函数,详见本人另一篇博客:几种常见的激活函数,代价函数则是使用的交叉熵函数,神经网络的交叉熵代价函数为: 

一步步手写神经网络的图5

接下来正式进入到forward propagation阶段,前向传播的计算过程为: 

一步步手写神经网络的图6

总结下上面的公式其实能够发现: 

一步步手写神经网络的图7

下面是backward propagation(bp)阶段,其实就是求导(得到梯度),我会详细的写出求导过程:

对  W[3] W [ 3 ]  求导:

一步步手写神经网络的图8

在求出  W[3] W [ 3 ]  的同时其实也得到了  db[3] d b [ 3 ]

一步步手写神经网络的图9

对  W[2] W [ 2 ] 求导:

一步步手写神经网络的图10

同样能够得到  db[2] d b [ 2 ]

一步步手写神经网络的图11

W[1] W [ 1 ] 求导,得:

一步步手写神经网络的图12

db[1] d b [ 1 ] 为:

一步步手写神经网络的图13

其实bp这个公式也有规律的,通过上面我的 “总结”,应该发现: 

一步步手写神经网络的图14

        以上就是这个3层神经网络Foward propagation和backward propagation的详细具体过程。并且我们能够发现一些规律,很容易的推广到L层。下面就来一步步手撸一个神经网络,我们在实现的时候一定要注意矩阵的维度,而且要搞清楚矩阵之间到底是乘(线代里矩阵相乘的定义)还是点乘(对应元素相乘)。前向传播的还倒好,bp的向量化实现如下: 

一步步手写神经网络的图15

下面进入到代码实现阶段:

|| forward propagation阶段

1.首先初始化参数w,b,对于参数w,b的初始化要随机初始化,至于为什么要随机初始化,请参见本人博客:神经网络(neural network)。关于对权重的初始化方法,详见本人另一篇博客:深度学习中神经网络的几种权重初始化方法。下面代码中随机初始化参数w时之所以0.01,目的是:如果我们不乘的话,有可能会把参数初始化为一个比较大的数,这样会导致z=w.T X + b,z的值有时候会比较大,这样的话,如果你使用sigmoid或者tanH作为激活函数,得到的导数(梯度)会非常的小,这样参数更新的速度会比较慢。 

一步步手写神经网络的图16

2.实现激活函数(ReLU和sigmoid): 

一步步手写神经网络的图17

3.计算一个L层的网络每一层的激活值,也就是整个Foward propagation的过程: 

一步步手写神经网络的图18

4.整个forward propagation完后,开始计算代价函数: 

一步步手写神经网络的图19

|| backward propagation阶段

1.从我们总结出来的规律,能够看到,只要给定了后一层dA后,dz,dW,db很容易就能够求出: 
relu导数: 

一步步手写神经网络的图20

下面是bp过程: 

一步步手写神经网络的图21

2.下面就是更新参数w,b: 

一步步手写神经网络的图22

以上就是整个bp的过程,至此,fp和bp整个流程已经全部写完了,下面再写个主函数,把fp和bp串联下,整个dnn网络就完成了: 

一步步手写神经网络的图23

这样就得到了,这个网络的参数W,b,这样我们就可以用这个参数去做分类了,下面顺手在撸个predict函数吧: 

一步步手写神经网络的图24

写个入口函数: 

一步步手写神经网络的图25

至此,整个deep neural network已经写完了,虽然简单,可能代码也写的不够严谨。但对于理解neural network,即forward propagation和backward propagation非常有帮助。拿sklearn中的load_breast_cancer数据集测了下,当隐藏层单元设置为[20,10,5,1]时,准去率达到了92%,代价函数示意图如下: 

一步步手写神经网络的图26

p.s:这里另外提一下,ng的在Coursera上的课把每个步骤划分的更加细致,但是我个人认为那样不太好,有点打乱了fp和bp的整体性,这个每个人的口味都不一样。最重要的一点。。。是我觉得ng的relu求导写错了,现在把ng的relu求导代码贴出来,然后把我改正的(我认为是对的)也贴出来,供路过的大侠鉴定下,欢迎留言交流。 
ng的relu_backward: 

一步步手写神经网络的图27

我改正后的: 

一步步手写神经网络的图28

博客完整的代码已经放到github上了:deep_neural_network 
改正版的ngCoursera作业上的代码:deep_neural_network_ng 


  • 参考资料:Coursera上ng的《neural network and deep learning》课

默认 最新
当前暂无评论,小编等你评论哦!
点赞 评论 收藏 1
关注