cs231n笔记--反向传播

来源:互联网 发布:linux 挂载iso什么意思 编辑:程序博客网 时间:2024/06/08 03:13

简单表达式和梯度

首先反向传播是利用链式法则递归计算表达式的梯度的方法。从简单表达式入手可以为复杂表达式打好符号和规则基础。先考虑一个简单的二元乘法函数这里写图片描述对两个输入变量分别求偏导数还是很简单的:
这里写图片描述

这些导数的意义在于函数变量在某个点周围的极小区域内变化,而导数就是变量变化导致的函数在该方向的变化率。

链式法则

现在考虑更复杂的包含多个函数的复合函数,比如这里写图片描述。虽然这个表达足够简单,可以直接微分,但是在此使用一种有助于读者直观理解反向传播的方法。将公式分成两部分:q=x+y和f=qz。在前面已经介绍过如何对这分开的两个公式进行计算,因为f是q和z相乘,所以,又因为q是x加y,所以这里写图片描述
链式法则指出将这些梯度表达式链接起来的正确方式是相乘,比如这里写图片描述在实际操作中,这只是简单地将两个梯度数值相乘,示例代码如下:

# 设置输入值x = -2; y = 5; z = -4# 进行前向传播q = x + y # q becomes 3f = q * z # f becomes -12# 进行反向传播:# 首先回传到 f = q * zdfdz = q # df/dz = q, 所以关于z的梯度是3dfdq = z # df/dq = z, 所以关于q的梯度是-4# 现在回传到q = x + ydfdx = 1.0 * dfdq # dq/dx = 1. 这里的乘法是因为链式法则dfdy = 1.0 * dfdq # dq/dy = 1

最后得到变量的梯度[dfdx, dfdy, dfdz],它们告诉我们函数f对于变量[x, y, z]的敏感程度。这是一个最简单的反向传播。一般会使用一个更简洁的表达符号,这样就不用写df了。这就是说,用dq来代替dfdq,且总是假设梯度是关于最终输出的。
这次计算可以被可视化为如下计算线路图像:
这里写图片描述
上图的真实值计算线路展示了计算的视觉化过程。前向传播从输入计算到输出(绿色),反向传播从尾部开始,根据链式法则递归地向前计算梯度(显示为红色),一直到网络的输入端。可以认为,梯度是从计算链路中回流。

反向传播的直观理解

下面通过例子来对这一过程进行理解。加法门收到了输入[-2, 5],计算输出是3。既然这个门是加法操作,那么对于两个输入的局部梯度都是+1。网络的其余部分计算出最终值为-12。在反向传播时将递归地使用链式法则,算到加法门(是乘法门的输入)的时候,知道加法门的输出的梯度是-4。如果网络如果想要输出值更高,那么可以认为它会想要加法门的输出更小一点(因为负号),而且还有一个4的倍数。继续递归并对梯度使用链式法则,加法门拿到梯度,然后把这个梯度分别乘到每个输入值的局部梯度(就是让-4乘以x和y的局部梯度,x和y的局部梯度都是1,所以最终都是-4)。可以看到得到了想要的效果:如果x,y减小(它们的梯度为负),那么加法门的输出值减小,这会让乘法门的输出值增大。

sigmoid

任何可微分的函数都可以看做门。可以将多个门组合成一个门,也可以根据需要将一个函数分拆成多个门。使用sigmoid激活函数的2维神经元的例子。输入是[x0, x1],可学习的权重是[w0, w1, w2]。一会儿会看见,这个神经元对输入数据做点积运算,然后其激活数据被sigmoid函数挤压到0到1之间。在实际的应用中将这些操作装进一个单独的门单元中将会非常有用。该神经元反向传播的代码实现如下:

w = [2,-3,-3] # 假设一些随机数据和权重x = [-1, -2]# 前向传播dot = w[0]*x[0] + w[1]*x[1] + w[2]f = 1.0 / (1 + math.exp(-dot)) # sigmoid函数# 对神经元反向传播ddot = (1 - f) * f # 点积变量的梯度, 使用sigmoid函数求导dx = [w[0] * ddot, w[1] * ddot] # 回传到xdw = [x[0] * ddot, x[1] * ddot, 1.0 * ddot] # 回传到w# 完成!得到输入的梯度
原创粉丝点击