用Python+Numpy模块实现神经网络(五)

用Python+Numpy模块实现神经网络(四) 续集

7. 偏导数与偏导数链式法则 

    hi,大家好,欢迎阅读本篇博客,在上一篇中,我们知道了矩阵运算对于神经网络的重要性,并用Python亲手实践了一个简单的二层神经网络的前向传播。在这一篇中,我们又要引入(复习)两个数学概念:偏导数与偏导数链式法则。

    什么是偏导数?还记得前几篇博客中提到的导数吗(在《用Python+Numpy模块实现神经网络(三)》提到),我们计算导数的时候,函数是用Python+Numpy模块实现神经网络(五),也就是说,这个函数只有一个自变量,那么假如这个函数是用Python+Numpy模块实现神经网络(五),那么我们就无法给x与y同时求导,而是针对一个自变量求导,假如在上边函数中,我只想知道x的导数,我们可以叫他——关于x的偏导数。那么具体如何求呢(我们把关于x的偏导数记作用Python+Numpy模块实现神经网络(五),同理,我们把关于y的偏导数记作用Python+Numpy模块实现神经网络(五)):

用Python+Numpy模块实现神经网络(五)

是的!我们只针对x,就当是求单变量函数的导数一样,而把y“放任自流”????。(如果看不懂以上的,请回到《用Python+Numpy模块实现神经网络(三)》,要是还不懂,请自行寻找关于导数与微积分有关的详细文章、书籍)

接下来,我们再来讨论一下偏导数链式法则,别看名字这么长,其实也很好理解,假如有个函数:用Python+Numpy模块实现神经网络(五),而用Python+Numpy模块实现神经网络(五),那么我想知道f关于y的偏导数,那该怎么办?很简单,我们可以先求出f(x)等于x方的导数,再用他乘以x(y)等于y方的导数也就是:

用Python+Numpy模块实现神经网络(五)

先不要问它对神经网络到底有什么用处,读到下文就知道了????。

 

8. 计算机自动更新权重——反向传播与损失函数

 hey!现在精神怎么样。精神不好的去洗把脸,精神好的盯紧了!这一章将会是本系列最重要的章节。我们已经提了很久了,我们已经学会了神经网络的前向传播,可是一直没有知道如何让网络自己更新权重,首先,我们重申一下三层神经网络是如何前向传播的(式中的量都是矩阵)(I是输入矩阵,W1是输入层到隐藏层的权重矩阵,H是隐藏层神经元矩阵,W2是隐藏层到输出层的权重,O是输出层神经元矩阵,sigmoid是**函数(前几篇文章提到过)):

用Python+Numpy模块实现神经网络(五)

用Python+Numpy模块实现神经网络(五)

要做到反向传播,我们就得有一个损失函数,损失函数是什么?也就是评测输出离正确输出的距离的函数(O为神经网络输出,T为正确答案,E为损失(误差)):

用Python+Numpy模块实现神经网络(五)

为什么会有一个平方,想一想,加上了平方会让小的误差更小,大的误差更大,想想人,我们一般都会忽略一些无关紧要的小错,而更在意一些影响更大的大错误,当然,读到下文,你会发现他其实还有更大的用处哦????

好,请大家集中注意,让我们来想一想,我们如何让神经网络达到最优,其实就是让损失变成最小(或等于0),而我们损失函数的图像差不多如下:

用Python+Numpy模块实现神经网络(五)

可以看到这个非线性函数下方的(0.0,0.0)那个点,这就是损失函数等于零时的点,我们不可能用一个方程就解出那个点,于是我们又有了一个方法:

用Python+Numpy模块实现神经网络(五)

是的,就是如此,可是为什么一定要一步一步呢,不能一步用直线拟合到零点呢?来,那我们就看一下这样会怎么样:

用Python+Numpy模块实现神经网络(五)

对啊!真是不太对????!

好了,现在我们知道了如何调整权重了,可是具体如何实现吗?对了,还记得导数吗!它就能拟合曲线!也就是我们用上面学到的偏导数以及链式法则的知识,就能解决这个问题。首先,我们要引入新的变量——a,也就是说这个a就代表我们一步走多长,一般叫做步长或者学习率,在程序中我们一般叫他lr(Learing Rate学习率的简写),好,我们把要被求导的函数准备好吧:

用Python+Numpy模块实现神经网络(五)

用Python+Numpy模块实现神经网络(五)

是的,我们先从如何更新隐藏层到输出层的权重说起,我们已经见过上面的两个式子不止一次了,但是让我们以偏导数链式法则的视角开看这个式子,嘿!这是个链式法则的标准式!也就是说,我们知道了误差E就能求出权重要下降的量,那如何去求呢?算法如下!(等一等,sigmoid函数的导数是特殊的,它是sig(x)*(1-sig(x)),请牢记!!):

用Python+Numpy模块实现神经网络(五)

也就是我们要算出上面第一个式子的导数,再乘以第二个式子的导数:

第一个式子的导数为:

用Python+Numpy模块实现神经网络(五)

最后算得答案为用Python+Numpy模块实现神经网络(五)

好,我们再算第二个式子的导数:

用Python+Numpy模块实现神经网络(五)

这个式子可不是自己算的,上边已经说过了sigmoid函数的导数了,还在疑惑的小伙伴课就没认真看了!

让我们把他们总结到一起:

用Python+Numpy模块实现神经网络(五)

额?怎么短了不少。其实只是简化了,T-O不就是E么,而在函数图像中E其实是正的。sigmoid去哪了?其实那个sigmoid运算得到的不就是O吗!

等等!其实后边还有一项,在sigmoid运算中,其实还进行了一次求导,所以表达式得改为如下(顺便把表达式只局限于隐藏层与输出层之间的权重的更新的"毛病“改了,让表达式适用于更新随便两层之间的权重):

用Python+Numpy模块实现神经网络(五)

看,我们把学习率也加进去了,这个OT就是把O这个矩阵倒过来,它的作用在此就不详细讲了。

哎,好累啊!我写的很累,相信你读的也很累,但是还有最后一个小问题,让我们坚持一下!问题是:在输入曾与隐藏层之间,他们的E(误差)是什么呢?,其实他们的误差用最终误差E乘以W2,就对了。

 

今天真的很累,以上内容有些地方讲的可能有写不详细,如果大家可能对神经网络还是不大了解,我们就无法进入下一篇的内容,在此,我向大家极力推荐一本书,我就是通过这本书彻底学会神经网络的,请大家务必看一看,他的很多内容比本系列文章详细的多,而且对初学者真的非常友好,最后还有详讲用Python实现神经网络,我只给大家附一张书的封面图:

用Python+Numpy模块实现神经网络(五)

想学神经网络,这本书是一条必经之路。  未完待续......