提交 81be9e53 编写于 作者: A Aston Zhang

2pass backprop

上级 4a4b71f9
# 正向传播、反向传播和计算图
前面几节里我们使用了小批量随机梯度下降的优化算法来训练模型。在实现中,我们只提供了模型的正向传播(forward propagation)的计算,即对输入计算模型输出,然后通过`autograd`模块来调用系统自动生成的`backward`函数计算梯度。自动求梯度极大简化了深度学习模型训练算法的实现。除了利用正向传播的计算结果以外,深度学习模型的梯度计算还需要使用反向传播(back-propagation)算法。这一节我们将使用数学和计算图两个方式来描述正向传播和反向传播。具体地,我们将以带$L_2$范数正则化的单隐藏层感知机为例解释正向传播和反向传播。
前面几节里我们使用了小批量随机梯度下降的优化算法来训练模型。在实现中,我们只提供了模型的正向传播(forward propagation)的计算,即对输入计算模型输出,然后通过`autograd`模块来调用系统自动生成的`backward`函数计算梯度。基于反向传播算法(back-propagation)的自动求梯度极大简化了深度学习模型训练算法的实现。这一节我们将使用数学和计算图(computational graph)两个方式来描述正向传播和反向传播。具体地,我们将以带$L_2$范数正则化的单隐藏层感知机为样例模型解释正向传播和反向传播。
## 正向传播
正向传播是指对神经网络沿着从输入层到输出层的顺序,依次计算并存储模型中间变量。假设输入是一个特征为$\boldsymbol{x} \in \mathbb{R}^d$的样本。为了简单起见忽略掉隐藏层的偏差项,我们计算中间变量
正向传播是指对神经网络沿着从输入层到输出层的顺序,依次计算并存储模型的中间变量(包括输出)。为简单起见,假设输入是一个特征为$\boldsymbol{x} \in \mathbb{R}^d$的样本,且不考虑偏差项,那么中间变量
$$\boldsymbol{z} = \boldsymbol{W}^{(1)} \boldsymbol{x},$$
其中$\boldsymbol{W}^{(1)} \in \mathbb{R}^{h \times d}$是该隐藏层的模型参数。将中间变量$\boldsymbol{z} \in \mathbb{R}^h$应用按元素操作的激活函数$\phi$后,我们将得到向量长度为$h$的隐藏层变量
其中$\boldsymbol{W}^{(1)} \in \mathbb{R}^{h \times d}$是隐藏层的权重参数。把中间变量$\boldsymbol{z} \in \mathbb{R}^h$输入按元素操作的激活函数$\phi$后,我们将得到向量长度为$h$的隐藏层变量
$$\boldsymbol{h} = \phi (\boldsymbol{z}).$$
隐藏变量$\boldsymbol{h} \in \mathbb{R}^h$也是一个中间变量。通过输出层模型参数$\boldsymbol{W}^{(2)} \in \mathbb{R}^{q \times h}$可以得到向量长度为$q$的输出层变量
隐藏变量$\boldsymbol{h}$也是一个中间变量。假设输出层参数只有权重$\boldsymbol{W}^{(2)} \in \mathbb{R}^{q \times h}$,我们可以得到向量长度为$q$的输出层变量
$$\boldsymbol{o} = \boldsymbol{W}^{(2)} \boldsymbol{h}.$$
......@@ -24,7 +24,7 @@ $$L = \ell(\boldsymbol{o}, y).$$
$$s = \frac{\lambda}{2} \left(\|\boldsymbol{W}^{(1)}\|_F^2 + \|\boldsymbol{W}^{(2)}\|_F^2\right),$$
其中矩阵的Frobenius范数等价于将它拉升成向量后计算$L_2$范数。最终,模型在给定的数据样本上带正则化的损失为
其中矩阵的Frobenius范数等价于将矩阵压成向量后计算$L_2$范数。最终,模型在给定的数据样本上带正则化的损失为
$$J = L + s.$$
......@@ -33,24 +33,24 @@ $$J = L + s.$$
## 正向传播的计算图
我们通常绘制计算图来可视化运算符和变量在计算中的依赖关系。图3.6描述上面模型正向传播的计算图。它的左边下角是输入,右上角是输出。可以看到箭头方向主要是向右(向左箭头可以通过适当移动变量和运算符位置来修改),所以称为正向传播
我们通常绘制计算图来可视化运算符和变量在计算中的依赖关系。图3.6绘制了本节中样例模型正向传播的计算图。其中左下角是输入,右上角是输出。可以看到,图中箭头方向大多是向右和向上
![正向传播的计算图。其中方框代表变量,圆圈代表运算符,箭头表示依赖关系。](../img/forward.svg)
![正向传播的计算图。其中方框代表变量,圆圈代表运算符,箭头表示从输入到输出之间的依赖关系。](../img/forward.svg)
## 反向传播
反向传播依据微积分中的链式法则,沿着从输出层到输入层的顺序,依次计算并存储目标函数有关神经网络各层的中间变量以及参数的梯度。对输入输出$\mathsf{X}, \mathsf{Y}, \mathsf{Z}$为任意形状张量的函数$\mathsf{Y}=f(\mathsf{X})$和$\mathsf{Z}=g(\mathsf{Y})$,通过链式法则,我们有
反向传播指的是计算神经网络参数梯度的方法。总的来说,反向传播依据微积分中的链式法则,沿着从输出层到输入层的顺序,依次计算并存储目标函数有关神经网络各层的中间变量以及参数的梯度。对输入输出$\mathsf{X}, \mathsf{Y}, \mathsf{Z}$为任意形状张量的函数$\mathsf{Y}=f(\mathsf{X})$和$\mathsf{Z}=g(\mathsf{Y})$,通过链式法则,我们有
$$\frac{\partial \mathsf{Z}}{\partial \mathsf{X}} = \text{prod}\left(\frac{\partial \mathsf{Z}}{\partial \mathsf{Y}}, \frac{\partial \mathsf{Y}}{\partial \mathsf{X}}\right),$$
这里$\text{prod}$根据输入的形状选择相应的乘法运算符
其中$\text{prod}$运算符将根据两个输入的形状,在必要的操作(例如转置和互换输入位置)后对两个输入做乘法
因为样例模型的参数是$\boldsymbol{W}^{(1)}$和$\boldsymbol{W}^{(2)}$,所以反向传播的目标是计算$\partial J/\partial \boldsymbol{W}^{(1)}$和$\partial J/\partial \boldsymbol{W}^{(2)}$。接下来使用链式法则来反溯前向传播来依次计算每个中间变量的导数。首先,我们计算目标函数$J=L+s$有关损失项$L$和有关正则项$s$的梯度
回顾一下本节中样例模型,它的参数是$\boldsymbol{W}^{(1)}$和$\boldsymbol{W}^{(2)}$,因此反向传播的目标是计算$\partial J/\partial \boldsymbol{W}^{(1)}$和$\partial J/\partial \boldsymbol{W}^{(2)}$。我们将应用链式法则依次计算各中间变量和参数的梯度,其计算次序与前向传播中相应中间变量的计算次序相反。首先,分别计算目标函数$J=L+s$有关损失项$L$和正则项$s$的梯度
$$\frac{\partial J}{\partial L} = 1, \quad \frac{\partial J}{\partial s} = 1.$$
其次,我们依据链式法则计算目标函数有关输出层变量的梯度$\partial J/\partial \boldsymbol{o} \in \mathbb{R}^q$:
其次,依据链式法则计算目标函数有关输出层变量的梯度$\partial J/\partial \boldsymbol{o} \in \mathbb{R}^q$:
$$
\frac{\partial J}{\partial \boldsymbol{o}}
......@@ -59,7 +59,7 @@ $$
$$
接下来,我们可以很直观地计算出正则项有关两个参数的梯度:
接下来,计算正则项有关两个参数的梯度:
$$\frac{\partial s}{\partial \boldsymbol{W}^{(1)}} = \lambda \boldsymbol{W}^{(1)},\quad\frac{\partial s}{\partial \boldsymbol{W}^{(2)}} = \lambda \boldsymbol{W}^{(2)}.$$
......@@ -82,7 +82,7 @@ $$
$$
其中,激活函数$\phi$是按元素操作的。中间变量$\boldsymbol{z}$的梯度$\partial J/\partial \boldsymbol{z} \in \mathbb{R}^h$的计算需要使用按元素乘法符$\odot$:
由于激活函数$\phi$是按元素操作的,中间变量$\boldsymbol{z}$的梯度$\partial J/\partial \boldsymbol{z} \in \mathbb{R}^h$的计算需要使用按元素乘法符$\odot$:
$$
\frac{\partial J}{\partial \boldsymbol{z}}
......@@ -98,24 +98,28 @@ $$
= \frac{\partial J}{\partial \boldsymbol{z}} \boldsymbol{x}^\top + \lambda \boldsymbol{W}^{(1)}.
$$
## 反向传播的计算图
## 训练深度学习模型
图3.7完整描述了正向传播和反向传播的的计算图。可以看到在反向传播中我们使用了正向传播中计算得到的中间变量来避免重复计算。这个重用导致正向传播结束后不能立即释放中间变量内存,这是为什么训练要比预测占用更多内存的一个主要原因。其次,这些中间变量的个数跟网络层数线性相关,每个变量的大小跟批量大小和输入大小也是线性相关,它们是导致深度神经网络使用较大批量大小训练时超内存的主要原因
在训练深度学习模型时,正向传播和反向传播之间相互依赖。下面我们仍然以本节中的样例模型分别阐述它们之间的依赖关系
![正向传播和反向传播的计算图,其中正向传播部分在阴影框中。下半部是各个中间变量关于$L$的导数,上半部则是关于$s$和$J$的导数。](../img/backward.svg)
一方面,正向传播的计算可能依赖于模型参数的当前值。而这些模型参数是在反向传播的梯度计算后通过优化算法迭代的。例如,计算正则化项$s = (\lambda/2) \left(\|\boldsymbol{W}^{(1)}\|_F^2 + \|\boldsymbol{W}^{(2)}\|_F^2\right)$依赖模型参数$\boldsymbol{W}^{(1)}$和$\boldsymbol{W}^{(2)}$的当前值。而这些当前值是优化算法最近一次根据反向传播算出梯度后迭代得到的。
另一方面,反向传播的梯度计算可能依赖于各变量的当前值。而这些变量的当前值是通过正向传播计算得到的。举例来说,参数梯度$\partial J/\partial \boldsymbol{W}^{(2)} = (\partial J / \partial \boldsymbol{o}) \boldsymbol{h}^\top + \lambda \boldsymbol{W}^{(2)}$的计算需要依赖隐藏层变量的当前值$\boldsymbol{h}$。这个当前值是通过从输入层到输出层的正向传播计算并存储得到的。
因此,在模型参数初始化完成后,我们交替地进行正向传播和反向传播,并根据反向传播计算的梯度迭代模型参数。既然我们在反向传播中使用了正向传播中计算得到的中间变量来避免重复计算,那么这个重用也导致正向传播结束后不能立即释放中间变量内存。这也是训练要比预测占用更多内存的一个重要原因。另外需要指出的是,这些中间变量的个数跟网络层数线性相关,每个变量的大小跟批量大小和输入个数也是线性相关的,它们是导致较深的神经网络使用较大批量训练时更容易超内存的主要原因。
## 小结
* 反向传播沿着从输出层到输入层的顺序,依次计算并存储神经网络中间变量和参数的梯度。
* 正向传播沿着从输入层到输出层的顺序,依次计算并存储神经网络的中间变量。
* 正向传播和反向传播相互依赖。
* 反向传播沿着从输出层到输入层的顺序,依次计算并存储神经网络中间变量和参数的梯度。
* 在训练深度学习模型时,正向传播和反向传播相互依赖。
## 练习
* 对于具体的激活函数ReLU或sigmoid,如何计算它们的导数
* 试着加上偏差项后再求导。
* 在本节样例模型的隐藏层和输出层中添加偏差参数,修改计算图以及正向传播和反向传播的数学表达式
## 扫码直达[讨论区](https://discuss.gluon.ai/t/topic/3710)
......
......@@ -123,7 +123,7 @@ $$H\left(\boldsymbol y^{(i)}, \boldsymbol {\hat y}^{(i)}\right ) = -\sum_{j=1}^q
假设训练数据集的样本数为$n$,交叉熵损失函数定义为
$$\ell(\boldsymbol{\Theta}) = \frac{1}{n} \sum_{i=1}^n H\left(\boldsymbol y^{(i)}, \boldsymbol {\hat y}^{(i)}\right ),$$
其中$\boldsymbol{\Theta}$代表模型参数。同样地,如果每个样本只有一个标签,那么交叉熵损失可以简写成$\ell(\boldsymbol{\Theta}) = -\frac 1n \sum_{i=1}^n \log \hat y_{y^{(i)}}^{(i)}$。从另一个角度来看,我们知道最小化$\ell(\boldsymbol{\Theta})$等价于最大化$\exp(-n\ell(\boldsymbol{\Theta}))=\prod_{i=1}^n \hat y_{y^{(i)}}^{(i)}$,即最小化交叉熵损失函数等价于最大化训练数据集所有标签类别的联合预测概率。
其中$\boldsymbol{\Theta}$代表模型参数。同样地,如果每个样本只有一个标签,那么交叉熵损失可以简写成$\ell(\boldsymbol{\Theta}) = -(1/n) \sum_{i=1}^n \log \hat y_{y^{(i)}}^{(i)}$。从另一个角度来看,我们知道最小化$\ell(\boldsymbol{\Theta})$等价于最大化$\exp(-n\ell(\boldsymbol{\Theta}))=\prod_{i=1}^n \hat y_{y^{(i)}}^{(i)}$,即最小化交叉熵损失函数等价于最大化训练数据集所有标签类别的联合预测概率。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册