一、激活函数的意义:
先简单介绍一下什么是激活函数~
单一神经元模型如下图所示:
神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数(又称激励函数)。
下面进入正题,激活函数存在的意义是什么呢,为什么不直接将神经元的输入输出直接进行连接呢?
如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下你每一层节点的输入都是上层输出的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。
正因为上面的原因,我们决定引入非线性函数作为激励函数,使用激活函数是为了让中间输出多样化,能够处理更复杂的问题,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。有论文中把激活函数定义为一个几乎处处可微的函数f: R->R
那么,激活函数是为了让网络能够能够有更强的表现能力,为什么有这么多激活函数呢?
随着神经网络不断地发展,人们逐渐发现早期的激活函数会导致模型的收敛变慢,甚至造成不收敛现象。下面简单介绍一下常用的激活函数以及其中的优缺点,在介绍之前先介绍一下基本的概念:
饱和:
当函数f(x)满足:
时,称为右饱和;
当函数f(x)满足:
时,称为左饱和。
当f(x)同时满足左饱和及右饱和时,称为饱和。
软包和与硬包和:
在饱和定义的基础上,如果存在常数c1,当x>c1时候恒满足称之为右硬饱和;同样的,如果存在c2,当x<c2时恒满足,称之为左硬饱和。如果同时满足了左饱和,又满足了右饱和,称之为硬饱和。相对的,只有在x趋于极值时才能满足f(x)的导数为0,则成为软饱和。
二、非零均值的问题(non-zero-centered)
部分激活函数是非零均值的,如, 等激活函数,他会造成网络收敛很慢。我们可以简单看下表示式:,其中为函数的输出。那么,在计算损失函数后,需要进行反向传播更新该权重。这时候,对进行求导,是直接与相关的,而因为是大于的值,所以这时候的梯度方向就会完全取决于。这时候若恒正或者恒为负,那么就会出现 的问题,使得网络收敛变慢。
其中 的图像就如下面图像:
1. Sigmoid 函数
函数公式如下:
,
其导数为:
def sigmoid(x):
y = 1/(1+np.exp(-x))
return y
优点:
<1> Sigmoid的取值范围在(0, 1),而且是单调递增,比较容易优化
<2> Sigmoid求导比较容易,可以直接推导得出。
缺点:
1、激活函数计算量大,反向传播求误差梯度时,求导涉及除法;
2、反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练;
3、 是非零均值的函数,收敛缓慢。
4、函数运算量大。如我们用(每秒浮点操作次数)来衡量模型的计算量指标。则运算量是1 。那么Sigmoid包括了减、取幂、加、除共4 .
反向传播算法中,要对激活函数求导, 的导数表达式为: 激活函数原函数及导数图形如上图:由图可知,导数从0 开始很快就又趋近于0 了,易造成“梯度消失”现象。
2. Tanh函数
激活函数的公式如下,也称为双切正切函数,取值范围为[-1,1]。 而函数的反传公式为: 函数的缺点同函数的缺点类似。当 z 很大或很小时,𝑔′(𝑧) 接近于 0 ,会导致梯度很小,权重更新非常缓慢,即梯度消失问题。从下面的图像也能看出来,靠近图像两端越平缓,梯度越小。
在特征相差明显时的效果会相对更好,在循环过程中会不断扩大特征效果。与 的区别是, 是 均值的,因此实际应用中 会比
def tanh(x):
y = (np.exp(x) - np.exp(-x))/(np.exp(x) + np.exp(-x))
return y
优点:
<1> 函数输出以(0,0)为中心
<2> 收敛速度相对于Sigmoid更快
缺点:
<1> tanh并没有解决sigmoid梯度消失的问题
3. ReLU函数
公式如下:
def ReLU(x):
y = []
for i in x:
if i >= 0:
y.append(i)
else:
y.append(0)
return y
优点:
<1> 在SGD中收敛速度要比Sigmoid和tanh快很多
<2> 有效的缓解了梯度消失问题
<3> 对神经网络可以使用稀疏表达
<4> 对于无监督学习,也能获得很好的效果
缺点:
<1> 在训练过程中容易杀死神经元,造成梯度消失0的情况。比如一个特别大的梯度经过神经元之后,我们调整权重参数,就会造成这个ReLU神经元对后来来的输入永远都不会被激活,这个神经元的梯度永远都会是0。
<2> 非零均值,所以一般后会加。
4.LReLU函数
公式:
LReLU
LRelu的优点:缓解了Relu神经元死亡的问题。
def LReLU(x):
y = []
for i in x:
if i >= 0:
y.append(i)
else:
y.append(0.01*i)
return y
LRelu/PReLU的优点:
优点:
<1> .解决了正区间梯度消失问题;
<2> .易于计算;
<3> .收敛速度快;
<4> .解决了某些神经元不能被激活
缺点:
<1> 输出不是以零为中心
4.PReLU函数
公式:
PReLU
其中是可以学习的。如果,那么 PReLU 退化为ReLU;如果是一个很小的固定值(如),则 PReLU 退化为 Leaky ReLU(LReLU)。
PReLU 只增加了极少量的参数,也就意味着网络的计算量以及过拟合的危险性都只增加了一点点。特别的,当不同 channels 使用相同的a时,参数就更少了。BP 更新a时,采用的是带动量的更新方式(momentum)
5. Softmax 激活函数
多用于多分类神经网络输出,公式为:
主要用于分类最后归一化到 ,。当然也与一样,可以用在attention之中,学习到权重的矩阵。
6. Softplus激活函数
公式如下: 将与放在一起对比的话,则如图像所示:
可以看到,可以看作是的平滑。其中,加了是为了保证非负性。可以看作是强制非负校正函数平滑版本。
7. Mish激活函数
函数的公式如下:
在中 激活函数代码如下:
x = x * (torch.tanh(F.softplus(x)))
函数图像如图所示:
函数,以上无边界(即正值可以达到任何高度)避免了由于封顶而导致的饱和。理论上对负值的轻微允许零值更好的梯度流,而不是像中那样的硬零边界。
最后,可能也是最重要的,平滑的激活函数允许更好的信息深入神经网络,从而得到更好的准确性和泛化。
不过这个激活函数,版本的很占显存。
8. RReLU激活函数
(Randomized leaky rectified linear unit)也是 的一个变体。在中,是一个在一个给定的范围内随机抽取的值,这个值在测试环节就会固定下来。的亮点在于,在训练环节中,是从一个均匀的分布中随机抽取的数值。形式上来说,我们能得到以下结果:
其中
9. ELU激活函数
同样是针对的负数部分进行的改进,激活函数对小于零的情况采用类似指数计算的方式进行输出:
或者表达为:
对于有这些特点:
- 由于其正值特性,可以像, , 一样缓解梯度消失的问题。
- 相比,存在负值,可以将激活单元的输出均值往推近,达到接近的效果同时减少了计算量。
10. Swish激活函数
激活函数的公式如下: 其函数图像如下:
其中,是常数或可训练的参数。函数具备无上界有下界、平滑、非单调的特性。通过实验证明,对于深层模型, 的效果是优于的。
当时,激活函数成为线性函数。
当 为0或1. Swish变为ReLU: 。 以函数可以看做是介于线性函数与函数之间的平滑函数。
11. SELU激活函数
是给乘上系数 , 即$ SELU(x)=𝜆⋅ELU(x)$。
文章中主要证明是当取得时,在网络权重服从标准正态分布的条件下,各层输出的分布会向标准正态分布靠拢,这种"自我标准化"的特性可以避免梯度消失于梯度爆炸。函数图像如图所示:
- GELU激活函数
受启发于、等机制的影响,都意在将不重要的信息设置为0。对于输入的值,我们可以理解成是将输入的值乘以了一个0或者1。即对于每一个输入,其服从于标准正态分布,它也会乘以一个伯努利分布,其中。
(Gaussian error linear units)的表达式为。
而上式函数是无法直接计算的,因此可以使用另外的方式来进行逼近,论文得到的表达式为:。或者为。
, 中使用的激活函数,作者经过实验证明比等要好。原点可导,不会有 问题。
其函数图像如图所示: