反向传播
链式法则
若 f(x, y) = x + y
则 df/dx = 1 df/dy = 1
因为无论增加x,y中任一个的值,函数的值都会增加,并且增加的变化率独立于x,y的具体值。
链式法则就是把梯度表达式通过相乘链接起来,代码如下:
# 设置输入值
x = -2; y = 5; z = -4
# 进行前向传播
q = x + y # q becomes 3
f = q * z # f becomes -12
# 进行反向传播:
# 首先回传到 f = q * z
dfdz = q # df/dz = q, 所以关于z的梯度是3
dfdq = z # df/dq = z, 所以关于q的梯度是-4
# 现在回传到q = x + y
dfdx = 1.0 * dfdq # dq/dx = 1. 这里的乘法是因为链式法则
dfdy = 1.0 * dfdq # dq/dy = 1
这次计算的线路图,前向传播为绿色,从输入到输出,反向传播为红色,从输出到输入根据链式法则计算梯度。
链式法则指出,门单元应该将回传的梯度乘以它对其的输入的局部梯度,从而得到整个网络的输出对该门单元的每个输入值的梯度。
sigmoid函数
该神经元反向传播的代码实现如下:
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] # 回传到x
dw = [x[0] * ddot, x[1] * ddot, 1.0 * ddot] # 回传到w
# 完成!得到输入的梯度
局部梯度和梯度概念很重要!!:
梯度:整个网络的输出值关于输入值
局部梯度:门单元的输出值关于输入值
以及在CV里,dy/dx = dx,而不是数学里学到的=dy