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

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

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

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

『2』softmax函数是什么

softmax函数如下:

从公式上看含义不是特别清晰,所以借用知乎上的一幅图来说明(感谢原作者):

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

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

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

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

『4』如何解决

所以怎样规避这些问题呢?我们可以用同一个方法一口气解决俩:
令  M=max(xi),i=1,2,?,n ,即 M 为所有 xi 中最大的值,那么我们只需要把计算 f(xi)的值,改为计算  f(xi−M) 的值,就可以解决上溢出、下溢出的问题了,并且,计算结果理论上仍然和 f(xi)保持一致。
举个实例:还是以前面的图为例,本来我们计算  f(z2) ,是用“常规”方法来算的:

现在我们改成:

其中, 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中,都采用了此类方法来保持数值稳定。

原文地址:https://www.cnblogs.com/guoyaohua/p/8900683.html

时间: 2024-10-01 03:16:37

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

循环计算”时、日、月、年“数据的方法思路

1.使用游标实现跨数据库导数据 参考存储过程: ALTER proc [dbo].[Nsp_SiPingElectricityData]asdeclare @DANo Char(32)declare @DATime Datetimedeclare @LogTime Datetimedeclare @MeterType Char(4)declare @MeterNo Char(20)declare @Qty Decimal(18,6)declare @tagname nvarchar(50)dec

js计算当前日期上一个月和下一个月

/**         * 获取上一个月         *         * @date 格式为yyyy-mm-dd的日期,如:2014-01-25         */        function getPreMonth(date) {            var arr = date.split('-');            var year = arr[0]; //获取当前日期的年份            var month = arr[1]; //获取当前日期的月份   

php获取文章上一页与下一页的方法

本文实例讲述了php获取文章的方法.分享给大家供大家参考.具体方法如下: 今天发现一个站的出现问题,是直接到了本频道最新发布的文章了,按原理应该是文章本身ID的前与后的ID才是上下页吧,下面我来与大家详细讲述一下. 先看个例子:1,2,3,4,5. 假如上面5个是ID了,我要对我们要用order by id asc得出的排序应该是,4,好了原理就这么简. sql实现方法,代码如下: : 代码如下: $sql ="Select 字段 from 表名 where id>3 order by i

溢出overflow和表单

溢出overflow 当文字的太多以至于超出div的容纳,此时溢出:能利用属性设置是否有滚动条 该属性在IE中有一个bug :就是设置一个宽高都是1px的div时,IE显示的是高5px的div:可以添加overflow:hidden:一般设置宽高特别小的div或者元素最好添加它 CSS会把图片初始化为块状元素 表单实例 <html> <head> <title>表单</title> </head> <body> <form ac

基于Flink秒级计算时CPU监控图表数据中断问题

基于Flink进行秒级计算时,发现监控图表中CPU有数据中断现象,通过一段时间的跟踪定位,该问题目前已得到有效解决,以下是解决思路: 一.问题现象 以SQL02为例,发现本来10秒一个点的数据,有时会出现断点现象,会少1-2个点甚至更多: 二.问题定位 针对该问题,根据数据处理链路,制定了数据输出跟踪示意图,如下所示: 通过输出的实际数据发现: 1.监控Agent的数据已经正确上报Kafka 2.从Kafka中可以正确取到监控Agent上报的数据 3.从计算完毕的Kafka中取不到丢失点的数据

C# 计算地图上某个坐标点的到多边形各边的距离

原文:C# 计算地图上某个坐标点的到多边形各边的距离 在判断了某个坐标点是否在多边形内后,还有另一个需求就是当我这个坐标点在多边形外部时,我需要计算这个坐标点到多边形的距离是否在一个允许的误差范围内 通过两个位置的经纬度坐标计算距离(C#版本) 转自:https://blog.csdn.net/jasonsong2008/article/details/78423496 经纬坐标系中求点到线段距离的方法 转自C语言版本: https://blog.csdn.net/ufoxiong21/arti

计算地球上两个坐标点(经度,纬度)之间距离sql函数

go --计算地球上两个坐标点(经度,纬度)之间距离sql函数 --作者:lordbaby --整理:www.aspbc.com CREATE FUNCTION [dbo].[fnGetDistance](@LatBegin REAL, @LngBegin REAL, @LatEnd REAL, @LngEnd REAL) RETURNS FLOAT AS BEGIN --距离(千米) DECLARE @Distance REAL DECLARE @EARTH_RADIUS REAL SET @

输入年 月 日 ,计算时该年的第几天

#include "stdio.h" void main() { /*year 年 month 月 month1 备份月数 day 日 day1 备份总体天数,day用于接收当月的天数,d1备份当月的天数. s 计算当月之前的月的总天数 sum 天数总和 */ int year,month,month1,day,day1,d1,sum=0,s=0; printf("请输入年份:"); scanf("%d",&year); fflush(s

计算球面上经纬度坐标方法比较

计算球面上的两点(坐标为经纬度)之间的距离可以直接通过公式计算得到,也可以先将经纬度坐标转化为墨卡托投影坐标来,然后用平面中两点之间的距离公式来计算. 在网上找了一些代码,然后简单进行了测试,发现前者精度更高: 资料来源:http://0414.iteye.com/blog/2039199 http://blog.sina.com.cn/s/blog_8ab3b2cf0100xd69.html 1 package com.suncreate.spatialquery.web.utils; 2 3