说在前面的话:由于hexo渲染引擎会把下划线渲染成斜体符号,编辑公式变得格外困难(尽管本地预览一点问题也没有),所以以后下标较多的公式全部用图片代替。
参考资料:neural networks and deep learning
最初我们的网络采用quadratic function作为我们最后的损失函数,但这却带来了一些问题,在neural networks and deep learning的Chapter3中,作者以单个神经元(激励函数为sigmoid、cost function为quadratic function)为例,input为1,desired output为0,观察训练过程发现,当weight和bias初始值比较大时,会出现前150个训练周期cost都维持在较高水平不变化的情况,观察之前的神经网络也会出现类似的问题。
这显然是与我们的期望不符合的,从人类的认知角度来看,我们当然希望cost越大network学习得越快——即cost下降得越快,就好比显微镜观察事物的粗调节,反之即为细调节;从实际训练来看,出现上面的情况意味着我们需要更多的training epoch,只有当epoch数超过某个“阈值”,神经网络才会开始学到东西,这无疑给训练带来了麻烦。
cost下降缓慢的原因
先以单个神经元为例,quadratic cost function分别对weight和bias求导:
$$
\frac{\partial C}{\partial w}=(a-y)\sigma’(z)x=a\sigma’(z)……(1)
$$
$$
\frac{\partial C}{\partial b}=(a-y)\sigma’(z)=a\sigma’(z)……(2)
$$
式中y和x分别为0和1。观察发现两者导函数中都含有σ’(z)项,这里激励函数为sigmoid function,结合该函数的图像可以发现,当z的绝对值很大时,sigmoid function的导函数σ’(z)趋于0,此时梯度下降法近乎失效,weight和bias几乎不变。
之前搭建的神经网络也有这样的问题,结合BP算法的四个公式
$$
\delta^L=\nabla_aC\bigodot\sigma’(z^L)
$$
$$
\delta^l=((w^{l+1})^T\delta^{l+1})\bigodot\sigma’(z^l)
$$
$$
\frac{\partial{C}}{\partial{w^l_{jk}}}=a^{l-1}_k\delta^l_j
$$
$$
\frac{\partial{C}}{\partial{b^l_j}}=\delta^l_j
$$
发现quadratic function对weight和bias的导函数同样涉及到了σ’(z)项,原因此时就很清晰了。
cross-entropy function的来源
面对上面的问题,显然有两个解决的大方向,一是更改activation function,使得导数不会出现上面的情况,比如ReLU、Leaky ReLU等,对于这样的线性变换,quadratic cost function就不会有这样的问题;二是更改cost function,cross-entropy function就是这样的方法。
既然问题出在σ’(z)这一项上面,就想办法使得cost function求导之后不含这项,仍然先以单个neuron为例,结合(2)式,我们期望
$$
\frac{\partial C}{\partial b}=(a-y)……(3)
$$
新的cost function对b求导后有
$$
\frac{\partial C}{\partial b}=\frac{\partial C}{\partial a}\sigma’(z)
$$
这里激励函数仍为sigmoid函数,所以有
$$
\sigma’(z)=\sigma(z)(1-\sigma(z))=a(1-a)
$$
因此
$$
\frac{\partial C}{\partial b}=\frac{\partial C}{\partial a}a(1-a)
$$
结合(3)式,得到
$$
\frac{\partial C}{\partial a}=\frac{a-y}{a(1-a)}
$$
两边对a积分,得到
$$
C=-[y\ln a+(1-y)\ln(1-a)]+const
$$
对于整个training set的多个input则写作
$$
C=-\frac{1}{n}\sum_x[y\ln a+(1-y)\ln(1-a)]+const
$$
以上是单个neuron的情况,扩展到多层多神经元的网络,有
这样的损失函数即为cross-entropy function,代码实现如下
1 | class CrossEntropyCost(object): |
BP算法反向传播时修改如下:
1 | # backward pass |
cross-entropy function的合理性
首先,理想输出y为0或1(对于每个神经元都如是),0≤a≤1,显然C恒为正数。另外,无论y是0还是1,当a→y时,C总是趋向于0。因此C满足作为cost function的基本要求。
再看看我们之前的期望是否达到,C对weight求导
$$
\frac{\partial C}{\partial w_j}=-\frac{1}{n}\sum_x(\frac{y}{\sigma(z)}-\frac{(1-y)}{1-\sigma(z)})\frac{\partial \sigma}{\partial w_j}
$$
$$
=-\frac{1}{n}\sum_x(\frac{y}{\sigma(z)}-\frac{(1-y)}{1-\sigma(z)})\sigma’(z)x_j
$$
$$
=\frac{1}{n}\sum_xx_j(\sigma(z)-y)
$$
当输出结果接近desired output时,导数值趋于0,学习较慢,反之学习较快,对于bias也有同样的结果,我们的预期基本达到。
其他
在我们识别手写数字的网络中,y值为0或1,但在其他任务中y可以是0到1之间的值,此时当a=y时,交叉熵函数仍取最小值,此时函数值-[ylna+(1-y)ln(1-a)]称为binary entropy。
cross-entropy function对最后accuracy的提高并没有多大帮助,它主要是使得网络学习过程更加合理且有效率,并且与神经元的饱和有关——而这恰恰是神经网络学习过程中的一个重要问题。