防止sigmoid和tanh激活函数溢出的C++实现
引言
上一期,我们介绍了softmax函数的C++实现,但是考虑到sigmoid和tanh函数也是带 e e e的次幂,所以现在我们来考虑该函数的防止溢出实现。
sigmoid函数
原理
该函数的公式为:
1
1
+
e
−
x
\frac{1}{1+e^{-x}}
1+e−x1
在
x
≥
0
x\geq 0
x≥0的时候,
e
−
x
≤
1
e^{-x} \leq 1
e−x≤1,不会溢出,但是在
x
<
0
x < 0
x<0的时候,就有可能溢出了。所以在
x
<
0
x<0
x<0时,我们可以做如下变换:
1
1
+
e
−
x
=
1
⋅
e
x
(
1
+
e
−
x
)
⋅
e
x
=
e
x
e
x
+
1
\frac{1}{1+e^{-x}}=\frac{1\cdot e^x}{(1+e^{-x})\cdot e^x}=\frac{e^x}{e^x+1}
1+e−x1=(1+e−x)⋅ex1⋅ex=ex+1ex
这样
e
x
<
1
e^x<1
ex<1,也不会溢出了。
实现
double sigmoid(double x)
{
if (x > 0)
return 1.0 / (1.0 + exp(-x));
else
return exp(x) / (1.0 + exp(x));
}
tanh函数
原理
该函数的公式为:
e
x
−
e
−
x
e
x
+
e
−
x
\frac{e^x-e^{-x}}{e^x+e^{-x}}
ex+e−xex−e−x
那么在
x
x
x很大或者很小时,都有可能溢出,所以我们分开考虑。
1、 x ≥ 0 x\geq0 x≥0时
这时
e
x
e^x
ex可能溢出,
e
−
x
<
1
e^{-x}<1
e−x<1不会溢出。我们进行如下变换:
e
x
−
e
−
x
e
x
+
e
−
x
=
e
−
x
⋅
(
e
x
−
e
−
x
)
e
−
x
⋅
(
e
x
+
e
−
x
)
=
1
−
e
−
2
x
1
+
e
−
2
x
\frac{e^x-e^{-x}}{e^x+e^{-x}}=\frac{e^{-x}\cdot (e^x-e^{-x})}{e^{-x}\cdot (e^x+e^{-x})}=\frac{1-e^{-2x}}{1+e^{-2x}}
ex+e−xex−e−x=e−x⋅(ex+e−x)e−x⋅(ex−e−x)=1+e−2x1−e−2x
1、 x < 0 x<0 x<0时
这时
e
−
x
e^{-x}
e−x可能溢出,
e
x
<
1
e^{x}<1
ex<1不会溢出。我们进行如下变换:
e
x
−
e
−
x
e
x
+
e
−
x
=
e
x
⋅
(
e
x
−
e
−
x
)
e
x
⋅
(
e
x
+
e
−
x
)
=
e
2
x
−
1
e
2
x
+
1
\frac{e^x-e^{-x}}{e^x+e^{-x}}=\frac{e^{x}\cdot (e^x-e^{-x})}{e^{x}\cdot (e^x+e^{-x})}=\frac{e^{2x}-1}{e^{2x}+1}
ex+e−xex−e−x=ex⋅(ex+e−x)ex⋅(ex−e−x)=e2x+1e2x−1
这样就都不会溢出了。
实现
double tanh(double x)
{
if(x > 0)
return (1-exp(-2*x))/(1+exp(-2*x));
else
return (exp(2*x)-1)/(1+exp(2*x));
}