前向传播
- 前向传播(forward propagation或forward pass) 指的是:按顺序(从输入层到输出层)计算和存储神经网络中每层的结果。
为了搞清楚前向传播是如何实现的,我们以简单的例子作为切入点,假设输入的样本是 \(X\in R^{d×1}\) ,隐藏层不包括偏置项 \(b\) ,那么中间变量就是:
\[z = W^{(1)}X
\]
其中 \(W^{(1)}\in R^{h×d}\) 是隐藏层的权重参数。 将中间变量 \(z\in R^{h×1}\) 通过激活函数 \(ϕ\) 后, 我们得到长度为 \(h\) 的隐藏激活向量:
\[h=ϕ(z)
\]
隐藏变量 \(h\) 也是一个中间变量。 假设输出层的参数只有权重 \(W^{(2)}\in R^{q×h}\) , 我们可以得到输出层变量,它是一个长度为 \(q\) 的向量:
\[o=W^{(2)}h
\]
假设损失函数为 \(l\) ,样本标签为 \(y\) ,我们可以计算单个数据样本的损失项:
\[L=l(o,y)
\]
根据 \(L2\) 正则化的定义,给定超参数 \(λ\) ,正则化项为:
\[s = \frac{\lambda}{2} \left(\|\mathbf{W}^{(1)}\|_F^2 + \|\mathbf{W}^{(2)}\|_F^2\right)
\]
模型在给定数据样本上的正则化损失为:
\[J = L+s
\]
- 如果用计算图来表示我们的前向传播的过程就是:
反向传播
- 反向传播(backward propagation或backpropagation)指的是:计算神经网络参数梯度的方法。简言之,该方法根据微积分中的链式规则,按相反的顺序从输出层到输入层遍历网络。
我们定义高纬张量相乘:
\[\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)
\]
在计算图中的单隐藏层简单网络的参数是 \(W^{(1)}\) 和 \(W^{(2)}\) 。反向传播的目的是计算梯度 \(\partial J / \partial W^{(1)}\) 和 \(\partial J / \partial W^{(2)}\)
应用链式法则, 计算的顺序与前向传播中执行的顺序相反,第一步是计算目标函数 \(J=L+s\) 相对于损失项 \(L\) 和正则项 \(s\) 的梯度。
\[\frac{\partial J}{\partial L} = 1 \; \text{and} \; \frac{\partial J}{\partial s} = 1
\]
根据链式法则计算目标函数关于输出层变量 o 的梯度:
\[\frac{\partial J}{\partial \mathbf{o}}
= \text{prod}\left(\frac{\partial J}{\partial L}, \frac{\partial L}{\partial \mathbf{o}}\right)
= \frac{\partial L}{\partial \mathbf{o}}
\in \mathbb{R}^q\]
计算正则化项的梯度:
\[\frac{\partial s}{\partial \mathbf{W}^{(1)}} = \lambda \mathbf{W}^{(1)}
\; \text{and} \;
\frac{\partial s}{\partial \mathbf{W}^{(2)}} = \lambda \mathbf{W}^{(2)}\]
使用链式法则得出\(\partial J / \partial W^{(2)}\):
\[\frac{\partial J}{\partial \mathbf{W}^{(2)}}= \text{prod}\left(\frac{\partial J}{\partial \mathbf{o}}, \frac{\partial \mathbf{o}}{\partial \mathbf{W}^{(2)}}\right) + \text{prod}\left(\frac{\partial J}{\partial s}, \frac{\partial s}{\partial \mathbf{W}^{(2)}}\right)= \frac{\partial J}{\partial \mathbf{o}} \mathbf{h}^\top + \lambda \mathbf{W}^{(2)}
\]
继续沿着输出层到隐藏层反向传播,得到关于隐藏层输出的梯度 \(\partial J /\partial h \in R^h\):
\[\frac{\partial J}{\partial \mathbf{h}}
= \text{prod}\left(\frac{\partial J}{\partial \mathbf{o}}, \frac{\partial \mathbf{o}}{\partial \mathbf{h}}\right)
= {\mathbf{W}^{(2)}}^\top \frac{\partial J}{\partial \mathbf{o}}\]
由于激活函数 \(ϕ\) 是按元素计算的, 计算中间变量 \(z\) 的梯度 \(∂J/∂z∈Rh\) 需要使用按元素乘法运算符,我们用 \(⊙\) 表示:
\[\frac{\partial J}{\partial \mathbf{z}}
= \text{prod}\left(\frac{\partial J}{\partial \mathbf{h}}, \frac{\partial \mathbf{h}}{\partial \mathbf{z}}\right)
= \frac{\partial J}{\partial \mathbf{h}} \odot \phi'\left(\mathbf{z}\right)\]
根据链式法则,我们得到 \(\partial J/\partial W^{(1)}\)
\[\frac{\partial J}{\partial \mathbf{W}^{(1)}}
= \text{prod}\left(\frac{\partial J}{\partial \mathbf{z}}, \frac{\partial \mathbf{z}}{\partial \mathbf{W}^{(1)}}\right) + \text{prod}\left(\frac{\partial J}{\partial s}, \frac{\partial s}{\partial \mathbf{W}^{(1)}}\right)
= \frac{\partial J}{\partial \mathbf{z}} \mathbf{x}^\top + \lambda \mathbf{W}^{(1)}\]
最后做个总结的话就是:
(1)前向传播在神经网络定义的计算图中按照从输入到输出的顺序计算、存储中间变量。
(2)反向传播按照相反的顺序(从输入到输出层)计算和存储神经网络的中间变量和参数的梯度。
(3)在训练深度学习模型时,前向传播和反向传播是相互依赖的。
(4)训练比预测需要更多的显存和内存。