深度学习之激活函数
前言
激活函数(Activation Function)是机器学习和深度学习领域一个非常重要的概念。在多层神经网络中,为了增加网络学习与表达能力,需要使用函数 f 对上一层的节点的输出 X 进行变换,即将 f(X) 作为下一层的输入。两层之间的对数据施加的变换函数称为激活函数,也叫激励函数。本文将介绍几种在深度学习任务中常见的激活函数。
一、激活函数有什么作用?
激活函数的作用是在层与层之间引入非线性变化,使整个神经网络可以学习到复杂的非线性映射关系。若使用纯线性的映射,即使堆叠再多层神经网络,整个网络只能学习到线性变化,无法表达复杂的非线性函数。
- 控制神经元的输出:激活函数决定了神经元的输出值,通过对输入值进行非线性变换得到输出值,通常会将输出限制在一定范围内,比如0到1之间。
- 加速收敛:不同的激活函数有不同的特性,选择合适的激活函数可以加速神经网络的训练收敛。例如,ReLU激活函数可以帮助减缓梯度消失问题,加快训练收敛。
- 增强表达能力:不同的激活函数具有不同的决策边界与特性,合适选择激活函数可以提高模型的拟合能力与泛化性能。
对于引入非线性变换的理解,我们可以将一层神经元看作一个函数,假设某一网络层为 y = k x + b y=kx+b y=kx+b若没有激活函数,而是直接经过下一层 y = c x + d y=cx+d y=cx+d则经过这两层后得到的结果为 y = c k x + c b + d y=ckx+cb+d y=ckx+cb+d依旧为线性关系。依次类推,若没有引入非线性变化,堆叠再多网络层依旧是线性变化。若加入非线性变化,比如某激活函数为 y = x 2 y = x^2 y=x2则在第一层输出 kx+b 会变为 y = k 2 x 2 + 2 k b x + b 2 y=k^2x^2+2kbx+b^2 y=k2x2+2kbx+b2这里就引入了非线性关系。不同的激活函数可以带来不同的非线性变化关系。合适的激活函数可以更好的挖掘数据的表征与表示,增强模型的学习与表达能力。
二、常见的激活函数
在深度学习中,一些常用的激活函数有Sigmoid、Tanh、ReLU、Softmax、LeakyReLU、ELU、GELU、Hardswish、SiLU、Softplus等。这些激活函数可以分为饱和激活函数与非饱和激活函数,饱和函数的定义通俗来讲就是函数会收敛,在一定输入区域内收敛到一个恒定的输出值。例如Sigmoid激活函数,输入增大其会在1处收敛,即值逼近1但不会相等。输入减小其会在0出收敛,值逼近0但大于0。下面将依次介绍这些激活函数的公式、特点以及图像。
2.1 饱和激活函数
2.1.1 Sigmoid激活函数
函数公式:
σ
(
x
)
=
1
1
+
e
−
x
\sigma(x) = \frac{1}{1+e^{-x}}
σ(x)=1+e−x1
函数图像及特点:
Sigmoid激活函数如下图所示,输入为y=2x+1, 红色为输入,蓝色为激活函数变换后结果。SIgmoid激活函数会将输入的值映射到(0,1)的区间内,且当值减小时,Sigmoid的输出趋于0,值增大时,SIgmoid的输出趋于1。
优点: S型曲线,曲线平滑,有良好的梯度特性,有利于反向传播的收敛,函数形状类似生物神经元的激活特性,在模拟生物神经网络时较为合适。
缺点: 输入值过大或过小,梯度会接近0,导致梯度消失,不利于网络层数加深,且输出不是0中心,可能影响收敛速度。由于带有幂运算,其计算复杂度较高,可能会降低模型计算效率。
应用场景:二分类问题、神经网络中隐藏层、生物神经网络模拟。
2.1.2 Tanh激活函数
函数公式:
t
a
n
h
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}
tanh(x)=ex+e−xex−e−x
函数图像及特点:Tanh激活函数图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。Tanh将输入值映射到(-1,1)的区间内,当输入值增大时,Tanh的输出趋于1,当输入值减小时,Tanh的值趋于-1。
优点:输出是0为中心的,可以加快网络训练收敛速度。曲线平滑,在(-1,1)内有良好的梯度性,便于计算梯度。类似生物神经元的结构,模拟生物神经网络时候较为合适。对比Sigmoid,Tanh的输出范围更广,可以一定程度上避免梯度消失问题。
缺点:与Sigmoid一样,值过大或者过小时,梯度很小,几乎为0,会导致梯度消失问题,不利于深层网络的训练。计算复杂度高,可能导致计算效率低。
应用场景:需要0中心输出的神经网络、对称性问题(GAN中生成器与判别器)、模拟生物神经网络。例如,多层感知机(MLP)隐藏层、RNN与LSTM隐藏层、GAN生成器与判别器。
2.1.3 ELU激活函数
函数公式:
f
(
x
)
=
{
α
(
e
x
−
1
)
,
x≤0
b
,
x>0
f(x)=\begin{cases} \alpha(e^x-1),\text{x≤0}\\ b, \text{x>0}\\ \end{cases}
f(x)={α(ex−1),x≤0b,x>0
函数图像及特点:激活函数图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。其中 α 是一个超参数,控制当输入 x 为负值时的函数曲线。通常 α 的取值范围在 (0, 1] 之间。本图中α为默认值1。作为ReLU的升级版,ELU解决了ReLU在0处不可导的问题与死亡神经元的问题。
优点:防止梯度消失,ELU 在负值区域使用指数函数,可以避免梯度在反向传播过程中快速趋近于 0,从而缓解梯度消失问题。非线性与平滑性,ELU 提供了平滑的非线性特性,在 x=0 处导数存在,避免了 ReLU 的不连续性。避免了神经元死亡的问题。具有更好的训练收敛性能。
缺点:引入指数运算会增加时间复杂度,降低计算效率。引入额外超参数,增加了训练难度。ELU在负数区域指数增长,某些情况下可能不太理想。
应用场景:深度神经网络、图像处理任务、时间序列任务,例如VGGNet、ResNet、LSTM、GRU中。
2.1.4 GELU激活函数
函数公式:
g
e
l
u
(
x
)
=
x
Φ
(
x
)
,
Φ
(
x
)
=
∫
−
∞
x
e
−
(
x
−
μ
)
2
2
σ
2
2
π
σ
gelu(x)=x\Phi(x),\;\;\;\;\Phi(x)=\int_{-∞}^x \frac{e-\frac{(x-\mu)^2}{2\sigma^2}}{\sqrt{2\pi}\sigma}
gelu(x)=xΦ(x),Φ(x)=∫−∞x2πσe−2σ2(x−μ)2
函数图像及特点:激活函数图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。它是对传统 ReLU 激活函数的一种改进。是一种基于高斯误差函数的激活函数,相较于 ReLU 等激活函数,GELU 更加平滑,有助于提高训练过程的收敛速度和性能。
优点:在深度神经网络中表现出色,可以提高模型的性能和收敛速度。在计算机视觉和自然语言处理等任务中都有良好的表现。在某些情况下,可以更好地捕获输入数据的统计属性。
缺点:计算相对复杂,需要涉及误差函数的计算,比 ReLU 稍慢。对于小型网络或内存受限的场景,GELU 可能不太合适。
应用场景:CV、NLP、GAN、VAE、深度强化学习、混合精度训练,例如Transformer、StyleGAN、DCGAN等。
2.1.5 SiLU激活函数
函数公式:
s
i
l
u
(
x
)
=
x
∗
S
i
g
m
o
i
d
(
x
)
=
x
1
+
e
−
x
silu(x)=x*Sigmoid(x)=\frac{x}{1+e^{-x}}
silu(x)=x∗Sigmoid(x)=1+e−xx
函数图像及特点:激活函数图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。又称Swish激活函数,是近年来提出的一种新型激活函数。它的定义是输入乘以其sigmoid函数值。它在保持 ReLU 优点的同时,还克服了 ReLU 的一些缺点,因此在各种深度学习模型中都有广泛应用。
优点:平滑和连续性,作为一个平滑、连续的激活函数,可以避免 ReLU 激活函数存在的非连续性和饱和梯度问题。SiLU 的激活值会根据输入的大小自适应调整,帮助模型更好地学习输入数据的特征,称为自适应性。SiLU 不是单调递增的函数,这种非单调性可以帮助模型学习更复杂的输入-输出映射关系,此为非单调性。处处可导,导数在 0 点附近不会趋近于 0,可以缓解 ReLU 存在的梯度消失问题。函数形式受到生物神经元激活函数的启发,可能更符合生物学原理。
缺点:计算复杂度略高于 ReLU。收敛速度可能略慢,由于 SILU 的非单调性,在某些情况下收敛速度可能会略慢于 ReLU。
应用场景:CV、NLP、强化学习,前馈神经网络,例如EfficientNet、BERT、DQN等。
3.1.6 Softplus激活函数
函数公式:
f
(
x
)
=
l
o
g
(
1
+
e
x
)
f(x)=log(1+e^x)
f(x)=log(1+ex)
函数图像及特点:激活函数图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。Softplus 函数是一种平滑的替代 ReLU 激活函数的函数,与脑神经元激活频率函数有神似的地方。映射区间(0,+∞)。
优点:Softplus 函数是连续可微的,在 x=0 点导数也是连续的,避免了 ReLU 函数在该点导数不连续的问题。这使得优化算法更加稳定。Softplus 函数是非线性函数,能够捕捉输入数据中的非线性特征。Softplus 函数没有输入值过大或过小时输出趋于饱和的问题,避免了梯度消失。导数可以很容易计算,这使得它可以用于需要计算梯度的深度学习算法中。形式受到生物学神经元激活函数的启发,可能更符合生物学原理。
缺点:需要计算指数和对数运算,计算复杂度略高。由于 Softplus 函数的非线性性质,在某些情况下训练收敛速度可能会略慢于 ReLU。函数不对称,某些情况下不太合适。Softplus 函数有一个可调节的斜率参数 β,需要合理调参以获得最佳性能,增加了训练难度。
应用场景:需要稳定优化的场景、捕捉非线性特征的场景、避免梯度消失的深层模型,例如FNN、CNN、RNN。
2.2 非饱和函数
2.2.1 ReLU激活函数
函数公式:
f
(
x
)
=
{
x
,
x
≥
0
0
,
x
<
0
f(x)=\begin{cases} x, x≥0\\ 0, x<0\\ \end{cases}
f(x)={x,x≥00,x<0
函数图像及特点:ReLU激活函数图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。ReLU不改变正项输入的值,把输入为负数的值变为0。
优点:计算高效,与比较大小即可。在激活区域内线性,可以保留输入信号的信息强度。输出值非负,有利于稀疏性的产生,有利于特征提取。与SIgmoid与Tanh相比,更容易避免梯度消失问题。
缺点:当输入值小于0时,会出现dying死亡神经元的问题。对某些特殊分布的数据,ReLU会导致权重更加倾斜。对某些初始化方法,ReLU可能导致权重发散。
应用场景:深度神经网络的隐藏层激活函数,如CNN、RNN等、需要稀疏表示的图像处理、自然语言处理任务&&对计算效率要求实时性高的场景,例如CNN、RNN、LSTM、ResNet、GAN、Transformer等。
2.2.2 Softmax激活函数
函数公式:
f
(
x
)
=
e
x
i
∑
1
N
e
x
k
f(x)=\frac{e^{x_i}}{\sum_1^N e^{x_k}}
f(x)=∑1Nexkexi
函数图像及特点:Softmax激活函数图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。Softmax可以将向量中的每一个元素转换为其概率值的形式。
优点:Softmax函数输出概率分布,将输入向量映射到概率向量,使得每个输出元素的值在0和1之间,并且所有输出元素的值之和为1。这使得Softmax函数在多分类问题中特别有用,且容易计算梯度。
缺点:容易产生梯度消失问题,会影响深层网络训练。在梯度下降时可能遇到数值不稳定情况。
应用场景:多分类问题的输出层激活函数,例如图像分类,自然语言处理。
2.2.3 LeakyReLU激活函数
函数公式:
f
(
x
)
=
{
x
,
x
>
=
0
−
α
x
,
x
≤
0
f(x)=\begin{cases} x, x>=0\\ -\alpha x, x≤0\\ \end{cases}
f(x)={x,x>=0−αx,x≤0
函数图像及特点:LeakyReLU图像如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。作为ReLU激活函数的改进版,此激活函数带有参数α,当输入值为正时,保持输入不变,当输入值为负时候,会变成接近于0的负数,通过 y=-ax 进行变换。α默认的值为0.01,此图的α值设置较大,是为了更直观的显示图像,一般情况下α的值是0.01。
优点:解决了ReLU死亡神经元问题。引入了一个小斜率,使得负值输入也能产生一定的输出,避免了神经元永久失活。相比于标准ReLU,Leaky ReLU在负值区域仍有一定的梯度信息,有利于反向传播。
缺点:引入了额外的超参数α,增加了训练难度。某些情况下表现出的性能可能不如ReLU。
应用场景:复杂的深度神经网络模型,Leaky ReLU可以提高训练收敛速度和性能&&对于某些容易导致"dying ReLU"问题的任务,如生成对抗网络(GAN)中的生成器网络&&输入数据分布不均衡,存在大量负值输入时,Leaky ReLU可能会更加合适。例如,图像分类、目标检测等视觉任务、语言识别,自然语言处理、GAN。
2.2.4 Hardswish激活函数
函数公式:
f
(
x
)
=
{
x
,
x
≥
3
0
,
x
≤
−
3
x
(
x
+
3
)
6
,
o
t
h
e
r
w
i
s
e
f(x)=\begin{cases} x,x≥3\\ 0,x≤-3\\ \frac{x(x+3)}{6}, otherwise\\ \end{cases}
f(x)=⎩
⎨
⎧x,x≥30,x≤−36x(x+3),otherwise
函数图像及特点:如下图所示,红色为输入y=2x+1,蓝色为激活函数变换后结果。hardswish激活函数是对swish激活函数 的改进,而swish非线性激活函数是ReLU非线性激活函数的替代,在一定程度上可以提高神经网络的准确性。函数整体分3段,两段线性与一段非线性。
优点:计算效率高,没有指数与对数运算,使其计算量小,对于高效计算的场景非常有利。具有非线性特性,可以增强神经网络的表达能力。渐进线性特性,当输入很大时,Hardswish 函数会趋近于线性关系,避免了饱和效应。这有助于网络在大输入值区域保持良好的性能。与ReLU不同,Hardswish激活函数连续可微,0处也可导,避免梯度消失问题。
缺点:相比 ReLU,Hardswish 的表现并不总是优于 ReLU。它的性能更多取决于具体问题和网络架构。与 Swish 相比,Hardswish 虽然计算更高效,但也稍微牺牲了一些表现。
应用场景:CNN、RNN、移动设备与嵌入式系统,例如MobileNetV3、 TensorRT-Quantization。
三、模型中激活函数的选取
选择合适的激活函数是深度学习模型设计中非常重要的一步,它对于模型的性能非常重要。激活函数的选择会直接影响模型的学习能力和收敛效果。不同的任务和网络结构可能需要不同的激活函数。选择合适的激活函数时需要综合考虑以下几个方面:
- 非线性特性:激活函数需要具有非线性特性,才能使得神经网络具有强大的学习和逼近能力。线性激活函数无法表达复杂的非线性映射关系。
- 梯度传播特性:激活函数的导数特性会影响梯度在网络中的传播。梯度消失或梯度爆炸都会导致模型难以收敛。理想的激活函数应该具有较好的梯度传播特性。
- 输出范围:不同的激活函数输出范围不同,有的在0到1之间,有的在-1到1之间。输出范围会影响网络参数的初始化和优化过程。
- 计算复杂度:激活函数的计算复杂度也是一个考虑因素。简单的激活函数通常计算开销较小,有利于提高模型的推理速度。
同时还要考虑模型将来部署在哪里,是移动端还是云服务器,以及对时间效率是否有要求,数据分布适合哪种激活函数处理等。
四、激活函数使用
首先,要确保python环境中安装了pytorch包,若没有安装,可以去torch官网找到相应的版本进行安装。
以一个神经网络为例,这里我们定义一个简单的神经网络,包含两层卷积与一层ReLU激活函数:
import torch
import torch.nn as nn
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.cnn1 = nn.Conv2d(3,6,3,1,1)
self.cnn2 = nn.Conv2d(6,12,3,1,1)
self.fx = nn.ReLU()
def forward(self,x):
x = self.cnn1(x)
print(x)
x = self.fx(x)
print(x)
x = self.cnn2(x)
return x
testnet = Net()
x = torch.randn(1,3,64,64)
testnet(x)
以上演示了ReLU激活函数的使用,即调用torch.nn包中封装好的激活函数即可,其他激活函数也是这样使用。在网络的forward函数中,我们将中间过程的张量打印出来,可以观察激活函数对于张量的作用。ReLU激活函数会将张量中所有负数值变为0。
总结
以上就是关于常见激活函数、函数特点以及如何使用的介绍,如有任何疑问或者发现了纰漏,请在评论区留言,感谢您的阅读!