解决sigmoid/softmax指数运算溢出问题及python实现

sigmoid/softmax指数运算溢出问题

sigmoid和softmax函数在计算中,都会用到指数运算 e − x e^{-x} ex e x e^{x} ex,如果在 e − x e^{-x} ex x x x是一个很小的负数,如-128等,或者在 e − e^{-} e x x x是一个很大的正数,如128等,这时有溢出的风险。
而sigmoid和softmax的结果是一个在0~1之间的值,所以可以看到这种溢出只是一种中间过程,对于结果来说并不会有溢出,来看下如何去解决这个问题

解决 s i g m o i d sigmoid sigmoid函数溢出问题

1.如果 x > 0 x>0 x>0 y = 1 1 + e − x y=\frac{1}{1+e^{-x}} y=1+ex1

2.如果 x < 0 x<0 x<0 y = e x 1 + e x y=\frac{e^{x}}{1+e^{x}} y=1+exex
python代码如下:

import numpy as np
def sigmoid(x):
    if x >= 0:
        return 1 / (1 + np.exp(-x))
    else:
        return np.exp(x) / (1 + np.exp(x))

解决LR模型中计算cross entropy溢出问题

1.label记为 y y y
2. 记 z = 1 1 + e − x z=\frac{1}{1+e^{-x}} z=1+ex1

c r o s s e n t r o p y = y ∗ − l o g ( s i g m o i d ( z ) ) + ( 1 − y ) ∗ − l o g ( 1 − s i g m o i d ( z ) ) cross entropy=y*-log(sigmoid(z))+(1-y)*-log(1-sigmoid(z)) crossentropy=ylog(sigmoid(z))+(1y)log(1sigmoid(z))
= y ∗ − l o g ( 1 1 + e − x ) + ( 1 − y ) ∗ − l o g ( 1 − 1 1 + e − x ) =y*-log(\frac{1}{1+e^{-x}})+(1-y)*-log(1-\frac{1}{1+e^{-x}}) =ylog(1+ex1)+(1y)log(11+ex1)
= y ∗ l o g ( 1 + e − x ) + ( 1 − y ) ∗ ( − l o g ( e − x ) + l o g ( 1 + e − x ) ) =y*log({1+e^{-x}})+(1-y)*(-log(e^{-x})+log(1+e^{-x})) =ylog(1+ex)+(1y)(log(ex)+log(1+ex))
= y ∗ l o g ( 1 + e − x ) + ( 1 − y ) ∗ ( x + l o g ( 1 + e − x ) ) =y*log({1+e^{-x}})+(1-y)*(x+log(1+e^{-x})) =ylog(1+ex)+(1y)(x+log(1+ex))
= ( 1 − y ) ∗ x + l o g ( 1 + e − x ) =(1-y)*x+log(1+e^{-x}) =(1y)x+log(1+ex)
= x − x ∗ y + l o g ( 1 + e − x ) =x-x*y+log(1+e^{-x}) =xxy+log(1+ex)
对于 x < 0 x<0 x<0有溢出风险时,变换 x x x l o g ( e x ) log(e^{x}) log(ex)
则上式可以变换为:
= x − x ∗ y + l o g ( 1 + e − x ) =x-x*y+log(1+e^{-x}) =xxy+log(1+ex)
= l o g ( e x ) − x ∗ y + l o g ( 1 + e − x ) =log(e^{x})-x*y+log(1+e^{-x}) =log(ex)xy+log(1+ex)
= − x ∗ y + l o g ( 1 + e x ) =-x*y+log(1+e^{x}) =xy+log(1+ex)
综合起来,对于 c r o s s e n t r o p y = m a x ( x , 0 ) − x ∗ y + l o g ( 1 + e − ∣ x ∣ ) cross entropy = max(x,0)-x*y+log(1+e^{-|x|}) crossentropy=max(x,0)xy+log(1+ex)
python代码如下:

import numpy as np
def cross_entropy(y, x):
    if x >= 0:
        return (1-y) * x + np.log(1 + np.exp(-x))
    else:
        return (-x) * y + np.log(1 + np.exp(x)) 

解决 s o f t m a x softmax softmax函数溢出问题

在多元分类问题中,经常会用到 s o f t m a x softmax softmax函数
s o f t m a x softmax softmax函数形式如下:
y = e x i ∑ i = 1 n e x i y=\frac{e^{x_{i}}}{\sum_{i=1}^{n}{e^{x_{i}}}} y=i=1nexiexi
a.取所有 x i x_{i} xi中的最大值M,则计算 ( x 1 , x 2 , x 3 , . . . . . . , x n ) (x_{1},x_{2},x_{3},......,x_{n}) (x1,x2,x3,......,xn)这组数的softmax等同于计算 ( x 1 − M , x 2 − M , x 3 − M , . . . . . . , x n − M ) (x_{1}-M,x_{2}-M,x_{3}-M,......,x_{n}-M) (x1M,x2M,x3M,......,xnM)这一组数据的softmax,非常容易推导的,分子分母同时除以 e M e^{M} eM即可
b.所以这样softmax改成计算 y = e x i − M ∑ i = 1 n e x i − M y=\frac{e^{x_{i}-M}}{\sum_{i=1}^{n}{e^{x_{i}-M}}} y=i=1nexiMexiM,就解决了上溢出的问题,因为中间项都是小于等于1的值
python代码

import numpy as np
def softmax(X, k):
    if k >= len(X):
        return -1
    else:
        X = np.array(X)
        # 获得X中的最大值
        val_max = max(X)
        sum_X = 0
        for i in range(len(X)):
            sum_X += np.exp(X[i] - val_max)
        return np.exp(X[k] - val_max) / sum_X

参考

https://blog.csdn.net/haolexiao/article/details/107384486https://blog.csdn.net/haolexiao/article/details/107384486

猜你喜欢

转载自blog.csdn.net/shiaiao/article/details/109142869