Backpropagation
神经网络中,我们利用梯度下降法来对损失函数进行优化,这在神经元数量不多的时候很有效。但是深层神经网络中,有上百万的参数需要调整,单纯使用梯度下降法可以算,但几乎不可能算完。因此我们需要更有效的方法来优化损失函数,这也就引出了反向传播(backpropagation)
链式法则
下图是多层神经网络的一个模型,现在我们要对损失函数L进行优化,即对其中每个参数求偏导。以图中三角部分为例,展开:
假设该部分的模型函数如下:
z = w 1 x 1 + w 2 x 2 + b z=w_1x_1+w_2x_2+b z=w1x1+w2x2+b
z是即将输入给激活函数的值, w 1 w_1 w1是 x 1 x_1 x1的权重, w 2 w_2 w2是 x 2 x_2 x2的权重,b是偏置值,如下:
根据链式法则,我们将损失函数(这里的C是整个损失函数中的某一个加项)对某一个
w
w
w的偏导,拆成了上图中的形式。
前/后向传播
就像上图中标出的那样,我们把 ∂ z ∂ w \frac{\partial z}{\partial w} ∂w∂z,称为前向传播项;把 ∂ C ∂ z \frac{\partial C}{\partial z} ∂z∂C,称为后向传播项。
1、前向传播
之所以 ∂ z ∂ w \frac{\partial z}{\partial w} ∂w∂z称为前向传播,是因为它的值只和与参数直接相连的输入有关。例如在上图中, ∂ z ∂ w 1 = x 1 \frac{\partial z}{\partial w_1} = x_1 ∂w1∂z=x1, ∂ z ∂ w 2 = x 2 \frac{\partial z}{\partial w_2} = x_2 ∂w2∂z=x2
2、反向传播
∂ C ∂ z \frac{\partial C}{\partial z} ∂z∂C是很复杂的,因为C和z并不直接相关,我们用链式法则对其可以继续分解(假设经过激活函数后的输出可表示为 a = σ ( z ) a=\sigma(z) a=σ(z)):
∂ C ∂ z = ∂ a ∂ z ∂ C ∂ a \frac{\partial C}{\partial z}=\frac{\partial a}{\partial z}\frac{\partial C}{\partial a} ∂z∂C=∂z∂a∂a∂C
其中 ∂ a ∂ z \frac{\partial a}{\partial z} ∂z∂a就是激活函数在z处的值,可以简单的表示为 σ ′ ( z ) \sigma^{'}(z) σ′(z)。而 ∂ C ∂ a \frac{\partial C}{\partial a} ∂a∂C又要求我们继续进行链式展开:
∂ C ∂ a = ∂ z ′ ∂ a ∂ C ∂ z ′ + ∂ z ′ ′ ∂ a ∂ C ∂ z ′ ′ \frac{\partial C}{\partial a}=\frac{\partial z^{'}}{\partial a}\frac{\partial C}{\partial z^{'}}+\frac{\partial z^{''}}{\partial a}\frac{\partial C}{\partial z^{''}} ∂a∂C=∂a∂z′∂z′∂C+∂a∂z′′∂z′′∂C
很容易发现这是一个迭代的过程,因为我们总需要继续求解下一层的偏导数。这里我们先假设 ∂ C ∂ z ′ \frac{\partial C}{\partial z^{'}} ∂z′∂C和 ∂ C ∂ z ′ ′ \frac{\partial C}{\partial z^{''}} ∂z′′∂C已知,那么可以把最初的式子改写为:
∂ C ∂ z = σ ′ ( z ) [ w 3 ∂ C ∂ z ′ + w 4 ∂ C ∂ z ′ ′ ] \frac{\partial C}{\partial z}=\sigma^{'}(z)\left[w_3 \frac{\partial C}{\partial z^{'}} + w_4 \frac{\partial C}{\partial z^{''}} \right] ∂z∂C=σ′(z)[w3∂z′∂C+w4∂z′′∂C]
下面这张图能够让你更好的理解,为什么它被称为“反向”传播。
如何继续计算
1、单隐层
如果,上图中红色的就是output层,那么我们上面给出的假设已知是成立的,因为此时:
∂ C ∂ z ′ = ∂ y 1 ∂ z ′ ∂ C ∂ y 1 \frac{\partial C}{\partial z^{'}}=\frac{\partial y_1}{\partial z^{'}}\frac{\partial C}{\partial y_1} ∂z′∂C=∂z′∂y1∂y1∂C
∂ C ∂ z ′ ′ = ∂ y 2 ∂ z ′ ′ ∂ C ∂ y 2 \frac{\partial C}{\partial z^{''}}=\frac{\partial y_2}{\partial z^{''}}\frac{\partial C}{\partial y_2} ∂z′′∂C=∂z′′∂y2∂y2∂C
y与z之间的关系,由激活函数得出;而C与y之间的关系,正是你定义的损失函数,这些偏导都是已知的。
2、多隐层
那如果红色的之后还有很多层,我们其实只需要继续迭代,直到达到output层即可。我们可以想象成有一个逆向的神经网络,其优化过程如下:
总结
BP算法分为三个步骤(对某一个参数):
- forward pass。正向求取各个 ∂ z ∂ w = a \frac{\partial z}{\partial w}=a ∂w∂z=a
- backward pass。反向求取各个 ∂ C ∂ z \frac{\partial C}{\partial z} ∂z∂C
- combine。 a × ∂ C ∂ z = ∂ C ∂ w a \times \frac{\partial C}{\partial z} = \frac{\partial C}{\partial w} a×∂z∂C=∂w∂C