人工神经网络中的每一个神经元接收上一层神经元的输出作为作为自身的输入值,并传递给下一层神经元。在多层神经网络中,上一层神经元的输出和下一层神经元的输入之间往往具有一个函数关系,而这个函数就称为激活函数。
首先,如果不使用激活函数,那么神经网络的每一层都之做线性变换,多层输入的叠加还是线性变换。而线性模型的表达能力通常是不够的,因此利用激活函数,引入非线性因素,增强神经网络的表达能力。总之,引入非线性的激活函数之后,神经网络就可能学习到平滑的曲线来分割平面,而不是利用复杂的线性组合逼近曲线,因此神经网络具有更强的表达能力,能更好的拟合目标函数。
设有激活函数 h ( x ) h(x) h(x),满足: lim x → + ∞ h ′ ( x ) = 0 \lim\limits_{x\rightarrow +\infty}h^{'}(x)=0 x→+∞limh′(x)=0 称为右饱和。满足 lim x → − ∞ h ′ ( x ) = 0 \lim\limits_{x\rightarrow -\infty}h^{'}(x)=0 x→−∞limh′(x)=0 称为左饱和。当 h ( x ) h(x) h(x)既满足左饱和,又满足右饱和,我们就称 h ( x ) h(x) h(x)为饱和激活函数。反之,称为非饱和激活函数。
sigmoid函数是曾经最常用的激活函数之一。其计算式为: σ ( x ) = 1 1 + e − x \sigma(x)=\frac{1}{1+e^{-x}} σ(x)=1+e−x1 目前比较少使用它作为激活函数,主要是因为它存在以下的问题:
容易造成梯度消失的问题 之前在深度学习中的梯度消失与梯度爆炸问题及其解决办法中已经详细解释了梯度消失产生的原因,这里不再赘述。sigmoid的输出不是“零为中心”的 我们加权输出为 z = ω x + b z=\omega x+b z=ωx+b,激活函数作用后输出为 α = σ ( ω x + b ) \alpha = \sigma(\omega x+b) α=σ(ωx+b),不论 x x x是正还是负, ∂ α ∂ ω \frac{\partial \alpha}{\partial \omega} ∂ω∂α的符号是跟随 x x x的。结合反向传播算法(BP)和深度学习中的梯度消失与梯度爆炸问题及其解决办法中的描述,权重更新方式为: ω k → ω k ′ = ω k − η ∂ C ∂ ω k \omega_k \rightarrow \omega_k^{\prime}=\omega_k-\eta\frac{\partial C}{\partial \omega_k} ωk→ωk′=ωk−η∂ωk∂C 根据链式法则 ∂ C ∂ ω k = ∂ C ∂ σ ⋅ ∂ σ ∂ z ⋅ ∂ z ∂ ω k = x k ⋅ ∂ C ∂ σ ⋅ ∂ σ ∂ z \frac{\partial C}{\partial \omega_k} = \frac{\partial C}{\partial \sigma}\cdot \frac{\partial \sigma}{\partial z} \cdot\frac{\partial z}{\partial \omega_k} = x_k\cdot \frac{\partial C}{\partial \sigma}\cdot \frac{\partial \sigma}{\partial z} ∂ωk∂C=∂σ∂C⋅∂z∂σ⋅∂ωk∂z=xk⋅∂σ∂C⋅∂z∂σ 因此权重更新方式变为: ω k → ω k ′ = ω k − η x k ⋅ ∂ C ∂ σ ⋅ ∂ σ ∂ z \omega_k \rightarrow \omega_k^{\prime}=\omega_k-\eta x_k\cdot \frac{\partial C}{\partial \sigma}\cdot \frac{\partial \sigma}{\partial z} ωk→ωk′=ωk−ηxk⋅∂σ∂C⋅∂z∂σω k \omega_k ωk是上一轮的更新结果,可以视为常数,超参数 η \eta η也是常数,显然 ω k \omega_k ωk的更新方向由 x k ⋅ ∂ C ∂ σ ⋅ ∂ σ ∂ z x_k\cdot \frac{\partial C}{\partial \sigma}\cdot \frac{\partial \sigma}{\partial z} xk⋅∂σ∂C⋅∂z∂σ决定。而 ∂ C ∂ σ ⋅ ∂ σ ∂ z \frac{\partial C}{\partial \sigma}\cdot \frac{\partial \sigma}{\partial z} ∂σ∂C⋅∂z∂σ对于已经迭代的 ω k \omega_k ωk而言也是常数,因此更新方法完全取决于 x k x_k xk。 这就可能产生,明明一个权重矩阵中只需要稍微调大其中一个 ω \omega ω,调小另一个 ω \omega ω就能完成整个权重矩阵的更新,即要求对应的 x x x一个为正,一个为负。但因上一层神经元利用sigmoid函数作为激活函数后就做不到对应的两个 x x x符号相反(因为sigmoid函数的输出始终为正)。那就只有像下图所示的,‘Z’字形逼近了,速度明显就比较慢了。
指数函数的计算相对耗时tanh函数也曾是常用的激活函数之一,它的计算式为: t a n h ( x ) = 1 − e − 2 x 1 + e − 2 x tanh(x)=\frac{1-e^{-2x}}{1+e^{-2x}} tanh(x)=1+e−2x1−e−2x 与sigmoid函数的关系: t a n h ( x ) = 2 σ ( 2 x ) − 1 tanh(x)=2\sigma(2x)-1 tanh(x)=2σ(2x)−1 与sigmoid相比: 优点:
解决了“零为中心”问题缺点:
与sigmoid函数一样,也无法避免梯度消失和指数运算的缺点。ReLU(Rectified Linear Unit, 修正线性单元),是Krizhevsky、Hinton等人于2012年发表的《ImageNet Classification with Deep Convolutional Neural Networks》论文中提出的一种线性且不饱和的激活函数。 其计算式为: R e L u ( x ) = m a x ( 0 , x ) ReLu(x)=max(0,x) ReLu(x)=max(0,x) 相比于sigmoid和tanh函数,ReLU函数的优缺点如下: 优点:
完美解决了梯度消失问题在SGD中收敛速度更快,这主要得益于其线性和非饱和的特性无指数运算,计算速度更快 缺点:输出并非“零为中心” 跟sigmoid一样,其激活值始终是大于零的,其权重更新路径相似存在神经元死亡的威胁 注意到ReLU函数的函数式为 R e L u ( x ) = m a x ( 0 , x ) ReLu(x)=max(0,x) ReLu(x)=max(0,x),如果是 x > 0 x>0 x>0还好说,一旦 x < 0 x<0 x<0,那么其函数值就为0,对应的导数也为0,那么权重就无法更新了,也就是神经元无法继续学习,就是死亡了。根据上面的权重更新公式,假设我们设置了一个较大的学习率,导致更新后的权重为负值,刚好偏置的数值也刚刚好,导致加权输出 ω x + b \omega x+b ωx+b为负值,那么下一层神经元的输入 t a n h ( ω x + b ) tanh(\omega x+b) tanh(ωx+b)就为0。所以使用ReLU函数时一定要小心设置学习率,选择一个较小的学习率。因此为了解决ReLU函数存在的问题,就陆续出现了Leaky ReLU、RReLU等激活函数。
为了解决神经元死亡的情况,提出了Leaky ReLU。之前ReLU函数是将小于0的部分设置为0,而Leaky ReLU则赋上了一个非零的斜率。其计算式为: R e L U L ( x ) = { x if x ≥ 0 α x if x < 0 ReLU_L(x) = \begin{cases} x & \text{if } x \geq 0 \\ \alpha x & \text{if } x \lt 0 \end{cases} ReLUL(x)={xαxif x≥0if x<0 跟之前的激活函数相比: 优点:
不会出现ReLU的神经元死亡情况不存在任何神经元饱和的可能收敛速度快无指数运算,计算速度快小心选择 α < 0 \alpha \lt 0 α<0,不会存在“零为中心”问题 缺点:超参数 α \alpha α不太好选择,需要人工赋值RReLU(Randomized Leaky ReLU,随机修正线性单元)主要针对Leaky ReLU函数超参数 α \alpha α不太好选择的情况,RReLU函数则将 α \alpha α从一个高斯分布中随机选择,在测试过程中进行修正。数学表达形式与Leaky ReLU相似,是一种非确定性激活函数,其参数是随机的。 其数学表达式可以表示为: R R e L U j i = { x j i if x j i ≥ 0 α j i x j i if x j i < 0 RReLU_{ji}= \begin{cases} x_{ji} & \text{if } x_{ji} \geq 0 \\ \alpha_{ji} x_{ji} & \text{if } x_{ji} \lt 0 \end{cases} RReLUji={xjiαjixjiif xji≥0if xji<0 其中 α j i ∼ U ( l , u ) , l < u a n d l , u ∈ [ 0 , 1 ) \alpha_{ji} \sim U(l,u),l<u \ and \ l,u\in[0,1) αji∼U(l,u),l<u and l,u∈[0,1)
ELU(Exponential Linear Units,指数线性单元)由Djork等人提出,其计算式为: E L U ( x ) = { x if x > 0 α ( e x − 1 ) if x ≤ 0 ELU(x)= \begin{cases} x & \text{if } x \gt 0 \\ \alpha(e^x-1) & \text{if } x \leq 0 \end{cases} ELU(x)={xα(ex−1)if x>0if x≤0 特性总结:
左侧软饱和,右侧非饱和左侧软饱和让ELU对输入变化或噪声更鲁棒右侧线性部分解决梯度消失问题 ELU的变种SELU: S E L U ( x ) = λ ⋅ E L U ( x ) = λ { x if x > 0 α ( e x − 1 ) if x ≤ 0 SELU(x)=\lambda \cdot ELU(x)=\lambda \begin{cases} x & \text{if } x \gt 0 \\ \alpha(e^x-1) & \text{if } x \leq 0 \end{cases} SELU(x)=λ⋅ELU(x)=λ{xα(ex−1)if x>0if x≤0 当其中参数取为 λ ≈ 1.0507 \lambda\approx1.0507 λ≈1.0507, α ≈ 1.6733 \alpha\approx1.6733 α≈1.6733,在网络权重服从标准正态分布的条件下,各层输出的分布会向标准正态分布靠拢。这种“自我标准化”的特性可以避免梯度消失和爆炸的问题,让结构简单的前馈神经网络获得超高性能。GELU(Gaussian Error Linear Units,高斯误差线性单元),是2016年提出的一种高性能的激活函数,目前主要应用与NPL领域,使用GELU时最好选择一个带动量的优化器。其计算式为: G E L U ( x ) = 0.5 x ( 1 + t a n h ( 2 π ( x + 0.044715 x 3 ) ) ) = x σ ( 1.702 x ) GELU(x)=0.5x(1+tanh(\sqrt{\frac{2}{\pi}}(x+0.044715x^3)))=x\sigma(1.702x) GELU(x)=0.5x(1+tanh(π2 (x+0.044715x3)))=xσ(1.702x) 激活函数图像为: 其实GELU是dropout、zoneout、Relus的综合,GELU对于输入乘以一个0,1组成的mask,而该mask的生成则是依概率随机的依赖于输入。假设输入为 X X X,mask为 m m m,则 m m m服从一个伯努利分布( Φ ( x ) , Φ ( x ) = P ( X < x ) \Phi(x),\Phi(x)=P(X<x) Φ(x),Φ(x)=P(X<x),其中 X X X服从标准正态分布),这是因为神经元的输入趋向于正态分布,使得当输入 x x x减小的时候,输入会有一个更高的概率被dropout掉,这样的激活变换就会随机依赖于输入了。GELU的计算式也可以写为: G E L U ( x ) = x P ( X ≤ x ) = x Φ ( x ) GELU(x)=xP(X\leq x)=x\Phi(x) GELU(x)=xP(X≤x)=xΦ(x)
swish是2017年由谷歌提出的,其计算式为: s w i s h ( x ) = x ⋅ σ ( β x ) swish(x) = x · \sigma(\beta x) swish(x)=x⋅σ(βx) 函数图像为: 其中 β \beta β是超参数,swish函数具有无上界有下界,平滑,非单调的特性。在深层次模型中,其效果要优于ReLU。