激活函数
1. 常用的激活函数
在PyTorch中,提供了十几种激活函数层所对应的类,但常用的激活函数类和和功能如下表1所示。
| 名称 | 层对应的类 | 功能 |
|---|---|---|
| S型激活函数 | torch.nn.Sigmoid | Sigmoid激活函数 |
| 双曲正切函数 | torch.nn.Tanh | Tanh激活函数 |
| 线性修正单元函数 | torch.nn.ReLu | ReLu激活函数 |
| ReLu函数变体 | torch.nn.LeakyReLu | LeakyReLu激活函数 |
| 平滑近似ReLu函数 | torch.nn.Softplus | ReLu激活函数的平滑近似 |
2. 激活函数计算公式及其可视化
2.1 Sigmoid激活函数
torch.nn.Sigmoid()对应的Sigmoid激活函数,也叫logistic激活函数。
Sigmoid函数计算公式为
f
(
x
)
=
1
1
+
e
−
x
f(x)=\frac1{1+e^{-x}}
f(x)=1+e−x1
Sigmoid函数的导数有一个特殊的性质(导数是关于原函数的函数),导数公式如下:
f
′
(
x
)
=
f
(
x
)
∗
(
1
−
f
(
x
)
)
f'(x)=f(x)*(1-f(x))
f′(x)=f(x)∗(1−f(x))
Sigmoid 的函数图形如下:

Sigmoid 导数图形如下:

Sigmoid 优点:
- 能够把输入的连续值变换为0和1之间的输出 (可以看成概率)。
- 如果是非常大的负数或者正数作为输入的话,其输出分别为0或1,即输出对输入比较不敏感,参数更新比较稳定。
Sigmoid 缺点:
- 在深度神经网络反向传播梯度过程中,当输入远离坐标原点时,函数的梯度就变得很小,几乎为零,会影响梯度参数跟新速度,容易产生梯度消失(大概率)和梯度爆炸(小概率)问题。根据求导的链式法则,我们都知道一般神经网络损失对于参数的求导涉及一系列偏导以及权重连乘,那连乘会有什么问题呢?如果随机初始化各层权重都小于1(注意到以上Sigmoid导数不超过0.25,也是一个比较小的数),即各个连乘项都很小的话,接近0,那么最终很多很多连乘(对应网络中的很多层)会导致最终求得梯度为0,这就是梯度消失现象(大概率发生)。同样地,如果我们随机初始化权重都大于1(非常大)的话,那么一直连乘也是可能出现最终求得的梯度非常非常大,这就是梯度爆炸现象(很小概率发生)。
- Sigmoid函数的输出是0到1之间的,并不是以0为中心的(或者说不是关于原点对称的)。这会导致什么问题呢?神经网络反向传播过程中各个参数w的更新方向(是增加还是减少)是可能不同的,这是由各层的输入值x决定的(为什么呢?推导详见)。有时候呢,在某轮迭代,我们需要一个参数w0增加,而另一个参数w1减少,那如果我们的输入都是正的话(Sigmoid的输出都是正的,会导致这个问题),那这两个参数在这一轮迭代中只能都是增加了,这势必会降低参数更新的收敛速率。当各层节点输入都是负数的话,也如上分析,即所有参数在这一轮迭代中只能朝同一个方向更新,要么全增要么全减。(但是一般在神经网络中都是一个batch更新一次,一个batch中输入x有正有负,是可以适当缓解这个情况的)
- Sigmoid涉及指数运算,计算效率较低。
2.2 Tanh激活函数
Tanh是双曲正切函数。(一般二分类问题中,隐藏层用Tanh函数,输出层用Sigmod函数,但是随着Relu的出现,所有的隐藏层基本上都使用ReLu来作为激活函数了)。
Tanh 函数计算公式如下:
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
其导数也具备同Sigmoid导数类似的性质,导数公式如下:
t
a
n
h
′
(
x
)
=
1
−
t
a
n
h
2
(
x
)
tanh'(x)=1-tanh^2(x)
tanh′(x)=1−tanh2(x)
Tanh 函数图形如下:

Tanh 导数图形如下:

Tanh 优点:
- 输出区间在(-1,1)之间,且输出是以0为中心的,解决了sigmoid的第二个问题,使用效果会比Sigmoid较好。
- 如果使用tanh作为激活函数,还能起到归一化(均值为0)的效果。
Tanh 缺点:
- 梯度消失的问题依然存在,在输入很大或者很小时,梯度很小(导数还是趋于0的),不利于权重更新。
- 函数公式中仍然涉及指数运算,计算效率偏低。
2.3 ReLu激活函数
ReLU (Rectified Linear Units) 修正线性单元。ReLU目前仍是最常用的activation function,在隐藏层中推荐优先尝试!
ReLu函数计算公式为
f
(
x
)
=
m
a
x
(
0
,
x
)
f(x)=max(0, x)
f(x)=max(0,x)
ReLU 的函数图形如下:

ReLU 的导函数图形如下:

ReLU 优点:
- 梯度计算很快,只要判断输入是否大于0即可,这一点加快了基于梯度的优化算法的计算效率,收敛速度远快于Sigmoid和Tanh。
- 在正区间上解决了梯度消失(因为梯度永远为1,不会连乘等于0)的问题。
ReLU 缺点:
- ReLU 的输出不是以0为中心的,但是这点可以通过一个batch更新一次参数来缓解。
- Exist Dead ReLU Problem,某些神经元存在死机的问题(永远不会被激活),这是由于当输入x小于0的时候梯度永远为0导致的,梯度为0代表参数不更新(加0减0),这个和sigmoid、tanh存在一样的问题,即有些情况下梯度很小很小很小,梯度消失。但是实际的运用中,该缺陷的影响不是很大。 因为比较难发生,为什么呢?因为这种情况主要有两个原因导致,其一:非常恰巧的参数初始化。神经元的输入为加权求和,除非随机初始化恰好得到了一组权值参数使得加权求和变成负数,才会出现梯度为0的现象,然而这个概率是比较低的。其二:学习率设置太大,使得某次参数更新的时候,跨步太大,得到了一个比原先更差的参数。选择已经有一些参数初始化的方法以及学习率自动调节的算法可以防止出现上述情况。
2.4 LeakyReLU
相比于Sigmoid函数和Tanh函数,Relu函数通过裁剪负值,消除了梯度问题,但同时带来了Dead ReLU问题,即随着训练的进行,网络中的某些输出会变为0并且再也不会恢复。为了消除这一现象,有人有提出了Leaky ReLU或 Parametric ReLU (PReLU)等Relu函数的变体,这两种变体可以统一用以下 计算公式 来表示:
f
(
x
)
=
m
a
x
(
α
x
,
x
)
f(x)=max( \alpha x, x)
f(x)=max(αx,x)
以下以α为0.1的情况为例,通常α=0.01,这边取0.1只是为了图形梯度大一点,画出来比较直观。
Leaky Relu的函数图形如下:

Leaky Relu 的导数图形如下:

Leaky Relu 优点:
- 解决了Relu函数输入小于0时梯度为0的问题。
- 与ReLU一样梯度计算快,是常数,只要判断输入大于0还是小于0即可。
对于Leaky Relu 的缺点笔者暂时不了解,但是实际应用中,并没有完全证明Leaky ReLU总是好于ReLU,因此ReLU仍是最常用的激活函数。
2.5 Softplus激活函数
Softplus可以看作是ReLu的平滑。根据神经科学家的相关研究,Softplus和ReLu与脑神经元激活频率函数有神似的地方。也就是说,相比于早期的激活函数,Softplus和ReLu更加接近脑神经元的激活模型,而神经网络正是基于脑神经科学发展而来,这两个激活函数的应用促成了神经网络研究的新浪潮。
Softplus函数计算公式为
f
(
x
)
=
1
β
l
o
g
(
1
+
e
β
x
)
f(x)={1\over \beta}log(1+e^{\beta x})
f(x)=β1log(1+eβx)
其中,
β
\beta
β默认取值为1。
Softplus的函数图形如下:

Softplus的导函数图形如下:

Softplus和ReLu相比于Sigmoid的优点在哪里呢?
- 采用Sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。
- 对于深层网络,Sigmoid函数反向传播时,很容易就会出现梯度消失的情况(在Sigmoid接近饱和区时,变换太缓慢,导数趋于0,这种情况会造成信息丢失),从而无法完成深层网络的训练。
- Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。
参考资料
- 《PyTorch 深度学习入门与实战(案例视频精讲)》,孙玉林,余本国著. 北京:中国水利水电出版社,2020.7

本文详细介绍了PyTorch中常见的激活函数,包括Sigmoid、Tanh、ReLU、LeakyReLU和Softplus,讨论了它们的计算公式、优缺点以及在深度学习中的应用。ReLU因其快速的梯度计算和收敛速度成为首选,但存在Dead ReLU问题,Leaky ReLU则是其改进版。Softplus作为ReLU的平滑形式,降低了计算复杂度并有助于深层网络训练。
1573

被折叠的 条评论
为什么被折叠?



