正向传播、反向传播和计算图
使用数学来描述正向传播和反向传播。具体来说,我们将以带 (L2) 范数正则化的含单隐藏层的多层感知机为样例模型解释正向传播和反向传播。
正向传播
正向传播(forward propagation
)是指对神经网络沿着从输入层到输出层的顺序,依次计算并存储模型的中间变量(包括输出)
样本:(oldsymbol{x} in mathbb{R}^d)
中间变量:$$oldsymbol{z} = oldsymbol{W}^{(1)} oldsymbol{x},$$
隐藏层变量(加激活函数后的):
[oldsymbol{h} = phi (oldsymbol{z}).
]
输出层变量:
[oldsymbol{o} = oldsymbol{W}^{(2)} oldsymbol{h}.
]
单个数据样本的损失项:
[L = ell(oldsymbol{o}, y).
]
正则化项:
[s = frac{lambda}{2} left(|oldsymbol{W}^{(1)}|_F^2 + |oldsymbol{W}^{(2)}|_F^2
ight),
]
模型在给定的数据样本上带正则化的损失:
[J = L + s.
]
这里的损失加上了权重衰减
将(J)称为有关给定数据样本的目标函数
反向传播
反向传播(back-propagation
)指的是计算神经网络参数梯度的方法,反向传播依据微积分中的链式法则,沿着从输出层到输入层的顺序,依次计算并存储目标函数有关神经网络各层的中间变量以及参数的梯度.对输入或输出(mathsf{X}, mathsf{Y}, mathsf{Z})为任意形状张量的函数(mathsf{Y}=f(mathsf{X}))和(mathsf{Z}=g(mathsf{Y})),通过链式法则
[frac{partial mathsf{Z}}{partial mathsf{X}} = ext{prod}left(frac{partial mathsf{Z}}{partial mathsf{Y}}, frac{partial mathsf{Y}}{partial mathsf{X}}
ight),
]
参数:(oldsymbol{W}^{(1)}),(oldsymbol{W}^{(2)})
反向传播的目标:(partial J/partial oldsymbol{W}^{(1)})和(partial J/partial oldsymbol{W}^{(2)})
- 分别计算目标函数(J=L+s)有关损失项(L)和正则项(s)的梯度
[frac{partial J}{partial L} = 1, quad frac{partial J}{partial s} = 1.
]
- 依据链式法则计算目标函数有关输出层变量的梯度(partial J/partial oldsymbol{o} in mathbb{R}^q):
[frac{partial J}{partial oldsymbol{o}}
= ext{prod}left(frac{partial J}{partial L}, frac{partial L}{partial oldsymbol{o}}
ight)
= frac{partial L}{partial oldsymbol{o}}.
]
- 计算正则项有关两个参数的梯度:
[frac{partial s}{partial oldsymbol{W}^{(1)}} = lambda oldsymbol{W}^{(1)},quadfrac{partial s}{partial oldsymbol{W}^{(2)}} = lambda oldsymbol{W}^{(2)}.
]
- 计算最靠近输出层的模型参数的梯度(partial J/partial oldsymbol{W}^{(2)} in mathbb{R}^{q imes h})
[frac{partial J}{partial oldsymbol{W}^{(2)}}
= ext{prod}left(frac{partial J}{partial oldsymbol{o}}, frac{partial oldsymbol{o}}{partial oldsymbol{W}^{(2)}}
ight) + ext{prod}left(frac{partial J}{partial s}, frac{partial s}{partial oldsymbol{W}^{(2)}}
ight)
= frac{partial J}{partial oldsymbol{o}} oldsymbol{h}^ op + lambda oldsymbol{W}^{(2)}.
]
- 沿着输出层向隐藏层继续反向传播,隐藏层变量的梯度(partial J/partial oldsymbol{h} in mathbb{R}^h)
[frac{partial J}{partial oldsymbol{h}}
= ext{prod}left(frac{partial J}{partial oldsymbol{o}}, frac{partial oldsymbol{o}}{partial oldsymbol{h}}
ight)
= {oldsymbol{W}^{(2)}}^ op frac{partial J}{partial oldsymbol{o}}.
]
- 由于激活函数(phi)是按元素运算的,中间变量(oldsymbol{z})的梯度(partial J/partial oldsymbol{z} in mathbb{R}^h)的计算需要使用按元素乘法符(odot):
[frac{partial J}{partial oldsymbol{z}}
= ext{prod}left(frac{partial J}{partial oldsymbol{h}}, frac{partial oldsymbol{h}}{partial oldsymbol{z}}
ight)
= frac{partial J}{partial oldsymbol{h}} odot phi'left(oldsymbol{z}
ight).
]
- 最终,我们可以得到最靠近输入层的模型参数的梯度(partial J/partial oldsymbol{W}^{(1)} in mathbb{R}^{h imes d})。依据链式法则,得到
[frac{partial J}{partial oldsymbol{W}^{(1)}}
= ext{prod}left(frac{partial J}{partial oldsymbol{z}}, frac{partial oldsymbol{z}}{partial oldsymbol{W}^{(1)}}
ight) + ext{prod}left(frac{partial J}{partial s}, frac{partial s}{partial oldsymbol{W}^{(1)}}
ight)
= frac{partial J}{partial oldsymbol{z}} oldsymbol{x}^ op + lambda oldsymbol{W}^{(1)}.
]
训练深度学习模型
正向传播和反向传播之间相互依赖
- 一方面,正向传播的计算可能依赖于模型参数的当前值,而这些模型参数是在反向传播的梯度计算后通过优化算法迭代的。
- 另一方面,反向传播的梯度计算可能依赖于各变量的当前值,而这些变量的当前值是通过正向传播计算得到的。举例来说,参数梯度(partial J/partial oldsymbol{W}^{(2)} = (partial J / partial oldsymbol{o}) oldsymbol{h}^ op + lambda oldsymbol{W}^{(2)})的计算需要依赖隐藏层变量的当前值(oldsymbol{h})。这个当前值是通过从输入层到输出层的正向传播计算并存储得到的。