1. 什么是激活函数
如上图所示,激活函数(Activation Function)
是在人工神经网络神经元上运行的函数,负责将神经元的输入映射到输出。激活函数为人工神经网络引入非线性因素,可以让人工神经网络模型更好的去学习、理解非常复杂的非线性关系。
2. 为什么要用激活函数
2.1 感知机(Perception)
感知机(Perception)
是人工神经网络的前身,在感知机模型中不使用激活函数,是一个线性分类器。
2.1.1 一层感知机
一层感知机网络如下图所示:
表达式为:
y
=
w
1
x
1
+
w
2
x
2
+
w
3
x
3
y = w_{1}x_{1}+w_{2}x_{2}+w_{3}x_{3}
y=w1x1+w2x2+w3x3
观察上式可知:一层感知机是一个线性分类器;
2.1.2 二层感知机
二层感知机如下图所示:
y
=
w
2
−
1
(
w
1
−
11
x
1
+
w
1
−
21
x
2
+
w
1
−
31
x
3
)
+
w
2
−
2
(
w
1
−
12
x
1
+
w
1
−
22
x
2
+
w
1
−
32
x
3
)
+
w
2
−
3
(
w
1
−
13
x
1
+
w
1
−
23
x
2
+
w
1
−
33
x
3
)
y=w_{2-1}(w_{1-11}x_{1}+w_{1-21}x_{2}+w_{1-31}x_{3})\\+w_{2-2}(w_{1-12}x_{1}+w_{1-22}x_{2}+w_{1-32}x_{3}) \\+w_{2-3}(w_{1-13}x_{1}+w_{1-23}x_{2}+w_{1-33}x_{3})
y=w2−1(w1−11x1+w1−21x2+w1−31x3)+w2−2(w1−12x1+w1−22x2+w1−32x3)+w2−3(w1−13x1+w1−23x2+w1−33x3)
整理如下:
y
=
(
w
2
−
1
w
1
−
11
+
w
2
−
2
w
1
−
12
+
w
2
−
3
w
1
−
13
)
x
1
+
(
w
2
−
1
w
1
−
21
+
w
2
−
2
w
1
−
22
+
w
2
−
3
w
1
−
23
)
x
2
+
(
w
2
−
1
w
1
−
31
+
w
2
−
2
w
1
−
32
+
w
2
−
3
w
1
−
33
)
x
3
y=(w_{2-1}w_{1-11}+w_{2-2}w_{1-12}+w_{2-3}w_{1-13})x_{1}\\+(w_{2-1}w_{1-21}+w_{2-2}w_{1-22}+w_{2-3}w_{1-23})x_{2}\\+(w_{2-1}w_{1-31}+w_{2-2}w_{1-32}+w_{2-3}w_{1-33})x_{3}
y=(w2−1w1−11+w2−2w1−12+w2−3w1−13)x1+(w2−1w1−21+w2−2w1−22+w2−3w1−23)x2+(w2−1w1−31+w2−2w1−32+w2−3w1−33)x3
把一层感知机的表达式和二层感知机整理后的式子进行对比发现:感知机的层数并不能改变其是线性分类器的特性。
2.2 线性不可分
线性分类器存在一个问题:不能解决线性不可分
的问题。最简单的线性不可分问题如下图所示:使用一条直线把橙色的正方形和绿色的圆形进行分割。
上图中红色和深绿色的线是两条例子,经试验发现,在二维平面中不存在这样一条直线可以把橙色的正方形和绿色的圆形进行分割。
这就是感知机(线下分类器)面临的问题:不能解决线性不可分问题。
2.3 激活函数的作用
激活函数最重要的作用就是可以给模型带来非线性因素
,直白的理解就是把直线“掰弯”
。
如上图所示,当感知器加入激活函数后,可以使用曲线把橙色的正方形和绿色的圆形分割开来。
3. 常见的激活函数
3.1 sigmoid
表达式
sigmoid 是常用的非线性激活函数,解析式如下所示:
s
i
g
m
o
i
d
(
x
)
=
f
(
x
)
=
1
1
+
e
−
x
sigmoid(x) = f(x) = \frac{1}{1+e^{-x}}
sigmoid(x)=f(x)=1+e−x1
导函数的表达式如下:
s
i
g
m
o
i
d
′
(
x
)
=
f
′
(
x
)
=
e
−
x
(
1
+
e
−
x
)
2
=
1
1
+
e
−
x
−
1
(
1
+
e
−
x
)
2
=
f
(
x
)
×
(
1
−
f
(
x
)
)
sigmoid'(x)=f'(x) = \frac{e^{-x}}{(1+e^{-x})^2}=\frac{1}{1+e^{-x}}-\frac{1}{(1+e^{-x})^2}=f(x)\times(1-f(x))
sigmoid′(x)=f′(x)=(1+e−x)2e−x=1+e−x1−(1+e−x)21=f(x)×(1−f(x))
图像
备注:橙色的线表示原函数,蓝色的线表示导函数。
特点
sigmoid把输入的值转换为0到1之间,特别的:如果是非常大的正数,就转换为1,如果非常小的负数,则转换为0;
缺点
- 从上图可以看出,sigmod的导函数的值域为:[0, 0.25],在反向传播(BP)更新参数时很容易出现
梯度消失
的现象; - 有饱和区域,当输入的x非常大或非常小时,sigmoid激活函数的导函数值为0,即此时的梯度为0,会导致神经元不能更新;
- sigmoid的输出都是正数,不是
zero centered
,这会导致zigzag
现象; - sigmoid含有幂运算,在求解时比较耗时。对于规模较大的神经网络,这会时训练时间增长。
3.2 tanh
表达式
tanh的解析式如下所示:
t
a
n
h
(
x
)
=
f
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
tanh(x)=f(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}
tanh(x)=f(x)=ex+e−xex−e−x
tanh的导函数如下所示:
t
a
n
h
′
(
x
)
=
f
′
(
x
)
=
(
e
x
+
e
−
x
)
2
−
(
e
x
−
e
−
x
)
2
(
e
x
+
e
−
x
)
2
=
1
−
(
e
x
−
e
−
x
e
x
+
e
−
x
)
=
1
−
f
2
(
x
)
tanh'(x)=f'(x)=\frac{(e^{x}+e^{-x})^2-(e^{x}-e^{-x})^2}{(e^{x}+e^{-x})^2}=1-(\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}})=1-f^2(x)
tanh′(x)=f′(x)=(ex+e−x)2(ex+e−x)2−(ex−e−x)2=1−(ex+e−xex−e−x)=1−f2(x)
图像
备注:橙色的线表示原函数,蓝色的线表示导函数。
特点
- tanh 把输入的值转换为0到1之间,特别的:如果是非常大的正数,就转换为1,如果非常小的负数,则转换为0;
- tanh解决了sigmoid不是
zero centered
的问题。
缺点
- 从上图可以看出,sigmod的导函数的值域为:[0, 1],在反向传播(BP)更新参数时仍然会出现
梯度消失
的现象; - 有饱和区域,当输入的x非常大或非常小时,sigmoid激活函数的导函数值为0,即此时的梯度为0,会导致神经元不能更新;
- tanh含有幂运算,在求解时比较耗时。对于规模较大的神经网络,这会时训练时间增长。
3.3 relu
3.3.1 relu
表达式
relu的解析式如下所示:
r
e
l
u
(
x
)
=
f
(
x
)
=
m
a
x
(
0
,
x
)
relu(x) =f(x)=max(0,x)
relu(x)=f(x)=max(0,x)
relu的导函数解析式如下所示:
r
e
l
u
′
(
x
)
=
f
′
(
x
)
=
{
1
,
x
>
0
0
,
x
≤
0
relu'(x)=f'(x)= \{{1, x>0 \atop 0, x \leq 0}
relu′(x)=f′(x)={0,x≤01,x>0
图像
备注:橙色的线表示原函数,蓝色的线表示导函数。
优点
- 在正区间中,解决了梯度消失的问题;
- 不含幂运算,计算速度非常快;
- 收敛速度远远快于sigmoid和tanh;
存在的问题
- relu的输出不是
zero-centered
; - 存在
dead relu problem
,即:某些神经元在训练过程中会出现永远不会被激活的情况,因为在反向更新时,如果梯度太大,权值更新之后可能会变成负数,在之后的正向传播的时候,输出会一直为0,造成dead relu
的问题(备注:此问题可以通过使用小学习率或者使用leaky ReLU等方法改进)。
3.3.2 leaky relu
表达式
leaky_relu的解析式如下所示:
l
e
a
k
y
_
r
e
l
u
(
x
)
=
f
(
x
)
=
m
a
x
(
a
x
,
x
)
leaky\_relu(x) =f(x)=max(ax,x)
leaky_relu(x)=f(x)=max(ax,x)
leaky_relu的导函数解析式如下所示:
r
e
l
u
′
(
x
)
=
f
′
(
x
)
=
{
1
,
x
>
0
a
,
x
≤
0
relu'(x)=f'(x)= \{{1, x>0 \atop a, x \leq 0}
relu′(x)=f′(x)={a,x≤01,x>0
图像
备注:橙色的线表示原函数,蓝色的线表示导函数。
特点
leaky relu是为了解决relu的dead relu
问题而设计的,将relu的前半段用“ax”(通常a取值为0.01)替换0。这样在理论上就解决了dead relu
的问题。
备注:在实践中,并没有证明leaky relu在效果上完全优于relu。
3.3.3 elu
表达式
elu的表达式如下所示:
e
l
u
(
x
)
=
f
(
x
)
=
{
x
,
x
>
0
a
(
e
x
−
1
)
,
x
≤
0
elu(x)=f(x)= \{{x,x>0 \atop a(e^{x}-1), x \leq 0}
elu(x)=f(x)={a(ex−1),x≤0x,x>0
elu导函数的表达式如下所示:
e
l
u
′
(
x
)
=
f
′
(
x
)
=
{
1
,
x
>
0
a
e
x
,
x
≤
0
elu'(x)=f'(x)=\{{1, x>0 \atop ae^{x}, x \leq 0}
elu′(x)=f′(x)={aex,x≤01,x>0
图像
备注:橙色的线表示原函数,蓝色的线表示导函数。
特点
elu也是为了解决relu的dead relu
问题而设计的,elu除了具有relu的优点之外还具有以下优点:
- 解决
dead relu
问题; - 输出的均值接近于0,即满足
zero-centered
;
小缺点
- 计算量比relu和leaky relu大;
备注:在实践中,并没有证明elu在效果上完全优于relu。
3.4 gelu
GELU
全名 Gaussian Error Linerar Unit(高斯误差线性单元)
,目前已被最领先的模型所使用(比如:BERT、RoBERTa等)。
在神经网络建模的过程中非线性因素是非常重要的,有了非线性因子,模型可以很好的拟合目标函数。此外,为了加强模型的泛化能力还需要加入正则化(如:dorpout)。通常非线性激活
和正则化
是分开的,而模型的输入是由非线性激活与正则两者共同决定的。
GELU
是将relu
和dropout
进行融合,在非线性激活中融入随机正则的思想,是一种对神经元输入的概率描述。GELU
对输入乘以一个0,1
组合的mask
,其中mask
服从于伯努利分布(Φ(x), Φ(x)=P(X<=x),X服从标准正太分布),其值的生成是依概率随机的依赖于输入。
数学表达式:
G
E
L
U
(
x
)
=
x
P
(
X
<
=
x
)
=
x
Φ
(
x
)
GELU(x)=xP(X<=x)=xΦ(x)
GELU(x)=xP(X<=x)=xΦ(x)
其中Φ(x)是正太分布函数,可以采用正太分布N(0, 1),也可以使用带参数的正太分布N(μ,σ),然后通过训练获得
μ
,
σ
\mu,\sigma
μ,σ。可以使用tanh
函数进行逼近上述函数,表达式如下:
G
E
L
U
(
x
)
=
0.5
x
(
1
+
t
a
n
h
[
2
/
π
(
x
+
0.044715
x
3
)
]
)
GELU(x)=0.5x(1+tanh[ \sqrt{2/π}(x+0.044715x^3 )])
GELU(x)=0.5x(1+tanh[2/π(x+0.044715x3)])
pytorch的实现源码如下:
class GELU(nn.Module):
"""
Paper Section 3.4, last paragraph notice that BERT used the GELU instead of RELU
"""
def forward(self, x):
return 0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3))))