深入理解激活函数
前言
本文将围绕激活函数的定义、作用、分类、函数图像、导数图像(梯度)、及激活函数各自的优缺点等等方面展开叙述。
- 不足与错误之处欢迎大家指出!
一、定义
神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数。
二、作用
-
激活函数,又称“非线性映射函数”,作为决定神经网络是否传递信息的「开关」,激活函数对于神经网络而言至关重要。
-
可以说,深度网络模型其强大的表示能力大部分便是由激活函数的非线性带来的。
-
在计算每一层的激活值时,我们要用到激活函数,之后才能确定这些激活值究竟是多少。
-
根据每一层前面的激活、权重和偏置,我们要为下一层的每个激活计算一个值。
-
但在将该值发送给下一层之前,我们要使用一个激活函数对这个输出进行缩放。本文将介绍不同的激活函数。
如果不用激活函数(其实相当于激活函数是f(x) = x,即线性映射),在这种情况下你每一层节点的输入都是上层输出的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。
正因为上面的原因,我们决定引入非线性函数作为激活函数,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。
三、类别
深度神经网络中常用的激活函数有:
- Sigmoid
- tanh
- ReLU:修正线性单元
- Leaky ReLU
- PReLU:参数化 ReLU
- RReLU:随机化 ReLU
- ELU:指数化线性单元
- SELU
- GELU
- Maxout
3.0 分类
-
饱和激活函数(软和硬)
-
非饱和激活函数
-
饱和激活函数的定义是什么?针对 导数 而言的
-
用“非饱和激活函数”有两点好处:
-
首先,“非饱和激活函数”能解决所谓的“梯度消失”问题。
-
其次,它能加快收敛速度。
3.1 Sigmoid
-
sigmoid 函数是一个 logistic 函数,即:不管输入是什么,得到的输出都在 0 到 1 之间。换言之,你输入的每个神经元、节点或激活都会被缩压缩到 0 到 1 之间的值。
-
公式如下: S i g m o i d ( x ) = σ ( x ) = 1 1 + e − x (1) \bm{Sigmoid(x)=\sigma(x)=\dfrac 1{1+e^{-x}} \tag{1}} Sigmoid(x)=σ(x)=1+e−x1(1)
-
函数图像如下:
-
导数图像(或者说梯度)为:
-
优点:它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1。
-
缺点1:从梯度图中可以看出,在大于5(或者小于-5)部分的梯度接近零,这会导致:在误差反向传播过程中导数处于该区域的误差很难甚至无法传递至前面的层,进而导致整个整个网络无法正常训练,也就是会发生梯度消失。
-
如果我们初始化神经网络的权值为 [ 0 , 1 ] 之间的随机值,由反向传播算法的数学推导可知,梯度从后向前传播时,每传递一层梯度值都会减小为原来的0.25倍,如果神经网络隐层特别多,那么梯度在穿过多层后将变得非常小接近于0,即出现梯度消失现象;当网络权值初始化为 ( 1 , + ∞ )区间内的值,则会出现梯度爆炸情况。详细的数学分析可以参考 Why are deep neural networks hard to train?
-
缺点2:从函数图像中可以看到,Sigmoid函数的值域的均值并未是0(即zero-centered),而是全为正,这样的结果实际上并不符合我们对**神经网络内数值的期望(均值)**应为0的设想,因为这会导致后一层的神经元将得到上一层输出的非0均值的信号作为输入。其解析式中含有幂运算,计算机求解时相对来讲比较耗时。对于规模比较大的深度网络,这会较大地增加训练时间。
3.2 tanh
- tanh函数则是一个实值输入压缩至 [-1, 1]的范围之内,它是在Sigmoid函数的基础上为解决均值问题提出的激活函数
- 公式为: t a n h ( x ) = 2 σ ( 2 x ) − 1 = 1 − e − 2 x 1 + e − 2 x (2) \bm{tanh(x)=2\sigma(2x)-1 {}\\ =\dfrac {1-e^{-2x}}{1+e^{-2x}} \tag{2}} tanh(x)=2σ(2x)−1=1+e−2x1−e−2x(2)
- 函数图像为:
- 导数图像(或者说梯度)为:
- 优点:函数范围为 [-1, 1],因此输出响应的均值为0。
- 缺点:由于tanh函数仍基于Sigmoid型函数,因此tanh依然会发生“梯度饱和”现象,梯度消失的问题仍然存在。
3.3 ReLU
-
为了避免梯度饱和现象的发生,Nair和Hinton将ReLU引入神经网络,这是目前使用最为广泛的激活函数之一。
-
公式为:本质上是一个分段函数 R e L U ( x ) = m a x ( x ) = ( 0 , x ) = { x , i f x ≥ 0 0 , i f x < 0 (3) \bm{ReLU(x)=max(x)=(0,x)}=\begin{cases} x, & if \quad x\geq 0 \\ 0, & if \quad x < 0 \end{cases} \tag{3} ReLU(x)=max(x)=(0,x)={x,0,ifx≥0ifx<0(3)
ReLU 公式表明: -
如果输入 x 小于 0,则令输出等于 0;
-
如果输入 x 大于 0,则令输出等于输入。
-
函数图像为:
-
导数图像(或者说梯度)为:
-
优点1:ReLU 可以对抗梯度爆炸/消失问题(在正区间,即大于0的部分)。相比于前两个激活函数,ReLU的梯度在 x ≥ 0 x\geq0 x≥0 时为1,反之为0;对 x ≥ 0 x\geq0 x≥0 部分完全消除了Sigmoid型函数的梯度饱和效应。
-
优点2:计算复杂度上,只需要判断输入是否大于0,它相对前两者的指数函数的计算更为简单,效率更高。
-
优点3:同时,实验中还发现ReLU有助于随机梯度下降方法收敛,收敛速度比 sigmoid 和 tanh 约快6倍左右。
从梯度图中可以看出,当使用 ReLU 激活函数时,我们不会得到非常小的值(比如前面 sigmoid 函数的 0.0000000438)。 相反,它要么是 0(导致某些梯度不返回任何东西),要么是 1。
-
缺点1:ReLU的输出不是zero-centered。
-
缺点2:死亡 ReLU 问题——x<0时,梯度便为0。换言之,对于小于0的这部分卷积结果响应,它们一旦变为负值将再也无法影响网络的训练,因为这会导致相应的参数永远不能被更新。
-
发生这种现象主要有两个可能的原因:
-
(1) 非常不幸的参数初始化,这种情况比较少见
-
(2) learning rate太高,导致在训练过程中参数更新太大,不幸使网络进入这种状态。
-
解决方法:1)采用Xavier初始化方法;2)避免将learning rate设置太大,或使用adagrad等自动调节learning rate的算法。
3.4 Leaky ReLU
-
为了缓解 “ Dead ReLU ” 的问题,研究者将 ReLU 函数中的 x < 0 x<0 x<0 的部分调整为 f ( x ) = α ⋅ x f(x) = \alpha \cdot x f(x)=α⋅x,通常 α = 0.01 或 0.001 \alpha=0.01 或 0.001 α=0.01或0.001 数量级较小的正数。
-
公式为: L e a k y R e L U ( x ) = m a x ( α ⋅ x ) = { x , i f x ≥ 0 α ⋅ x , i f x < 0 (4) Leaky\ ReLU(x)=max(\alpha \cdot x)=\begin{cases} x, & if \qquad x\geq 0 \\ \alpha \cdot x, & if \qquad x < 0 \end{cases} \tag{4} Leaky ReLU(x)=max(α⋅x)={x,α⋅x,ifx≥0ifx<0(4)
-
函数图像为:
-
导数图像(或者说梯度)为:注意!!在x轴的负方向上导数的值并不是0,而是接近0
-
优点:可以发现,原始 ReLU 函数是 Leaky ReLU 函数的一个特例,即 α = 0 \alpha=0 α=0 .
-
优点:Leaky ReLU 有 ReLU 的所有优点,外加不会有 “Dead ReLU” 问题,但是在实际操作当中,并没有完全证明Leaky ReLU 总是好于 ReLU。
-
缺点: α \alpha α 是超参数,需人为指定,然而合适的值较难设定且较为敏感,因此 Leaky ReLU 在实际使用中的性能并不是很稳定。
3.5 PReLU
- 为了解决 Leaky ReLU 中超参数 α \alpha α 不易设定的问题,PReLU 直接将 α \alpha α 作为一个网络中可学习的变量融入模型的整体训练过程。在求解 PReLU 时,仍然使用传统的误差反向传播和 SGD ,对于参数 α \alpha α 的更新遵循链式法则。
- 公式为:参考文献:Delving deep into rectifiers: surpassing human-level performance on ImageNet classification(何凯明)
- 函数图像为:同 Leaky ReLU
- 导数图像(或者说梯度)为:同 Leaky ReLU
- 优点:带来了更大的自由度。PReLU 有 ReLU 的所有优点,外加不会有 “Dead ReLU” 问题。
- 缺点1:增加了网络过拟合的风险,在实际使用中需格外注意。
- 缺点2: 不具备像ReLU会给网络带来稀疏性的优点,但能够提升网络性能。
- 虽然PReLU 引入了额外的参数,但基本不需要担心过拟合。这一点与缺点1的说法产生了矛盾,有路过的大佬能给说说嘛???,详见深度学习:神经网络中的激活函数
3.6 RReLU
-
另一种解决 α \alpha α 超参数设定的方式就是将其随机化,这便是 RReLU 。对于随机化 ReLU 中 α \alpha α 的设定,其取值在训练阶段服从均匀分布,在测试阶段将其指定为该均匀分布对应的分布期望 l + u 2 \dfrac {l+u} 2 2l+u
-
公式为: R R e L U ( x ) = m a x ( α ⋅ x ) = { x , i f x ≥ 0 α ′ ⋅ x , i f x < 0 (5) \bm{RReLU(x)=max(\alpha \cdot x)=\begin{cases} x, & if \qquad x\geq 0 \\ \alpha' \cdot x, & if \qquad x < 0 \end{cases} \tag{5}} RReLU(x)=max(α⋅x)={x,α′⋅x,ifx≥0ifx<0(5)
-
函数图像为:
-
导数图像(或者说梯度)为:同 Leaky ReLU
-
优点:RReLU 有 ReLU 的所有优点,外加不会有 “Dead ReLU” 问题。
-
注意:RReLU中的 α \alpha α 是一个在一个给定的范围内随机抽取的值,这个值在测试环节就会固定下来。
3.7 ELU (Exponential Linear Units)
-
指数线性单元激活函数解决了 ReLU 的一些问题,同时也保留了一些好的方面。这种激活函数要选取一个 α 值;常见的取值是在 0.1 到 0.3 之间。
-
ELU 函数,是为了解决 ReLU 存在的 zero-centered 问题而提出,同时也保留了了一些好的方面。
-
公式为: E L U ( x ) = { x , i f x ≥ 0 α ⋅ ( e x − 1 ) , i f x < 0 (6) \bm{ELU(x)=\begin{cases} x, & if \quad x\geq 0 \\ \alpha \cdot (e^x-1), & if \quad x < 0 \end{cases} \tag{6}} ELU(x)={x,α⋅(ex−1),ifx≥0ifx<0(6)
-
函数图像为:
-
导数图像(或者说梯度)为:
-
优点:解决了 ReLU 函数的 “Dead ReLU” 问题;ELU激活函数的输出均值是接近于零的,同时保留了 ReLU 的所有优点。
类似于 Leaky ReLU,理论上虽然好于 ReLU,但在实际使用中,目前并没有好的证据 ELU 总是优于 ReLU。 -
缺点:指数计算的稍微增大了计算量,计算效率低。在实际的应用之中,一般设置 α \alpha α 为 1.
3.8 SELU
-
经过该激活函数后使得样本分布自动归一化到0均值和单位方差(自归一化,保证训练过程中梯度不会爆炸或消失,效果比Batch Normalization 要好) 。
-
其实就是ELU乘了个 λ \lambda λ,关键在于这个 λ \lambda λ 是大于1的。
-
以前relu,prelu,elu这些激活函数,都是在负半轴坡度平缓,这样在activation的方差过大的时候可以让它减小,防止了梯度爆炸,但是正半轴坡度简单的设成了1。而selu的正半轴大于1,在方差过小的的时候可以让它增大,同时防止了梯度消失。这样激活函数就有一个不动点,网络深了以后每一层的输出都是均值为0方差为1。
-
公式为: E L U ( x ) = λ { x , i f x > 0 α e x − α , i f x ≤ 0 (7) \bm{ELU(x)=\lambda \begin{cases} x, & if \quad x> 0 \\ \alpha e^x-\alpha, & if \quad x \leq 0 \end{cases} \tag{7}} ELU(x)=λ{x,αex−α,ifx>0ifx≤0(7)
-
函数图像为:
-
导数图像(或者说梯度)为:
-
优点:不存在死区;存在饱和区(负无穷时, 趋于 - ‘αλ’);输入大于零时,激活输出对输入进行了放大.
3.9 GELU (Gaussian error linear units)
- 最近,高斯误差线性单元激活函数在 Transformer 模型(谷歌的 BERT 和 OpenAI 的 GPT-2)中得到了应用。GELU 的论文来自 2016 年,但直到最近才引起关注。
- 公式为: G E L U ( x ) = 0.5 x ( 1 + t a n h ( 2 π ( x + 0.044715 x 3 ) ) ) (8) \bm{GELU(x)=0.5x(1+tanh(\sqrt{\dfrac 2 \pi }(x+0.044715x^3))) \tag{8}} GELU(x)=0.5x(1+tanh(π2(x+0.044715x3)))(8)
- 函数图像为:
从图中可以看出,当 x 大于 0 时,输出为 x;但 x=0 到 x=1 的区间除外,这时曲线更偏向于 y 轴。 - 导数图像(或者说梯度)为:暂无
- 优点:似乎是 NLP 领域的当前最佳;尤其在 Transformer 模型中表现最好;能避免梯度消失问题。
- 注意:尽管是 2016 年提出的,但在实际应用中还是一个相当新颖的激活函数。
3.10 Maxout
-
Maxout “Neuron” 是由Goodfellow等人在2013年提出的一种很有特点的神经元,它的激活函数、计算的变量、计算方式和普通的神经元完全不同,并有两组权重。先得到两个超平面,再进行最大值计算。激活函数是对ReLU和Leaky ReLU的一般化归纳,没有ReLU函数的缺点,不会出现激活函数饱和神经元死亡的情况。
-
公式为: G E L U ( x ) = 0.5 x ( 1 + t a n h ( 2 π ( x + 0.044715 x 3 ) ) ) (9) \bm{GELU(x)=0.5x(1+tanh(\sqrt{\dfrac 2 \pi }(x+0.044715x^3))) \tag{9}} GELU(x)=0.5x(1+tanh(π2(x+0.044715x3)))(9)
Maxout是深度学习网络中的一层网络,就像池化层、卷积层一样等,我们可以把maxout 看成是网络的激活函数层,我们假设网络某一层的输入特征向量为:X=(x1,x2,……xd),也就是我们输入是d个神经元。Maxout隐藏层每个神经元的计算公式如下:
h i ( x ) = m a x j ∈ [ 1 , k ] z i j (10) \bm{h_i(x)=max_{j\in[1,k]} \ z_{ij} \tag{10}} hi(x)=maxj∈[1,k] zij(10)
上面的公式就是maxout隐藏层神经元i的计算公式。其中,k就是maxout层所需要的参数了,人为设定大小。就像dropout一样,也有自己的参数p(每个神经元dropout概率),maxout的参数是k。公式中Z的计算公式为:
z i j = x T W ⋯ i j + b i j \bm{z_{ij}=x^TW_{\cdots ij}+b_{ij}} zij=xTW⋯ij+bij
假设w是2维的,那么我们可以得出下列公式。
f ( x ) = m a x ( w 1 T x + b 1 , w 2 T x + b 2 ) (11) \bm{f(x)=max(w_1^Tx+b_1,w_2^Tx+b_2) \tag{11}} f(x)=max(w1Tx+b1,w2Tx+b2)(11)
ReLU和Leaky ReLU都是Maxout的变形。比如的时候,就是ReLU。Maxout的拟合能力非常强,它可以拟合任意的凸函数。Goodfellow在论文中从数学的角度上也证明了这个结论,只需要2个Maxout节点就可以拟合任意的凸函数,前提是“隐含层”节点的个数足够多。 -
函数图像为:暂无
-
导数图像(或者说梯度)为:暂无
-
优点:Maxout具有ReLU的所有优点,线性、不饱和性。同时没有ReLU的一些缺点。如:神经元的死亡。
-
缺点:从公式中可以看出,每个neuron将有两组w,那么参数就增加了一倍。这就导致了整体参数的数量激增。
四、小结&建议
(1)激活函数(非线性映射函数)对向深度网络模型引入非线性而产生强大的表示能力功不可没;
(2)Sigmoid型函数是历史上最早的激活函数之一,但它与 tanh(x) 型函数一样会产生梯度饱和效应,因此在实践中不建议使用;
(3)深度学习往往需要大量时间来处理大量数据,模型的收敛速度是尤为重要的。所以,总体上来讲,训练深度学习网络尽量使用zero-centered数据 (可以经过数据预处理实现) 和zero-centered输出。所以要尽量选择输出具有zero-centered特点的激活函数以加快模型的收敛速度。
(4)建议首先使用目前最常用的 ReLU,那么一定要注意 模型参数的初始化 和 小心设置 learning rate,而且要注意不要让网络出现很多 “dead” 神经元,如果这个问题不好解决,那么可以试试 Leaky ReLU、PReLU 或者 Maxout。
(5)为了进一步提升模型精度,可以尝试 Leaky ReLU、PReLU、RReLU 和 ELU。但四者之间的实际性能优劣并无一致性的结论,需要具体问题具体分析,也就是只有自己做了实验才知道效果好不好!!!别光听别人说,做了实验才知道!!!
(6)最好不要用 sigmoid,可以试试 tanh,不过可以预期它的效果会比不上 ReLU 和 Maxout。
(7)通常来说,不能把各种激活函数串起来在一个网络中使用。