反向传播算法(BP)

栏目: 编程工具 · 发布时间: 5年前

内容简介:之前介绍过牛顿迭代法:当我们想要优化一个目标函数时,需要在每次迭代的时候对变量/参数进行更新,而更新参数的最重要的部分就是下面对最简单的神经网络进行BP算法的公式推导:下图是一个只有两个神经元的网络(图片修改自李弘毅老师的PPT),输入样本为一个二维的向量

之前介绍过牛顿迭代法:当我们想要优化一个目标函数时,需要在每次迭代的时候对变量/参数进行更新,而更新参数的最重要的部分就是 求目标函数对参数的导数 了。

下面对最简单的神经网络进行BP算法的公式推导:

下图是一个只有两个神经元的网络(图片修改自李弘毅老师的PPT),输入样本为一个二维的向量

,输出为一个数 ,现在假设loss函数是 ,那么要求的便是 以及 (把 合并成一个向量

也是可以的)。

反向传播算法(BP)

图中,

表示sigmiod函数。

首先思考一下,这个导数如果让你计算应该怎么做呢?

因为loss函数里与

, 参数相关的就只有 了,而 得出, 由线性函数

得到…那自然会想到用chain rule来求导了。

整理一下思路:

那么求导如下:

这么求解貌似是可以的,however, 没有任何技巧可言,当网络结构有变化的时候,算法变的异常难写,比如:一层多个神经元的情况,两层之间非全连接的情况,某些神经元共享参数的情况等,想想都可怕,想要写个general的算法几乎不可能,另外还有计算量需要被考虑。

还好聪明人总是有的,考虑到

和对 求导过程其实是一样的,下面就仅介绍

的BP求导过程。

对于上面的问题,先只看第一层神经元的参数更新(其实对于任意层任意神经元都有下式的关系):

接下来分别计算

: 正向计算

从式(3)可以看出正向计算有个非常好的性质,

就是神经元的值,这都已经在正向传播时计算过了!

反向计算

这其中,

很简单,sigmiod求导就ok了,而且

,nice,又可以用现成的结果了。

而对于

的计算比较棘手了,因为:

其中

就是神经元间的连接权重参数,对于比较复杂的网络,计算 可以进行递归计算。如果被计算的

是神经网络的最后一层(output layer),问题就变的简单了:

结束了,,

再看一下 反向计算

:因为 比较好求,是一个常数,sigmoid函数在该神经元上的求导就得到了; 呢则可以使用递归方法,只要求出output layer的 就ok。从下图来看,就是input为

,然后按照同样的网络反方向计算一次,和正向传播的不同之处仅仅在于sigmoid(非线性转换/激活函数)变成先求导再相乘,结构清晰,计算量也大幅度下降。

反向传播算法(BP)

最后总结一下: 正向传播反向传播 相乘就可以计算出所有的参数更新梯度。

反向传播算法(BP)

插句话:

神经网络中常用的优化算法是 随机梯度下降法 (SGD),实践中常用的是 adam 优化器(一种自适应步长/学习率的优化算法),理论上梯度下降做自适应步长也很简单,不过需要求Hessian矩阵,而对于上千万甚至上亿个参数的目标函数来说,计算量实在是太大了。

代码实现

这里对基础版的反向传播算法进行代码实现,代码来自 这里 ,你也可以点击 这里 进行查看。核心代码如下:

def feedforward(self, x):  # 正向计算
    # return the feedforward value for x
    a = np.copy(x)
    z_s = []
    a_s = [a]
    for i in range(len(self.weights)):
        activation_function = self.getActivationFunction(self.activations[i])
        z_s.append(self.weights[i].dot(a) + self.biases[i])
        a = activation_function(z_s[-1])
        a_s.append(a)
    return (z_s, a_s)

def backpropagation(self,y, z_s, a_s):  # 反向计算
    dw = []  # dl/dW
    db = []  # dl/db
    deltas = [None] * len(self.weights)  # delta = dl/dz  known as error for each layer
    # insert the last layer error
    deltas[-1] = ((y-a_s[-1])*(self.getDerivitiveActivationFunction(self.activations[-1]))(z_s[-1]))
    # Perform BackPropagation
    for i in reversed(range(len(deltas)-1)):
        deltas[i] = self.weights[i+1].T.dot(deltas[i+1])*(self.getDerivitiveActivationFunction(self.activations[i])(z_s[i]))
    #a= [print(d.shape) for d in deltas]
    batch_size = y.shape[1]
    db = [d.dot(np.ones((batch_size,1)))/float(batch_size) for d in deltas]
    dw = [d.dot(a_s[i].T)/float(batch_size) for i,d in enumerate(deltas)]
    # return the derivitives respect to weight matrix and biases
    return dw, db

RNN怎么做BP

RNN的结构和 前馈神经网络 有所不同,反向传播和上述也略有不同,这里要介绍的算法叫做 Backpropagation Through Time (BPTT) 。这里假设读者对RNN、LSTM、GRU等算法已经有所了解了,就提纲挈领的介绍一下 BPTT 特别之处。

  • 主要的不同点还是要看公式,RNN的在 时刻输出神经元的值可以用下式表示:式中 与上一时刻的计算结果相关
  • 所以 的计算算是新内容,其他的和之前说的没有什么不一样
  • 也可以认为就是结构上与前馈网络有所不同(如下图所示),对于每一个 都有一个loss,这里需要对每一个loss计算梯度,加起来就是整个需要更新的梯度了。

反向传播算法(BP) 一个简单的many2many形式的RNN展开图,图片来自 这里


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

可视化未来

可视化未来

[美] 埃雷兹·艾登、[法] 让-巴蒂斯特·米歇尔 / 王彤彤、沈华伟、程学旗 / 浙江人民出版社 / 2015-9 / 54.90元

科学的传播速度有多快?今时今日我们很少谈论上帝了吗?人们什么时候开始用“having sex” 而不用“making love”? 史上的人是在哪岁成名的?语法的变化速度到底有多快?哪些作家被纳粹审查得最彻底? “donut” 什么时候开始取代“doughnut”? 我 们能否预测人类未来?比尔·克林顿和花椰菜哪个更出名? 《可视化未来》一书的两位作者通过与“谷歌图书”的合作,得以有机会研究......一起来看看 《可视化未来》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码