目录
梯度下降
neural network中梯度下降使用方法不变,区别在于有将近million个参数.
最大困难是如何有效计算近百万维的vector, Backpropagation是梯度下降较有效率的算法.
反向传播是求微分计算vector的一种方法,而不是一种新的算法.
梯度下降的计算方法
参数:
$$ \theta = \left\{ {w_{1},w_{2},\cdots,b_{1},b_{2},\cdots} \right\} $$
先选一个初始参数θ^0, 对它计算损失函数的梯度:
$$ \nabla L\left( \theta \right) = \begin{bmatrix} \begin{matrix} {{\partial L( \theta )}/{\partial w_{1}}} \\ {{\partial L( \theta )}/{\partial w_{2}}} \\ \vdots \\ \end{matrix} \\ \begin{matrix} {{\partial L( \theta )}/{\partial b_{1}}} \\ {{\partial L( \theta )}/{\partial b_{2}}} \\ \vdots \\ \end{matrix} \\ \end{bmatrix} $$
更新参数:
$$ \theta^{1} = ~\theta^{0} - \eta\nabla L\left( \theta^{0} \right) $$
链式法则
Backpropagation主要原理为Chain Rule(链式法则):
$$ x = g\left( s \right),y = h\left( s \right),z = k\left( {x,y} \right)\\ \frac{dz}{ds} = \frac{\partial z}{\partial x}\frac{dx}{ds} + \frac{\partial z}{\partial y}\frac{dy}{ds} $$
神经网络训练
神经网络的损失函数total loss L定义为训练集样本的loss(交叉熵l)之和:
$$ L = {\sum_{n = 1}^{N}l^{n}} $$
单个样本loss为NN输出y与真实样本y hat距离:
用L对某一个参数w做偏微分, 即所有样本的交叉熵对参数w的偏微分累计求和:
$$ \frac{\partial L\left( \theta \right)}{\partial w} = {\sum_{n = 1}^{N}\frac{\partial l^{n}\left( \theta \right)}{\partial w}} $$
只需考虑一笔𝜕l/𝜕w怎样求:
先考虑一个神经元,先拿出第一层的neuron,输入为外界input x1与x2,通过这个neuron,得到z:
$$ z = x_{1}w_{1} + x_{2}w_{2} + b $$
然后经过激活函数输出,和很多其他神经元操作,最终输出 y1和y2.
单个样本的损失𝜕l/𝜕w计算: 按照链式法则,拆分成两项分别计算.
$$ \frac{\partial l}{\partial w} = \frac{\partial z}{\partial w}\frac{\partial l}{\partial z} $$
Forward pass: 计算前面这一项(较简单)的过程;Backward pass: 计算后项(较复杂)的过程.
Forward pass
$$ \frac{\partial z}{\partial w_{1}} = x_{1},\\ \frac{\partial z}{\partial w_{2}} = x_{2} $$
w前输入是什么,微分后的值就是什么.
1. input layer作为neuron的输入时,w1前面连接x1,微分值就是x1;前面连接x2,微分值就是x2.
2. hidden layer作为输入时,即输入前一层neuron的output,于是微分值就是前一层的z经过激活函数之后输出的值(下图中的数据是假定激活函数为sigmoid function得到的)
Backward pass
解释一
依旧假设激活函数是sigmoid function. z通过激活得到a,这个神经元的输出是:
$$ a = \sigma\left( z \right) $$
接下来这个a乘weight ,再加其他项值得到z',它是下一个激活函数的输入,然后a乘上另一个weight ,再加其他项值得到z''.
可以再做一次链式求导拆解:
$$ \frac{\partial l}{\partial z} = \frac{\partial a}{\partial z}\frac{\partial l}{\partial a} $$
其中第一项𝜕a/𝜕z即激活函数(sigmoid)的微分:
$$ \frac{\partial a}{\partial z} = \sigma'\left( z \right) $$
sigmoid微分图像:
第二项𝜕l/𝜕a, 观察l与a的关系:
下一层有两个神经元, z'与z''代表的不是求导的意思, 只是用以区分. z' z''后面分别连接到两个神经元, 但l是同一个l(前面这个神经元的).
a会影响z'和z'',而z'和z''会影响l,所以通过链式法则可以得到:
$$ \frac{\partial l}{\partial a} = \frac{\partial z'}{\partial a}\frac{\partial l}{\partial z'} + \frac{\partial z''}{\partial a}\frac{\partial l}{\partial z''} $$
每项的前一个因子较简单(后一项等待会儿套娃):
$$ z^{'} = aw_{3} + \cdots\\ \frac{\partial z^{'}}{\partial a} = w_{3}\\ \frac{\partial z^{''}}{\partial a} = w_{4} $$
整理可得𝜕l/𝜕z的微分:
$$ \frac{\partial l}{\partial z} = \sigma'\left( z \right)\left\lbrack {w_{3}\frac{\partial l}{\partial z'} + w_{4}\frac{\partial l}{\partial z''}} \right\rbrack $$
解释二
假设另一个neuron(非原network中, 与原方向相反, input含右侧的𝜕l/𝜕z', 𝜕l/𝜕z''), input 中𝜕l/𝜕z'乘上w3,input 𝜕l/𝜕z''乘上w4,它们两个相加再乘上激活函数的微分, 得到输出即𝜕l/𝜕z.
此时𝜕l/𝜕z的微分与上式相同:
$$ \frac{\partial l}{\partial z} = \sigma'\left( z \right)\left\lbrack {w_{3}\frac{\partial l}{\partial z'} + w_{4}\frac{\partial l}{\partial z''}} \right\rbrack $$
其中σ'(z)为常数, 因为z已由forward pass给定.
这个神经元不是把input进行non-linear转换,而是直接乘上一个常数输出. 因此画成三角形,代表它跟圆形的neuron的运作方式不同. (三角形像电路的运算放大器op-amp,也是乘一个常数. )
接着需要计算每项后一个因子𝜕l/𝜕w1, 𝜕l/𝜕w2,分两种情况考虑.
情况1: 后接输出层
当蓝色神经元是hidden layer最后一层,连接在后两个红色神经元是输出层,它的输出为整个network的输出,这个时候计算就比较简单, 直接代入y:
$$ \frac{\partial l}{\partial z'} = \frac{\partial y_{1}}{\partial z'}\frac{\partial l}{\partial y_{1}}\\ \frac{\partial l}{\partial z''} = \frac{\partial y_{2}}{\partial z''}\frac{\partial l}{\partial y_{2}} $$
其中𝜕 y1/𝜕z'就是输出层激活函数 (softmax) 对z'的偏微分.
而𝜕l/𝜕y1, 取决于损失函数定义(y和y hat之间距离),交叉熵,或均方误差mean square error. 此时可得𝜕l/𝜕w1, 𝜕l/𝜕w2.
情况2: 后接隐藏层
当红色neuron并不是整个network的output,z'经过红色neuron的激活函数得到a',然后输出的a'和w5、w6相乘并加上一堆其他东西分别得到z_a和z_b,z_a和z_b再输入其他激活函数, 如下图所示:
计算𝜕l/𝜕z', 𝜕l/𝜕z'', 需要知道𝜕l/𝜕z_a, 𝜕l/𝜕z_b;
当知道𝜕l/𝜕z', 𝜕l/𝜕z''后, 能算出𝜕l/𝜕z. 如下图所示:
只要不是输出层, 就借助下一层从后往前算, 这时的计算量其实不是很大(参照解释二, 建立一个反向的神经网络右边两个微分值相加通过op-amp,乘上放大系数得到左边的输出):
注:Backward pass如果正向做,每计算一个,需要把该neuron后面所有的计算一遍,重复运算;而反向做Backward pass,把这些调用都变成代入“值”的过程,因此可以直接计算出结果.
总结
Forward pass,每个neuron激活函数的输出,就是它所连接的weight的𝜕z/𝜕w.
Backward pass,建一个与原来方向相反的神经网络,三角形neuron的输出就是𝜕l/𝜕z.
把forward pass得到和backward pass得到结果的相乘, 即可得:
$$ \frac{\partial z}{\partial w}\frac{\partial l}{\partial z} = \frac{\partial l}{\partial w} $$