参考:http://freemind.pluskid.org/machine-learning/softmax-vs-softmax-loss-numerical-stability/
The softmax loss layer computes the multinomial logistic loss of the softmax of its inputs. It’s conceptually identical to a softmax layer followed by a multinomial logistic loss layer, but provides a more numerically stable gradient.
中心思想是:在数值计算(或者任何其他工程领域)里,知道一个东西的基本算法和写出一个能在实际中工作得很好的程序之间还是有一段不小的距离的。有很多可能看似无关紧要的小细节小 trick,可能会对结果带来很大的不同。
当然这样的现象其实也很合理:因为理论上的工作之所以漂亮正是因为抓住了事物的主要矛盾,忽略“无关”的细节进行了简化和抽象,从而对比较“干净”的对象进行操作,在一系列的“assumption”下建立起理论体系。但是当要将理论应用到实践中的时候,又得将这些之前被忽略掉了的细节全部加回去,得到一团乱糟糟,在一系列的“assumption”都不再严格满足的条件下找出会出现哪些问题并通过一些所谓的“engineering trick”来让原来的理论能“大致地”继续有效。
softmax函数:
假设
Multinomial Logistic Loss:
softmax-loss(将softmax和Multinomial Logistic Loss两者结合在一起):
最小化,意味着让正确的类别的概率越接近1越好。
在设计 Deep Neural Networks 的库,则可能会倾向于将两者分开来看待,提供两个不同的 Layer 结构比只提供一个合在一起的 Softmax-Loss Layer 要灵活许多,从代码的角度来说也显得更加模块化。但是这里自然地就出现了一个问题:numerical stability。
反向传播说白了就是链式法则Chain Rule,因为 back propagation 是用 chain rule 将导数乘到一起,粗略地讲,如果每一层的导数都“小于一”的话,在层数较多的情况下很容易到后面乘着乘着就接近零了。反过来如果每一层的导数都“大于一”的话,gradient 乘到最后又会出现 blow up 的问题。
说清楚back propagation后,继续看softmax-loss层
同样,如果是softmax层和multinomial logistic loss层,
首先对loss层求导:
然后到达softmax层,层内导数
使用链式法则
最终得到和上面一样的结果。但是可以看出,如果分成两层计算的话,要多算好多步骤,除了计算量增大了一点,我们更关心的是数值上的稳定性。由于浮点数是有精度限制的,每多一次运算就会多累积一定的误差。分成两步计算的时候我们需要计算 ,如果碰巧这次预测非常不准,分母接近0,也就是正确的类别所得到的概率非常小(接近零)的话,这里会有溢出的危险。
通过下图,我们可以有一个直观的认识:图中横坐标是
首先可以看到的是单层直接计算确实比分成两层算要好一点,不过从纵坐标上也可以看到两者差距其实非常小。往左边看的话,会发现黄色的点没有了,那是因为结果得到了Nan,
比较有趣的是往右边的正数半轴看,发现到了
下面都是指使用softmax-loss:
面对上溢的问题,解决方案:就是在求 exponential 之前将
当然,总不能在计算的时候平白无故地减去一个什么数,但是在这个情况里是可以这么做的,因为最后的结果要做 normalization,很容易可以证明,这里对