反向传播算法基于多元函数链式法则,以下记录多元函数链式法则的证明与反向传播算法的实战推演。
多元复合函数的求导法则(多元链式法则) 定义如果函数$u=\varphi(t)$及$v=\psi(t)$都在点$t$可导,函数$z = f(u,v)$在对应点$(u,v)$具有连续偏导数(重点),那么复合函数$z = f[\varphi(t),\psi(t)]$在点$t$可导,且有:
$\displaystyle \frac{\mathrm{d}z}{\mathrm{d}t} = \frac{\partial z}{\partial u}\frac{\mathrm{d}u}{\mathrm{d}t}+ \frac{\partial z}{\partial v}\frac{\mathrm{d}v}{\mathrm{d}t} $
证明设$t$获得增量$\Delta t$,此时$u = \varphi(t),v = \psi(t)$的对应增量为$\Delta u,\Delta v$,由此,$z=f(u,v)$获得增量$\Delta z$。因为函数$z = f(u,v)$在点$(u,v)$有连续偏导数,于是全增量$\Delta z$可表示为(全微分的充分条件):
$\displaystyle\Delta z = \frac{\partial z}{\partial u}\Delta u+ \frac{\partial z}{\partial v}\Delta v+\varepsilon_1\Delta u+\varepsilon_2\Delta v$
这里有,当$\Delta u\to 0,\Delta v\to 0$时,有$\varepsilon_1\to0,\varepsilon_2\to 0$。
上式两边各除以$\Delta t$,得:
$\displaystyle\frac{\Delta z}{\Delta t} = \frac{\partial z}{\partial u}\frac{\Delta u}{\Delta t}+ \frac{\partial z}{\partial v}\frac{\Delta v}{\Delta t}+\varepsilon_1\frac{\Delta u}{\Delta t}+\varepsilon_2\frac{\Delta v}{\Delta t}$
于是,取极限$\Delta t\to0$,就有:
$\displaystyle \frac{\mathrm{d}z}{\mathrm{d}t} = \frac{\partial z}{\partial u}\frac{\mathrm{d}u}{\mathrm{d}t}+ \frac{\partial z}{\partial v}\frac{\mathrm{d}v}{\mathrm{d}t} $
得证。(主要功劳在于它有连续偏导数,于是有全微分,才能用来加)
而神经网络中的多元函数大多是仿射函数(Softmax不是,但是也符合可微条件),符合上述全微分的充分条件,所以可以使用反向传播来计算所有参数的梯度。
反向传播算法的实例推演反向传播的过程与公式推导(点击链接)不难,主要就是运用上述的多元函数链式法则。
但是看完原理后,代码如何实现呢?有个疑问就是,第n层的一个参数$w$,要使用第n+1层所有相关导数的累加,假设需要累加$n$次;而第n+1层的相关导数,又要第n+2层的所有相关导数的相关导数的累加,假设累加$m$次。也就是说,对于第n层的这个参数的导数,仅通过两层就要计算$n\times m$次。如此嵌套下去,要进行的加和运算似乎是指数级上升,这样是肯定不行的。可以想到,某些中间结果需要暂存,以防止上述重复计算。以下直接举一个具体的例子来说明。
定义一个全连接网络,规模与各层激活函数如下图所示:
如图所示,神经网络使用MSE来作为损失函数。网络使用随机梯度下降,即每次传入一个样本。实际上,使用MSE时,批量梯度下降每次更新的梯度是批次中各个样本点梯度的简单相加,与随机梯度下降相比并没有其他复杂操作,所以这里只举随机梯度下降的为例。
每一层的操作都已在图中标出。其中$x\in R^4,y\in R^3$分别是样本的特征向量和标记向量;$h\in R^5,g\in R^6,f\in R^3$分别是输入层、隐层、输出层的输出向量;$w^k,b^k$分别是第$k$层用于仿射运算的矩阵和偏置向量,$i^k$是仿射运算的结果;$\delta(x)$是ReLu激活函数(对向量元素进行的运算),$\sigma(x)$是Softmax激活函数(对向量进行的运算)。
下面开始推算每层参数、中间变量的导数和梯度,式子之前的大写字母表示在程序实现中应该保存的矩阵或向量,以避免重复计算。
首先算损失$L$对$f$的梯度,存入$A$中:
$ \displaystyle A =\frac{\partial L}{\partial f} = \left[ \begin{matrix} \frac{\partial L}{\partial f_1}\\ \frac{\partial L}{\partial f_2}\\ \frac{\partial L}{\partial f_3}\\ \end{matrix} \right] = \left[ \begin{matrix} f_1 - y_1\\ f_2 - y_2\\ f_3 - y_3\\ \end{matrix} \right] = f-y $
再算$f$对$i^3$的导数,由于激活函数使用的是Softmax,每个$i_k$都参与了每个$f_j$的计算,所以是一个雅可比矩阵:
$\displaystyle \begin{aligned} B &= \frac{\partial f}{\partial i^3}= \left[ \begin{matrix} \frac{\partial f_1}{\partial i^3_1}&\frac{\partial f_1}{\partial i^3_2}&\frac{\partial f_1}{\partial i^3_3}\\ \frac{\partial f_2}{\partial i^3_1}&\frac{\partial f_2}{\partial i^3_2}&\frac{\partial f_2}{\partial i^3_3}\\ \frac{\partial f_3}{\partial i^3_1}&\frac{\partial f_3}{\partial i^3_2}&\frac{\partial f_3}{\partial i^3_3}\\ \end{matrix} \right]= \left[ \begin{matrix} \frac{\partial \sigma_1(i^3)}{\partial i^3_1}&\frac{\partial \sigma_1(i^3)}{\partial i^3_2}&\frac{\partial \sigma_1(i^3)}{\partial i^3_3}\\ \frac{\partial \sigma_2(i^3)}{\partial i^3_1}&\frac{\partial \sigma_2(i^3)}{\partial i^3_2}&\frac{\partial \sigma_2(i^3)}{\partial i^3_3}\\ \frac{\partial \sigma_3(i^3)}{\partial i^3_1}&\frac{\partial \sigma_3(i^3)}{\partial i^3_2}&\frac{\partial \sigma_3(i^3)}{\partial i^3_3}\\ \end{matrix} \right]\\& =\left[ \begin{matrix} f_1-f_1f_1&-f_1f_2&-f_1f_3\\ -f_1f_2&f_2-f_2f_2&-f_2f_3\\ -f_1f_3&-f_2f_3&f_3-f_3f_3\\ \end{matrix} \right] =\text{diag}(f)-ff^T \end{aligned} $
于是$L$对$i^3$求梯度就是($\cdot$表示矩阵乘法):