文章目录
前言
今天这篇文章对一些常用激活函数做一下总结吧。在神经网络中激活函数还是很重要的,并且熟悉激活函数对理解别的问题也是很有帮助的。
为什么需要激活函数
从数学上看,神经网络是一个多层复合函数。引入激活函数是为了保证神经网络的非线性。因为线性函数无论怎样复合结果还是线性的,所以对激活函数最基本的要求是非线性的。
假设神经网络的输入是n维向量x,输出是m维向量y,它实现了如下向量到向量的映射:
R
n
→
R
m
R^n \rightarrow R^m
Rn→Rm
我们将这个函数记为
y
=
h
(
x
)
y = h(x)
y=h(x)
神经网络第l层的变换写成矩阵和向量形式为:
u
(
l
)
=
W
(
l
)
x
(
l
−
1
)
+
b
(
l
)
x
(
l
)
=
f
(
u
(
l
)
)
\begin{aligned} & u^{(l)} = W^{(l)}x^{(l-1)} + b^{(l)} \\ & x^{(l)} = f(u^{(l)}) \end{aligned}
u(l)=W(l)x(l−1)+b(l)x(l)=f(u(l))
其中W是权重矩阵,b是偏置向量,u是临时结果,x是神经网络每一层的输入或输出。激活函数分别作用于向量u的每一个分量,产生一个向量输出x。在正向传播阶段,反复用上面的公式进行计算,最后得到网络的输出。对于一个3层的网络,整个映射可以写成:
h
(
x
)
=
f
(
W
(
3
)
f
(
W
(
2
)
(
f
(
W
(
1
)
x
+
b
(
1
)
)
+
b
(
2
)
)
+
b
(
3
)
)
h(x) = f(W^{(3)}f(W^{(2)}(f(W^{(1)}x + b^{(1)}) + b^{(2)}) + b^{(3)})
h(x)=f(W(3)f(W(2)(f(W(1)x+b(1))+b(2))+b(3))
这是一个3层的复合函数。从这里可以清晰的看到,如果没有激活函数,整个函数将是一个线性函数:
W
(
3
)
(
W
(
2
)
(
W
(
1
)
x
+
b
(
1
)
)
+
b
(
2
)
)
+
b
(
3
)
W^{(3)}(W^{(2)}(W^{(1)}x + b^{(1)}) + b^{(2)}) + b^{(3)}
W(3)(W(2)(W(1)x+b(1))+b(2))+b(3)
什么样的函数可以做激活函数
前面已经说过,为保证非线性,激活函数必须为非线性函数,但仅仅具有非线性是不够的。神经网络在本质上是一个复合函数,这会让我们思考一个问题:这个函数的建模能力有多强?即它能模拟什么样的目标函数?已经证明,只要激活函数选择得当,神经元个数足够多,使用3层即包含一个隐含层的神经网络就可以实现对任何一个从输入向量到输出向量的连续映射函数的逼近,这个结论称为万能逼近(universal approximation)定理。万能定理对激活函数的要求是必须非常数、有界、单调递增并且连续。
当然,仅仅满足万能逼近定理的要求也是不够的。神经网络的训练一般采用反向传播算法和梯度下降法。反向传播算法从复合函数求导的链式法则导出,因为神经网络是一个多层的复合函数。在反向传播时,误差项的计算公式为:
δ
(
l
)
=
(
W
(
l
+
1
)
)
T
δ
(
l
+
1
)
⊙
f
′
(
u
(
l
)
)
\delta^{(l)} = (W^{(l+1)})^T \delta^{(l+1)} \odot f'(u^{(l)})
δ(l)=(W(l+1))Tδ(l+1)⊙f′(u(l))
由于使用梯度下降法需要计算损失函数对参数的梯度值,这个梯度值根据上面的误差项计算,而误差项的计算又涉及到计算激活函数的导数,因此激活函数必须是可导的。实际应用时并不要求它在定义域内处处可导,只要是几乎处处可导即可。
什么样的函数是好的激活函数
反向传播算法计算误差项时每一层都要乘以本层激活函数的导数。如果激活函数导数的绝对值小于1,多次连乘之后误差项很快会衰减到接近于0,参数的梯度值由误差项计算得到,从而导致前面层的权重梯度接近于0,参数没有得到有效更新,这称为梯度消失问题。与之相反的是梯度爆炸问题,如果激活函数的导数的绝对值大于1,多次乘积之后权重值会趋向于非常大的数,这称为梯度爆炸。
理论分析和实验结果都证明,随着网络层数的增加,反向传播的作用越来越小,网络更加难以训练和收敛。
这就引入了激活函数饱和性的概念。如果一个激活函数满足:
lim
x
→
+
∞
f
′
(
x
)
=
0
\lim_{x \to + \infty} f'(x) = 0
x→+∞limf′(x)=0
即在正半轴函数的导数趋于0,则称该函数为右饱和。类似的如果满足:
lim
x
→
−
∞
f
′
(
x
)
=
0
\lim_{x \to - \infty} f'(x) = 0
x→−∞limf′(x)=0
即在负半轴函数的导数趋于0,则称该函数左饱和。如果一个激活函数既满足左饱和又满足右饱和,称之为饱和。如果存在常数c,当
x
>
c
x>c
x>c时有:
f
′
(
x
)
=
0
f'(x) = 0
f′(x)=0
则称函数右硬饱和;当
x
<
c
x<c
x<c时有:
f
′
(
x
)
=
0
f'(x) = 0
f′(x)=0
则称函数左硬饱和。既满足左硬饱和又满足右硬饱和的激活函数为硬饱和函数。饱和性和梯度消失问题密切相关。在反向传播过程中,误差项在每一层都要乘以激活函数导数值,一旦x的值落入饱和区间,多次乘积之后会导致梯度越来越小,从而出现梯度消失问题。
所以,非饱和函数相比饱和函数来说更能成为好的激活函数。
常用激活函数
sigmoid
sigmoid函数的表达式为:
σ
(
x
)
=
1
1
+
e
−
x
\sigma(x) = \frac{1}{1+e^{-x}}
σ(x)=1+e−x1
其函数图像如下图所示:
sigmoid的值域为(0,1)。其导数为:
σ
′
(
x
)
=
σ
(
x
)
(
1
−
σ
(
x
)
)
\sigma'(x) = \sigma(x)(1 - \sigma(x))
σ′(x)=σ(x)(1−σ(x))
优点
- 求导容易,利用其本身函数值即可。
缺点
- 函数具有软饱和性,容易产生梯度消失问题。
- 输出不以0为中心,如果数据输入神经元是正的,那么会导致计算的梯度也始终为正。
- e − x e^{-x} e−x计算耗时。
tanh
tanh函数的表达式为:
t
a
n
h
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
=
2
σ
(
2
x
)
−
1
tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} = 2 \sigma(2x) - 1
tanh(x)=ex+e−xex−e−x=2σ(2x)−1
其函数图像如下图所示:
tanh的值域为(-1, 1)。其导数为:
t
a
n
h
′
(
x
)
=
1
−
(
t
a
n
h
(
x
)
)
2
tanh'(x) = 1 - (tanh(x))^2
tanh′(x)=1−(tanh(x))2
优点
- 输出以0为中心。
- 比sigmoid函数训练时收敛更快。
缺点
- 仍然是饱和函数,没有解决梯度消失问题。
ReLU
ReLU函数的表达式为:
R
e
L
U
(
x
)
=
m
a
x
(
0
,
x
)
ReLU(x) = max(0, x)
ReLU(x)=max(0,x)
其函数图像如下图所示:
其导数为:
R
e
L
U
′
(
x
)
=
s
i
g
n
(
x
)
=
{
1
,
x
>
0
,
0
,
x
<
0
ReLU'(x) = sign(x) = \begin{cases} 1, & x > 0,\\ 0, & x <0 \end{cases}
ReLU′(x)=sign(x)={1,0,x>0,x<0
需要注意的是,ReLU在原点处不可导。
优点
- 解决了部分梯度消失问题
- 训练收敛速度相比tanh更快
缺点
- 当x<0时,出现梯度消失问题。此时相当于神经元死亡。
对于神经元死亡问题,我们简单解释一下。
假设现有损失函数为交叉熵损失函数,
y
y
y为实际值,
y
^
\hat y
y^为预测值,那么其计算公式为:
L
(
y
,
y
^
)
=
−
(
y
l
o
g
(
y
^
)
+
(
1
−
y
)
l
o
g
(
1
−
y
^
)
)
L(y, \hat y) = -(ylog(\hat y) + (1 - y)log(1-\hat y))
L(y,y^)=−(ylog(y^)+(1−y)log(1−y^))
如果正例为1,负例为0,那么当
y
^
=
y
\hat y = y
y^=y时,损失函数值为0;当
y
^
=
0
\hat y = 0
y^=0而
y
=
1
y = 1
y=1时,损失函数值为无穷大;当
y
^
=
1
\hat y = 1
y^=1而
y
=
0
y = 0
y=0时,损失函数值为无穷大。
假设神经网络某层的计算公式为:
y
=
R
e
L
U
(
W
T
X
+
b
)
y = ReLU(W^T X + b)
y=ReLU(WTX+b)
如果学习率设置的比较大,且此时的实际值为负例,训练结果为使模型往实际值拟合,那么权重W就会突然变得很小,使
W
T
X
+
b
W^T X + b
WTX+b为负,再经过ReLU,那么输出就为0。但反向传播到此处就会碰到问题,因为此时梯度为0,从而无法更新参数值,也就相当于神经元死亡了。
对于这种问题的解决办法一般是设置一个比较小的学习率,或者使用L2正则化以及使用Momentum、RMS、Adam等其他梯度下降方式。
Leaky ReLU
Leaky ReLU函数的表达式:
f
(
x
)
=
{
x
,
x
>
0
,
α
x
,
x
≤
0
f(x) = \begin{cases} x, & x > 0, \\ \alpha x, & x \le 0 \end{cases}
f(x)={x,αx,x>0,x≤0
式中
α
\alpha
α是一个很小的正数,比如0.01。
其函数图像如下图所示:
其导数为:
f
′
(
x
)
=
{
1
,
x
>
0
,
α
,
x
≤
0
f'(x) = \begin{cases} 1, & x>0, \\ \alpha, & x \le 0 \end{cases}
f′(x)={1,α,x>0,x≤0
优点
- 解决了ReLU神经元死掉的问题。
比Leaky ReLU更进一步的是PReLU,它与Leaky ReLU的区别是,其计算公式中的 α \alpha α不是预先定义好的,而是被当做参数去训练。
Randomized Leaky ReLU
Randomized Leaky ReLU中的
α
\alpha
α在训练阶段是从高斯分布
U
(
l
,
u
)
U(l, u)
U(l,u)中随机取出来的,然后在测试过程中进行纠正。
其表达式为:
y
j
i
=
{
x
j
i
,
x
j
i
≥
0
,
α
j
i
x
j
i
,
x
j
i
<
0
where
α
j
i
∼
U
(
l
,
u
)
,
l
<
u
and
l
,
u
∈
[
0
,
1
)
y_{ji} = \begin{cases} x_{ji}, & x_{ji} \ge 0, \\ \alpha_{ji}x_{ji}, & x_{ji} < 0 \end{cases} \\ \text{where }\alpha_{ji} \sim U(l, u), l < u \text{ and } l, u \in [0, 1)
yji={xji,αjixji,xji≥0,xji<0where αji∼U(l,u),l<u and l,u∈[0,1)
其函数图像如下图所示:
Maxout
Maxout函数表达式如下:
f
i
(
x
)
=
m
a
x
j
∈
[
1
,
k
]
z
i
j
f_i(x) = max_{j \in [1, k]} z_{ij}
fi(x)=maxj∈[1,k]zij
假设w是2维的,那么有:
f
(
x
)
=
m
a
x
(
w
1
T
X
+
b
1
,
w
2
T
X
+
b
2
)
f(x) = max({w_1}^TX+b_1, {w_2}^TX+b_2)
f(x)=max(w1TX+b1,w2TX+b2)
ReLu和Leaky ReLU都是它的变形(比如,
w
1
,
b
1
=
0
w_1, b_1 = 0
w1,b1=0的时候,就是ReLU )。
Maxout的拟合能力是非常强的,它可以拟合任意的凸函数,最直观的解释就是任意的凸函数都可以由分段线性函数以任意精度拟合,前提是“隐隐含层”的神经元个数可以任意多。
因为Maxout可以拟合任意凸函数,所以其没有固定的函数图像,下图是其一些拟合示例:
优点
- 计算简单。
- 解决了梯度消失问题,且不会产生死亡神经元。
- 训练收敛速度快。
缺点
- 每个神经元的参数加倍,导致参数数量激增。
其实还有很多其他的激活函数,限于篇幅这里就不一一分析了。
参考文章
理解神经网络的激活函数
【神经网络】激活函数面面观
常用激活函数的比较
为什么Relu会导致死亡节点
Maxout激活函数原理及实现