一步步手写神经网络

一步步手写神经网络

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

DNN

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

notation

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

matrix

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

维度

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

cost function

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

计算过程

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

for循环计算过程

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

W [ 3 ] 求导

w3导数

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

db3公式

W [ 2 ] 求导

dw2

同样能够得到 d b [ 2 ]

db2

W [ 1 ] 求导,得:

dW1

d b [ 1 ] 为:

db1

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

规律

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

向量化实现

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

|| forward propagation阶段

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

参数初始化

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

激活函数

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

forward propagation

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

cost function

|| backward propagation阶段

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

relu_backward

下面是bp过程:

bp

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

update_parameter

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

llm

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

predict

写个入口函数:

DNN

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

costf function 变化示意图

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

ng_relu_backward

我改正后的:

me_back

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


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

猜你喜欢

转载自blog.csdn.net/u012328159/article/details/80081962