本文根据pytorch里面的源码解析各个激活函数,各个激活函数的python接口定义位于包torch.nn.modules中的activation.py,在包modules的初始化__init__.py中关于激活函数的导入:
1.非线性激活函数的必要性
1.1.加入非线性因素:
如下图所示,是神经元的数学模拟,如果在神经元之间,没有使用非线性激活函数或者使用恒等激活函数,那么神经网络仅仅是将输入线性组合再输出。在这种情况下,多层神经网络与仅仅只有一层隐藏层的神经网络没有任何区别。因此,要想多个隐藏层有意义,必须使用非线性激活函数。
1.2.充分组合特征
一般函数都可以通过泰勒展式来近似计算,如sigmoid激活函数中的指数项可以通过展开得到如下,其中有各个不同的高次项,而y=wx+b是输入特征的线性组合,现在激活函数可以起到类似特征组合的作用;
e
x
=
1
+
1
1
!
x
+
1
2
!
x
2
+
.
.
.
+
1
n
!
x
n
+
ο
(
x
n
)
e^{x} = 1+\frac{1}{1!}x +\frac{1}{2!}x^{2}+...+\frac{1}{n!}x^{n}+\omicron(x^{n})
ex=1+1!1x+2!1x2+...+n!1xn+ο(xn)
2.各个激活函数说明
下面根据activation.py中的激活函数来一一解析;
2.1 Threshold;
参数包括两个threshold以及value,具体公式如下:
f
(
x
)
=
{
x
x
>
t
h
r
e
s
h
o
l
d
v
a
l
u
e
e
l
s
e
f(x)=\begin{cases} x & x > threshold \\ value & else \end{cases}
f(x)={xvaluex>thresholdelse
2.2 ReLU;
在Threshold中,当threshold=value=0的时候,即为
f
(
x
)
=
m
a
x
(
0
,
x
)
=
{
x
x
>
=
0
0
x
<
0
f(x) = max(0, x)=\begin{cases} x & x >= 0 \\ 0 & x < 0 \end{cases}
f(x)=max(0,x)={x0x>=0x<0
2.3 ReLU6;
在ReLU中,为了防止当输入量过大的时候输出的范围,在ReLU的基础上又增加“正数不能超过6”的限制,即为
f
(
x
)
=
m
i
n
(
m
a
x
(
0
,
x
)
,
6
)
=
{
6
x
>
=
6
x
0
<
=
x
<
6
0
x
<
0
f(x)=min(max(0, x), 6)=\begin{cases} 6 & x >= 6 \\ x & 0 <= x < 6 \\ 0 & x < 0 \end{cases}
f(x)=min(max(0,x),6)=⎩⎪⎨⎪⎧6x0x>=60<=x<6x<0
2.4 ELU;
为了防止当输入为负数的时候,输出值和梯度恒为0,所以,当输入值小于0的时候,输出为指数,即ELU,
f
(
x
)
=
{
x
x
>
=
0
α
⋅
(
e
x
−
1
)
x
<
0
f(x)=\begin{cases} x & x >= 0 \\ \alpha \cdot (e^{x}-1) & x < 0 \end{cases}
f(x)={xα⋅(ex−1)x>=0x<0
2.5 LeakyReLU;
与ELU同时,当输入值小于0的时候,输出为线性函数,即LeakyReLU, α \alpha α是随机设置的固定参数,默认为0.01,
f
(
x
)
=
{
x
x
>
=
0
α
⋅
x
x
<
0
f(x)=\begin{cases} x & x >= 0 \\ \alpha \cdot x & x < 0 \end{cases}
f(x)={xα⋅xx>=0x<0
2.6 PReLU;
与LeakyReLU的公式是相同的,不过在PReLU里面, α \alpha α是可学习的参数,也就是类型是nn.Parameter。在模型的优化过程中,是即时更新的。
2.7 Sigmoid;
Sigmoid函数用于将模型的输出进行归一化到(0,1)区间,普遍应用于分类模型中的预测概率值,
f
(
x
)
=
1
(
1
+
e
−
x
)
f(x)=\frac{1}{(1+e^{-x})}
f(x)=(1+e−x)1
对应的导函数为
f
(
x
)
˙
=
f
(
x
)
⋅
(
1
−
f
(
x
)
)
\dot{f(x)}=f(x) \cdot (1-f(x))
f(x)˙=f(x)⋅(1−f(x))
2.8 HardSigmoid;
在Sigmoid的基础上,又有HardSigmoid,因为当输入值趋向无穷大的时候,输出值趋向于1;当输入值趋向无穷小的时候,输出值趋向于0。所以,顾名思义,HardSigmoid是在Sigmoid的基础上,当输入值超过某个范围强行置1和0,以下为例,
f
(
x
)
=
{
0
x
<
−
3
x
6
+
1
2
−
3
<
=
x
<
3
1
x
>
=
3
f(x)=\begin{cases} 0 & x < -3 \\ \frac{x}{6} + \frac{1}{2} & -3 <= x < 3 \\ 1 & x >= 3 \end{cases}
f(x)=⎩⎪⎨⎪⎧06x+211x<−3−3<=x<3x>=3
2.9 Tanh;
Tanh函数将输出归一化到(-1,1)区间,
f
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
f(x)=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}
f(x)=ex+e−xex−e−x
对应的导函数为
f
(
x
)
˙
=
1
−
f
2
(
x
)
\dot{f(x)}=1-f^{2}(x)
f(x)˙=1−f2(x)
2.10 HardTanh;
与HardSigmiod如出一辙,HardTanh示例如下,
f
(
x
)
=
{
−
1
x
<
−
1
x
−
1
<
=
x
<
1
1
x
>
=
1
f(x)=\begin{cases} -1 & x < -1 \\ x & -1 <= x < 1 \\ 1 & x >= 1 \end{cases}
f(x)=⎩⎪⎨⎪⎧−1x1x<−1−1<=x<1x>=1
2.11 TanhShrink;
基于Tanh之上,计算输入输出的差值,即为TanhShrink,
f
(
x
)
=
x
−
t
a
n
h
(
x
)
f(x)=x-tanh(x)
f(x)=x−tanh(x)
2.12 Softmax;
Softmax函数用于将输入进行归一化到(0,1),并且其和为1,普遍应用于分类模型(互斥)的预测概率值,
f
(
x
i
)
=
e
x
i
∑
x
k
e
x
k
f(x_{i})=\frac{e^{x_{i}}}{\sum_{x_{k}}e^{x_k}}
f(xi)=∑xkexkexi
2.13 LogSoftmax;
LogSoftmax是基于Softmax函数之上,计算其对应的对数值,范围在(-∞,0)用来计算交叉熵损失函数(根据groundtruth的标签取出对应的值即可),
f
(
x
i
)
=
log
(
e
x
i
∑
x
k
e
x
k
)
f(x_{i})=\log{(\frac{e^{x_{i}}}{\sum_{x_{k}}e^{x_k}})}
f(xi)=log(∑xkexkexi)
2.14 Softmin;
Softmin是在Softmax的基础上,做相反变换,
f
(
x
i
)
=
e
−
x
i
∑
x
k
e
−
x
k
f(x_{i})=\frac{e^{-x_{i}}}{\sum_{x_{k}}e^{-x_k}}
f(xi)=∑xke−xke−xi
2.15 HardShrink;
基于HardTanh,当输入值跨越某个范围之后,其值为常量,当处于某个范围之间,为线性变换;HardShrink刚好相反,当处于某个范围之间为常量,当跨越某个范围之后,为线性变换,
f
(
x
)
=
{
x
x
>
λ
,
x
<
−
λ
0
o
t
h
e
r
w
i
s
e
f(x)=\begin{cases} x & x > \lambda,x < -\lambda \\ 0 & otherwise \end{cases}
f(x)={x0x>λ,x<−λotherwise
2.16 SoftShrink;
基于HardShrink,在两个阶跃点不连续,SoftShrink避免了这种情况,
f
(
x
)
=
{
x
−
λ
x
>
λ
0
−
λ
<
=
x
<
λ
x
+
λ
x
<
−
λ
f(x)=\begin{cases} x - \lambda & x > \lambda \\ 0 & -\lambda <= x < \lambda \\ x + \lambda & x < -\lambda \end{cases}
f(x)=⎩⎪⎨⎪⎧x−λ0x+λx>λ−λ<=x<λx<−λ
2.17 Softsign;
公式如下,
f
(
x
)
=
x
1
+
∣
x
∣
f(x)=\frac{x}{1+|x|}
f(x)=1+∣x∣x
2.18 Softplus;
公式如下,
f
(
x
)
=
1
β
⋅
log
(
1
+
e
(
β
⋅
x
)
)
f(x)=\frac{1}{\beta} \cdot \log{(1 +e^{(\beta \cdot x)})}
f(x)=β1⋅log(1+e(β⋅x))
当\beta取值为1的时候,
f
(
x
)
=
log
(
1
+
e
x
)
f(x) = \log{(1+e^{x})}
f(x)=log(1+ex)
2.19 SELU;
在ELU的基础上,增加了因子scale,公式如下,
f
(
x
)
=
{
s
c
a
l
e
⋅
x
x
>
=
0
s
c
a
l
e
⋅
α
⋅
(
e
x
−
1
)
x
<
0
f(x) = \begin{cases} scale \cdot x & x >= 0 \\ scale \cdot \alpha \cdot (e^{x}-1) & x < 0 \end{cases}
f(x)={scale⋅xscale⋅α⋅(ex−1)x>=0x<0
2.20 CELU;
在ELU的基础上,当输入为负数的时候,对指数进行了缩放,公式如下,
f
(
x
)
=
{
x
x
>
=
0
α
⋅
(
e
x
α
−
1
)
x
<
0
f(x) = \begin{cases} x & x >= 0 \\ \alpha \cdot (e^{\frac{x}{\alpha}}-1) & x < 0 \end{cases}
f(x)={xα⋅(eαx−1)x>=0x<0
2.21 GELU;
GELU(高斯误差线性单元)是一个非初等函数形式的激活函数,主要应用于GPT-2、BERT等NLP模型中,主题思想是,将ReLU以及变种与Dropout两个独立的方面来合二为一,在网络正则化方面,Dropout将神经元单元输出随机置0。两者都是将输出乘上来服从伯努利分布的变量,即
f
(
x
)
=
x
⋅
Φ
(
x
)
f(x) = x \cdot \Phi(x)
f(x)=x⋅Φ(x)
,\Phi(x)为伯努利分布的期望值,假设输入服从标准正态分布,累计分布函数为
Φ
(
x
)
=
P
(
X
<
=
x
)
=
1
2
π
∫
−
∞
x
e
x
p
(
−
t
2
2
)
d
t
=
1
2
(
1
+
e
r
f
(
x
2
)
)
\Phi(x)=P(X<=x)=\frac{1}{\sqrt{2\pi}}\int_{-\infty}^{x}exp(-\frac{t^{2}}{2}){dt} =\frac{1}{2}(1+erf(\frac{x}{\sqrt{2}}))
Φ(x)=P(X<=x)=2π1∫−∞xexp(−2t2)dt=21(1+erf(2x))
其中erf(x)为高斯误差函数,与tanh比较接近,在论文
中,给出了近似拟合函数,
x
⋅
Φ
(
x
)
=
x
⋅
σ
(
1.702
x
)
x \cdot \Phi(x)=x \cdot \sigma(1.702x)
x⋅Φ(x)=x⋅σ(1.702x)
x
⋅
Φ
(
x
)
=
1
2
x
[
1
+
t
a
n
h
(
2
π
(
x
+
0.044715
x
3
)
)
]
x \cdot \Phi(x)=\frac{1}{2}x[1+tanh(\sqrt{\frac{2}{\pi}}(x+0.044715x^{3}))]
x⋅Φ(x)=21x[1+tanh(π2(x+0.044715x3))]
2.22 Swish & HardSwish;
Swish公式如下,其中\beta是个常数或者可训练的参数:
f
(
x
)
=
x
⋅
s
i
g
m
o
i
d
(
β
⋅
x
)
f(x)=x \cdot sigmoid(\beta \cdot x)
f(x)=x⋅sigmoid(β⋅x)
HardSwish公式如下:
f
(
x
)
=
x
⋅
R
e
L
U
6
(
x
+
3
)
6
f(x)=x \cdot \frac{ReLU6(x+3)}{6}
f(x)=x⋅6ReLU6(x+3)
3.参考说明:
本文是作者在实践过程中总结出来的激活函数说明,后续有补充会及时更新,如有不正确之处,欢迎各位大佬批评指正!!!
1.https://zhuanlan.zhihu.com/p/63775557
2.https://blog.csdn.net/grayondream/article/details/102955297
3.https://www.cnblogs.com/makefile/p/activation-function.html
4.https://blog.csdn.net/grayondream/article/details/102955297