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

『1』什么是下溢出(underflow)和上溢出(overflow)
实数在计算机内用二进制表示,所以不是一个精确值,当数值过小的时候,被四舍五入为0,这就是下溢出。
此时如果对这个数再做某些运算(例如除以它)就会出问题。
反之,当数值过大的时候,情况就变成了上溢出。

『2』softmax函数是什么
softmax函数如下:
f(x)i=exi∑j=1nexj,j=1,2,⋅⋅⋅,nf(x)_i=\frac{e^{x_i}}{\sum_{j=1}^ne^{x_j}},j=1,2,···,nf(x)i​=∑j=1n​exj​exi​​,j=1,2,⋅⋅⋅,n
从公式上看含义不是特别清晰,所以借用知乎上的一幅图来说明(感谢原作者):

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

『2』计算softmax函数值的问题
通常情况下,计算softmax函数值不会出现什么问题,
例如,当softmax函数表达式里的所有xix_ixi​都是一个“一般大小”的数值c时–也就是上图中,
z1=z2=z3=cz_1=z_2=z_3=cz1​=z2​=z3​=c时,那么,计算出来的函数值y1=y2=y3=13y_1=y_2=y_3=\frac{1}{3}y1​=y2​=y3​=31​

但是,当某些情况发生时,计算函数值就出问题了:

①c 极其大,导致分子计算ece^cec时上溢出。
②c 为负数,且 |c|很大,此时分母是一个极小的正数,有可能四舍五入为0,导致下溢出。

『3』如何解决 (针对①)
所以怎样所以怎样规避这些问题呢?我们可以用同一个方法一口气解决俩:
令 M = max(xix_ixi​), i =1,2,3,….,n,即M为所有xix_ixi​ 中最大的值,那么我们只需要计算f(xi−M)f(x_i- M)f(xi​−M)的值,就可以解决上溢出、下溢出的问题了,并且,计算结果理论上仍然和f(xi)f(x_i)f(xi​) 保持一致。

举个实例:还是以前面的图为例,本来我们计算f(z2)f(z_2)f(z2​)是用“常规”方法来算的:

ez2ez1+ez2+ez3\frac {e^{z_2}} {e^{z_1} + e^{z_2} + e^{z_3}}ez1​+ez2​+ez3​ez2​​

=e1e3+e1+e−3=\frac {e^{1}} {e^{3} + e^{1} + e^{-3}}=e3+e1+e−3e1​

≈0.12\approx 0.12≈0.12


ez2ez1+ez2+ez3\frac {e^{z_2}} {e^{z_1} + e^{z_2} + e^{z_3}}ez1​+ez2​+ez3​ez2​​

=ez2eMez1eM+ez2eM+ez3eM=\frac {\frac{e^{z_2}}{e^M} }{\frac{e^{z_1}}{e^M} + \frac{e^{z_2}}{e^M} + \frac{e^{z_3}}{e^M}}=eMez1​​+eMez2​​+eMez3​​eMez2​​​

=e1−3e1−3+e3−3+e−3−3=\frac {e^{1-3}} {e^{1-3} + e^{3-3} + e^{-3-3}}=e1−3+e3−3+e−3−3e1−3​

≈0.12\approx 0.12≈0.12

通过这样的变换,对任何一个xix_ixi​,减去M之后,exi−Me^{x_i-M}exi​−M的最大值为0,所以不会发生上溢出;
同时,分母中也至少会包含一个值为1的项,所以分母也不会下溢出
(四舍五入为0,这里的意思是分母中某个xi=Mx_i=Mxi​=M,所以分母肯定大于1)。
所以这个技巧没什么高级的技术含量。
总结:这里是在分析和处理分子上溢出,分母下溢出的情况

『4』延伸问题 (针对②)
看似已经结案了,但仍然有一个问题:如果softmax函数中的分子发生下溢出,也就是前面所说的 c 为负数,且 |c|很大,此时分母是一个极小的正数,有可能四舍五入为0的情况,此时,如果我们把softmax函数的计算结果再拿去计算 log,即 log softmax,其实就相当于计算 log(0),所以会得到 −∞,但这实际上是错误的,因为它是由舍入误差造成的计算错误。(这段话的意思是害怕分母为0
所以,有没有一个方法,可以把这个问题也解决掉呢?
答案还是采用和前面类似的策略来计算 log softmax 函数值:

log∣f(xi)∣log|f(x_i)|log∣f(xi​)∣
=log(exiex1+ex2+⋅⋅⋅+exn)=log(\frac{e^{x_i}}{e^{x_1}+e^{x_2}+···+e^{x_n}})=log(ex1​+ex2​+⋅⋅⋅+exn​exi​​)
=log(exieMex1eM+ex2eM+⋅⋅⋅+exneM)=log(\frac{\frac{e^{x_i}}{e^M}}{\frac{e^{x_1}}{e^M}+\frac{e^{x_2}}{e^M}+···+\frac{e^{x_n}}{e^M}})=log(eMex1​​+eMex2​​+⋅⋅⋅+eMexn​​eMexi​​​)
=log(e(xi−M)∑jne(xj−M))=log(\frac{e^{(x_i-M)}}{\sum_j^ne^{(x_j-M)}})=log(∑jn​e(xj​−M)e(xi​−M)​)
=log(e(xi−M))−log(∑jne(xj−M))=log(e^{(x_i-M)})-log(\sum_j^ne^{(x_j-M)})=log(e(xi​−M))−log(j∑n​e(xj​−M))
=(xi−M)−log(∑jne(xj−M))=(x_i-M)-log(\sum_j^ne^{(x_j-M)})=(xi​−M)−log(j∑n​e(xj​−M))

在最后的表达式中,会产生下溢出的因素已经被消除掉了——求和项中,至少有一项的值为1(因为有一项xjx_jxj​-M是0),这使得log后面的值不会下溢出,也就不会发生计算 log(0) 的悲剧。

总结:这里是在分析和处理分子下溢出,分母下溢出的情况

参考链接:
https://blog.csdn.net/m0_37477175/article/details/79686164

softmax函数上溢出和下溢出(转载+自己理解)相关推荐

  1. 无符号数相加溢出_探讨有符号数与无符号数数据上溢出和下溢出问题

    下面为有符号数的溢出: #include Void main() { Int i= 2147483647; Printf("%d,%d",i.i 1); } 输出结果为:21474 ...

  2. Softmax 函数解决上溢出(overflow)和下溢出(underflow)问题

    什么是上溢出和下溢出 在计算softmax值的时候,会做e的指数,这可能会数值过大导致导致上溢出,或者数值过小而取0(下溢出) 解决办法 https://blog.csdn.net/csuzhaoqi ...

  3. 矩阵的乘法、乘积(点积)和softmax函数的溢出

    矩阵的乘法比较简单,对应元素分别相乘即可,比如: a1=np.array([1,2]) a2=np.array([3,5]) a3=np.array([[1,2],[3,4]]) [[1,2], [3 ...

  4. linux扩展堆函数,linux下进程堆栈下溢出判断及扩展实现

    一.堆栈扩展 在进程创建的时候,内核并没有为进程分配太多的堆栈,即使是逻辑地址空间也没有,这样做的好处就是如果说用户态的程序堆栈向下溢出(对386来说,就是访问了更低地址的内存空间),这样内核可以比较 ...

  5. Softmax函数下的交叉熵损失含义与求导

    交叉熵损失函数(CrossEntropy Function)是分类任务中十分常用的损失函数,但若仅仅看它的形式,我们不容易直接靠直觉来感受它的正确性,因此我查阅资料写下本文,以求彻底搞懂. 1.Sof ...

  6. 动态函数监控技术在缓冲区溢出检测中的应用

    动态函数监控技术在缓冲区溢出检测中的应用 摘要:本文通过对Window环境下函数劫持方法的分析,并结合调试器技术,提出了动态监测进程函数调用的方法.同时,对缓冲区溢出shellcode进行了分析,用有 ...

  7. 干货,史上杀伤力最大的溢出型漏洞到底是什么?看这一篇就够了| 漏洞连载

    4月发生的BEC事件以及SMT事件已经沉淀一段时间了,具体的情况也被多方媒体所报道,相关的漏洞根源问题也有很多大神团队的分析和指正. 近日,有安全团队将各种已经发生或可能发生的类似溢出漏洞原理进行整理 ...

  8. R语言使用upper.tri函数、lower.tri函数、diag函数改变matrix矩阵上三角形、下三角形、对角线的数值

    R语言使用upper.tri函数.lower.tri函数.diag函数改变matrix矩阵上三角形.下三角形.对角线的数值 目录

  9. php分页上一页下一页判断,一个分页函数:显示“上一页下一页”等

    '************************************************** '函数名:ShowPage '作 用:显示"上一页 下一页"等信息 '参 数 ...

最新文章

  1. Android WindowManager 解析与骗取 QQ 密码案例分析
  2. communication with respect to scholars
  3. 调用函数,计算分段函数的值
  4. 为什么java抗并发_用最通熟易懂的话说明,为什么要使用java并发编程
  5. nacicat for mysql查询_navicat for mysql怎么用
  6. python 文件指针及文件覆盖
  7. 先睹为快!第十一届数据技术嘉年华七大看点全揭秘
  8. 详解 Ops 智能运维机器人,故障处理又快又准!
  9. 优化数据库语句的几个简单技巧
  10. 关于微信小程序中uView中通过packer选择器修改表单无法触发form组件的表单验证的问题
  11. 目标检测(十三)--MultiPathNet
  12. 谷歌推出3D社区“Lively” 挑战第二人生(组图)
  13. Ext4文件系统架构分析(三) ——目录哈希、扩展属性与日志
  14. 9个优秀的标签云免费生成工具
  15. USACO 1.1.3 - Friday the Thirteenth(模拟)
  16. 《太阳照常升起》观后感
  17. 浏览器窗口、网页尺寸
  18. openstack项目中遇到的各种问题总结 其一(问题多多)
  19. USB Type-C Configuration Channel (CC)引脚功能介绍
  20. redis6种数据淘汰策略

热门文章

  1. oc知识点 类的扩展
  2. 关于页面之间传参时有空格,中文及点击页面后退按钮的问题
  3. 什么是 Silverlight?
  4. 将截断字符串或二进制数据
  5. iview Table列表中增加字体图标
  6. iview table后端分页 多选 翻页选中回显
  7. 运算放大器基本公式_运算放大器积分器的些微差异
  8. JS如何制作图形验证码
  9. linux中怎么给用户设置不同的权限,linux怎么将一个文件设置为多个人拥有或者同一组内只让某两个用户有删除权限?...
  10. [BZOJ 2957]楼房重建(线段树)