有效防止softmax计算时上溢出(overflow)和下溢出(underflow)的方法

Deep Learning》(Ian Goodfellow & Yoshua Bengio & Aaron Courville)第四章「数值计算」中,谈到了上溢出(overflow)和下溢出(underflow)对数值计算的影响,并以softmax函数和log softmax函数为例进行了讲解。这里我再详细地把它总结一下。函数

『1』什么是下溢出(underflow)和上溢出(overflow)

  实数在计算机内用二进制表示,因此不是一个精确值,当数值太小的时候,被四舍五入为0,这就是下溢出。此时若是对这个数再作某些运算(例如除以它)就会出问题。反之,当数值过大的时候,状况就变成了上溢出。atom

『2』softmax函数是什么

softmax函数以下:
spa

从公式上看含义不是特别清晰,因此借用知乎上的一幅图来讲明(感谢原做者):3d

 

这幅图极其清晰地代表了softmax函数是什么,一图胜千言。blog

『3』计算softmax函数值的问题

  一般状况下,计算softmax函数值不会出现什么问题,例如,当softmax函数表达式里的全部 xi 都是一个“通常大小”的数值 c 时——也就是上图中, z1=z2=z3=c  时,那么,计算出来的函数值y1=y2=y3=1/3 。
可是,当某些状况发生时,计算函数值就出问题了:
get

  • c 极其大,致使分子计算 ec 时上溢出
  • c 为负数,且  |c| 很大,此时分母是一个极小的正数,有可能四舍五入为0,致使下溢出

『4』如何解决

因此怎样规避这些问题呢?咱们能够用同一个方法一口气解决俩:
令  M=max(xi),i=1,2,,n ,即 M 为全部 xi 中最大的值,那么咱们只须要把计算 f(xi)的值,改成计算  f(xiM) 的值,就能够解决上溢出、下溢出的问题了,而且,计算结果理论上仍然和 f(xi)保持一致。
举个实例:仍是之前面的图为例,原本咱们计算  f(z2) ,是用“常规”方法来算的:
io

如今咱们改为:
class

其中, M=3 是  z1,z2,z3 中的最大值。可见计算结果并未改变。这是怎么作到的呢?经过简单的代数运算就能够参透其中的“秘密”:
技巧

  经过这样的变换,对任何一个 xi,减去M以后,e 的指数的最大值为0,因此不会发生上溢出;同时,分母中也至少会包含一个值为1的项,因此分母也不会下溢出(四舍五入为0)。因此这个技巧没什么高级的技术含量。二进制

『5』延伸问题

  看似已经结案了,但仍然有一个问题:若是softmax函数中的分子发生下溢出,也就是前面所说的 c 为负数,且 |c| 很大,此时分母是一个极小的正数,有可能四舍五入为0的状况,此时,若是咱们把softmax函数的计算结果再拿去计算 log,即 log softmax,其实就至关于计算  log(0) ,因此会获得  ,但这其实是错误的,由于它是由舍入偏差形成的计算错误。因此,有没有一个方法,能够把这个问题也解决掉呢?
  答案仍是采用和前面相似的策略来计算 log softmax 函数值:

  你们看到,在最后的表达式中,会产生下溢出的因素已经被消除掉了——求和项中,至少有一项的值为1,这使得log后面的值不会下溢出,也就不会发生计算 log(0) 的悲剧。在不少数值计算的library中,都采用了此类方法来保持数值稳定。

相关文章
相关标签/搜索