sigmoid和softmax函数在计算中,都会用到指数运算 e − x e^{-x} e−x或 e x e^{x} ex,如果在 e − x e^{-x} e−x中 x x x是一个很小的负数,如-128等,或者在 e x e^{x} ex中 x x x是一个很大的正数,如128等,这时有溢出的风险。
而sigmoid和softmax的结果是一个在0~1之间的值,所以可以看到这种溢出只是一种中间过程,对于结果来说并不会有溢出,来看下如何去解决这个问题
1.如果 x > 0 x>0 x>0则 y = 1 1 + e − x y=\frac{1}{1+e^{-x}} y=1+e−x1
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))
1.label记为 y y y
2. 记 z = 1 1 + e − x z=\frac{1}{1+e^{-x}} z=1+e−x1
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=y∗−log(sigmoid(z))+(1−y)∗−log(1−sigmoid(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}}) =y∗−log(1+e−x1)+(1−y)∗−log(1−1+e−x1)
= 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})) =y∗log(1+e−x)+(1−y)∗(−log(e−x)+log(1+e−x))
= 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})) =y∗log(1+e−x)+(1−y)∗(x+log(1+e−x))
= ( 1 − y ) ∗ x + l o g ( 1 + e − x ) =(1-y)*x+log(1+e^{-x}) =(1−y)∗x+log(1+e−x)
= x − x ∗ y + l o g ( 1 + e − x ) =x-x*y+log(1+e^{-x}) =x−x∗y+log(1+e−x)
对于 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}) =x−x∗y+log(1+e−x)
= l o g ( e x ) − x ∗ y + l o g ( 1 + e − x ) =log(e^{x})-x*y+log(1+e^{-x}) =log(ex)−x∗y+log(1+e−x)
= − x ∗ y + l o g ( 1 + e x ) =-x*y+log(1+e^{x}) =−x∗y+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)−x∗y+log(1+e−∣x∣)
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函数形式如下:
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) (x1−M,x2−M,x3−M,......,xn−M)这一组数据的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=1nexi−Mexi−M,就解决了上溢出的问题,因为中间项都是小于等于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/107384486