在学习神经网络中,我们会常常碰到激活函数这个名词。那么什么是激活函数?激活函数激活的是什么?在神经网络中,有什么用?
1. 激活函数的概念
- 首先激活函数并不是真正的激活什么,而是指如何把‘激活的神经元的特征’通过函数把特征保留并映射出来,这是神经网络能解决非线性问题的关键。也就是,神经网络能够加入影响模型结果的非线性因素,从而使得神经网络更好地解决复杂的问题。
1.1 激活函数在神经网络中,如何工作的
- 在神经网络中,对于某一个隐藏层的节点,该节点的激活值计算一般分为两步:
- (1)输入该节点的值为
时,在进入这个隐藏节点后,会先进行一个线性变换,计算出值
,其中上标n表示第n层隐藏层。
- (2)再进行一个非线性变换,也就是经过非线性激活函数,计算出该节点的输出值(激活值)
,其中h(x)为非线性函数。
2019062201.jpg
- (1)输入该节点的值为
2.饱和,硬饱和,软饱和
- 右饱和:当一个激活函数
,满足
时,我们称之为右饱和。其实就是激活函数的导函数,在趋于正无穷的时候,极限存在且等于0。
- 左饱和:当一个激活函数
,满足
时,我们称之为左饱和。其实就是激活函数的导函数,在趋于负无穷的时候,极限存在且等于0。
- 饱和:当一个激活函数,既满足右饱和有满足左饱和时,我们称之为饱和。
- 右硬饱和:对于任意的x,如果存在常数c,当
时恒有
;
- 左硬饱和:对于任意的x,如果存在常数c,当
时恒有
;
- 硬饱和:若激活函数既满足右硬饱和又满足左硬饱和,我们称这种激活函数为硬饱和;
- 软饱和:只有在极限状态下,激活函数的导数(偏导数)等于0,我们称之为软饱和;
3. 梯度消失和梯度爆炸
- 深度学习会常常碰到一组名词,梯度消失和梯度爆炸,什么是梯度消失和梯度爆炸呢,简单的介绍一下。
- 梯度消失:在反向传播的算法过程中,由于我们使用了是矩阵求导的链式法则,有一大串连乘,如果连乘的数字在每层都是小于1的,则梯度越往前乘越小,导致梯度消失。梯度消失造成的结果是将导致靠近输入层的参数几乎不能被更新,靠近输入层的layer预测结果不准确,产生对整个后面的影响,最后无法训练。
- 梯度爆炸:如果连乘的数字在每层都是大于1的,则梯度越往前乘越大,导致梯度爆炸。对于梯度爆炸,则一般可以通过调整我们模型中的初始化参数得以解决。
4. 稀疏性的观点
- Machine Learning中的颠覆性研究是稀疏特征,基于数据的稀疏特征研究上,派生了Deep Learning这一分支。稀疏性概念最早由Olshausen、Field在1997年对信号数据稀疏编码的研究中引入,并最早在卷积神经网络中得以大施拳脚。近年来,稀疏性研究不仅在计算神经科学、机器学习领域活跃,甚至信号处理、统计学也在借鉴。总结起来稀疏性大概有以下三方面的贡献:
4.1 信息解离
- 当前,深度学习一个明确的目标是从数据变量中解离出关键因子(重要特征)。原始数据(以自然数据为主)中,通常缠绕着高度密集的特征。原因是这些特征向量是相互关联的,一个小小的关键因子可能牵扰着一堆特征,有点像蝴蝶效应,牵一发而动全身。基于数学原理的传统机器学习手段在解离这些关联特征方面具有致命弱点。然而,如果能够解开特征间缠绕的复杂关系,转换为稀疏特征,那么特征就有了鲁棒性(去掉了无关的噪声)。
4.2 线性可分性
- 稀疏特征有更大可能线性可分,或者对非线性映射机制有更小的依赖。因为稀疏特征处于高维的特征空间上(被自动映射了)从流形学习观点来看,稀疏特征被移到了一个较为纯净的低维流形面上。线性可分性亦可参照天然稀疏的文本型数据,即便没有隐层结构,仍然可以被分离的很好。
4.3 稠密分布但是稀疏
- 稠密缠绕分布着的特征是信息最富集的特征,从潜在性角度,往往比局部少数点携带的特征成倍的有效。而稀疏特征,正是从稠密缠绕区解离出来的,潜在价值巨大。
4.4 稀疏性激活函数的贡献的作用:
- 不同的输入可能包含着大小不同关键特征,使用大小可变的数据结构去做容器,则更加灵活。假如神经元激活具有稀疏性,那么不同激活路径上:不同数量(选择性不激活)、不同功能(分布式激活),两种可优化的结构生成的激活路径,可以更好地从有效的数据的维度上,学习到相对稀疏的特征,起到自动化解离效果。
- 稀疏性有很多优势。但是,过分的强制稀疏处理,会减少模型的有效容量。即特征屏蔽太多,导致模型无法学习到有效特征。论文中对稀疏性的引入度做了实验,理想稀疏性(强制置0)比率是70%~85%。超过85%,网络就容量就成了问题,导致错误率极高。
- 此处参考此博客
5.常用的激活函数
- 以多层感知机的网络结构为例,当前层的梯度和三个方面相关。具体公式查看神经网络的原理。
- 第一方面是损失函数;
- 第二方面是上一层的输出值,
- 第三方面是当前层的导函数值。
5.1 Sigmoid函数
Sigmoid 函数也称为 S 曲线函数,具有指数函数的形状,在物理意义上最为接近生物神经元,在生物学中也是常见的 S 型函数,又称之为 S 型生长曲线,因此也是神经网络中最常用的激活函数之一。该函数是将取值为
的数映射到
(开区间,不是闭区间) 之间。
Sigmoid函数的具体公式为:
Sigmoid导函数公式:
-
Sigmoid函数图像: 2019062202.png
-
Sigmoid导函数图像:2019062203.png
-
Sigmoid导函数定义域在[0,1]的图像:2019062204.png
Sigmoid函数的表达式或图像,将定义域为
的数映射到
,我们可以知道,只要是sigmoid作为该层的激活函数,该层的输出都是(0,1),从而导致,下一层再次经过线性变化和非线性变换的输出也是(0,1),特别说明,第一层的输入是自己传入的数据(不仅限于(0,1))。
Signoid导函数的表达式及图像值知,其值阈为[0,0.25],定义域在(0,1)时,sigmoid的导函数时严格单调递减的,
,
,其值在(0.196,0.250)区间内。
此时我们知道了隐藏层的输出值阈及导函数值阈,假定损失函数选择均方误差函数,这就很简单的估计出每一层的梯度值。在传递过程中,每传递一层梯度值都会减小为原来的0-0.25倍,如果神经网络隐层特别多,且每一隐藏层的激活函数都是sigmoid函数,在第n层时,梯度值的上界为0.25^{n},当n等于5时,
,那么梯度在穿过多层后将变得非常小接近于0,即出现梯度消失现象;
sigmoid 函数具有单调递增及反函数单调递增的性质,常被用作神经网络的阈值函数,将其映射到
区间,一般来讲,在训练神经网络过程中,对于求导,连续求导,处理二分类问题,一般使用sigmoid函数,这是因为sigmoid函数可以很好的把实数域光滑地映射到
,函数值恰好的解释预测为正类的概率。但是对于多分类问题,就比较麻烦,需要自己预处理一下,才能使用sigmoid函数.
-
Sigmoid函数优缺点
-
优点:
- 函数具有单调递增,连续可导,输出范围有限(在(0,1)区间内),优化稳定,可以用于输出层(尽量不要使用在隐藏层);
- 函数及导函数形式简单;
-
缺点:
- 由于该函数具有软饱和性,容易产生梯度消失,导致训练出现问题。
- 其输出大于0,因此输出值不是以0为均值的。这称为偏移现象,导致后一层的神经元得到上一层输出的非0均值的数据作为输入,这将产生一个结果,每一层的线性映射部分,对参数求偏导的结果都为正(或者负),这样在反向传播时,要么往正方向更新,要么负方向更新,使得收敛速度慢。
- sigmoid函数及其导函数含有指数,导致计算机运算的时间长,这也造成了收敛速度慢。
-
5.2 Tanh 函数
Tanh也是一种常见的激活函数,它是sigmoid函数的变形。
Tanh函数的公式为:
Tanh导函数公式:
-
Tanh函数的图像:2019062205.png
-
Tanh导函数的图像:2019062207.png
tanh函数的表达式或图像,我们能轻易知道tanh的值阈[-1,1],从而它解决了Sigmoid函数的不是0均值输出问题。
tanh导函数的表达式或图像,我们能够知道其值阈为[0,1]。当线性变换的结果大于3或者小于-3时,其导函数的值接近于0。
在梯度消失方面,tanh函数的缺点同sigmoid函数的缺点一样,当该层线性变换的结果很大或很小时,梯度接近于0,会导致梯度很小,权重更新非常缓慢,即梯度消失。
在定义域[-1,1]时,tanh导函数对应的值阈为[0.42,1],上一小节的知识可知,sigmoid导函数的值阈为[0.196,0.250],从而tanh函数要比sigmoid函数收敛速度快。
但是梯度消失的问题和幂运算的问题仍然存在。梯度消失问题相对于sigmoid要有所缓解。
一般来说,Tanh函数在特征相差明显时效果好,在传递过程中会不断地扩大特征,效果就显示出来了。如果特征相差不是很大,或者特征比较复杂的时,Tanh的效果就不好了。
-
Tanh函数的优缺点:
- 优点:
- Tanh函数输出的均值为0,该角度导致收敛要比sigmoid函数快。
- 迭代次数较少
- 缺点:
- Tanh函数及其导函数,同sigmoid函数一样。含有指数,导致计算机运算的时间长。
- 与sigmoid函数相同,具有软饱和性,会产生梯度消失问题,但是改善一些。
- 优点:
5.3 Relu 函数
- Relu(Rectified Linear Units)是一种最常用的激活函数,与Sigmoid相比,Relu函数的收敛速度会更快。
- Relu函数的表达式:
- Relu导函数的表达式:
-
Relu函数的图像:2019062208.png
-
Relu导函数的图像:2019062209.png
- Relu函数的表达式及其图像,知道定义域
,值阈
。
- Relu导函数的表达式及其图像,知道定义域
,值阈0或者1。
- 我们可以看到,当
时,Relu 硬饱和;当
时,Relu 不存在饱和问题。从而Relu函数能够在x>0时保持梯度不衰减,从而缓解梯度消失问题。这可以让我们直接以有监督的方式训练深度神经网络,而无须依赖无监督的逐层预训练。然而,随着训练的推进,部分输入会落入硬饱和区,导致对应的权重无法更新。这种现象被称为'神经元死亡'。针对神经元死亡,我们会对Relu函数进行改进。
- Relu函数的取值是
,因为神经网络是不断重复计算的,实际上变成了它在不断试探如何用一个大多数为0的矩阵来表达数据的特征,会导致因为稀疏特征的存在,反而使得运算速度快,效果好。
- 深度学习中最大的问题是梯度消失问题,使用tanh、sigmod等饱和激活函数情况下特别严重。神经网络在进行方向误差传播时,各个层都要乘以激活函数的一阶导数,梯度每传递一层就会衰减一层,网络层数较多时,梯度就会不停衰减直到消失,使得训练网络收敛越来越慢,而ReLU函数凭借其线性、非饱和的形式,训练速度则快很多。
- Relu 优缺点:
- 优点:
- 只需要判断输入是否大于0,相比 Sigmoid函数,Tanh函数,Relu函数能够快速的收敛;
- Sigmoid 函数和 Tanh 函数涉及指数运算,Relu函数在大于0的区间内,简单的线性运算,可以更好的实现;
- Relu有效的缓解梯度消失问题。在x>0的区间里,解决了梯度消失问题。
- 在无监督预训练的时候也有较好的表现。
- 缺点:
- 可能会出现神经元死亡,权重无法更新;
- ReLU的输出不是0均值,影响收敛性;
- 输入负数,则完全不激活,ReLU函数死掉;
- dead relu
- 优点:
5.3.1 DEAD RELU
5.3.1.1 什么是 dead relu
- 在训练过程中,某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生:
- (1) 非常不幸的参数初始化,这种情况比较少见(w都是负的);
- (2) 由于一次梯度更新的幅度过大(learning rate太大),导致某些Relu节点的权重调整的太大,使得后续的训练对该节点不再起作用,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
5.3.1.2 dead relu 产生的原因
假设有一个神经网络在其输入X上有一些分布。让我们看一个特定的ReLU单元R,对于任何固定的参数集,X上的分布意味着在R的输入上的分布。假设R的输入分布为以+0.1为中心的低方差高斯分布,在这种情况下,现在假设在一个特定的backprop期间,有一个大的梯度向后传递给R.由于R是开放的,它会将这个大的梯度向后传递到它的输入。这会导致计算R输入的函数发生相对较大的变化。这意味着R的输入上的分布已经改变。 假设R的输入现在分布为以-0.1为中心的低方差高斯分布。现在我们有R的大多数输入都是负数,因此大多数输入经过ReLU函数能得到一个0(ReLU is close),大多数输入不能反向传播通过ReLU得到一个梯度,因此ReLU的输入w一般都得不到更新通过随机反向传播(SGD)。R的输入分布相对较小的变化(-0.2)导致R的行为存在质的差异。我们越过零边界,R现在几乎总是关闭。问题是关闭的ReLU无法更新其输入参数,因此死亡(死亡=始终关闭)ReLU会停止运行,这就是所谓的‘dying ReLU’。
5.3.2 Leaky-Relu
-
Relu函数在定义域大于0的区间内,保持梯度不衰减,但是在定义域小于0的区间内,Relu硬饱和,会出现神经元死亡的现象。针对小于0的硬饱和现象,一般会对Relu函数做出相应的改进,改进后的函数表达式为:
2019062210.png
- L-Relu函数,在定义域小于0的区间内,比着Relu前面多了一个系数(0.01),其存在的目的在于即修正了数据又保留了部分在定义域小于0的值,使其信息不完全全部丢失。
5.3.3 P-ReLu
- 相比L-Relu,P-Relu函数在定义域小于0的区间内,将0.01更改为学习率,LReLu与ReLu对模型影响相差不大,通过在训练深度神经网络时,不断调整学习率(也可以固定学习率),让模型更加完美。
- P-Relu表达式为:
-
P-Relu具体表达式为:
2019062211.png
5.3.4 C-ReLu
C-Relu中的C是指concatenated。 CRelu主要用在CNN架构中,通过简单的修改,更好地提高CNN的性能。在深入分析CNN网络内部结构,发现在CNN网络的前几层学习到的滤波器中存在负相关。
C-Relu表达式:
。举个例子,理解一下,假设输入C-Relu函数是1,经过非线性映射变为
;假设输入C-Relu函数是-1,经过非线性映射变为
;
-
下图是对所有卷积核寻找其 pair filter(即所有卷积核中选择一个cos相似度最小的卷积核),并计算cos相似度得到蓝色的统计直方图。 红色的曲线是假设随机高斯分布生成的卷积核得到的相似度统计。在第一卷积层,蓝色的直方图分布以-0.5为中心点,对称均匀分布,也就是说有较多成对的滤波器。越到后面的层,蓝色的直方图分布越集中,成对的滤波器越少。也就是说学习到的滤波器存在冗余。由于CNN前几层出现大量负值数据及大量的对称的滤波,ReLU在神经网络的前几层会抹掉定义域为负的值,对此设计了C-ReLU。2019062212.png
低层的滤波器分布存在对称的现象, 所以考虑在低层的网络中采用 CRelu效果会提升很多。
使用CReLU时,要有意识的将滤波器数量减半,否则会将输入的feature-map的数量扩展为两倍, 网络参数将会增加。
C-Relu论文:请点我
5.3.5 ELU (Exponential Linear Units)
为了减少不必要的偏移移位效应,做出如下改变:(i)输入单元的激活可以以零为中心,(ii)可以使用具有负值的激活函数。 介绍一个新的激活函数具有负值,同时保持正参数的特性,即elu。
-
ELU函数表达式:2019062213.png
-
ELU函数图像:2019062214.png
-
ELU导函数图像:2019062215.png
-
elu函数可以加速训练并且可以提高分类的准确率。它有以下特征:
- 1)elu由于其正值特性,可以像relu,lrelu,prelu一样缓解梯度消失的问题。
- 2)相比relu,elu存在负值,可以将激活单元的输出均值往0推近,达到batchnormlization的效果且减少了计算量。(输出均值接近0可以减少偏移效应进而使梯度接近于自然梯度),所以收敛速度更快。
- 3)Lrelu和prelu虽然有负值存在,但是不能确保是一个噪声稳定的去激活状态。Elu左侧软饱性能够让ELU对输入变化或噪声更鲁棒。
- 4)Elu在负值时是一个指数函数,对于输入特征只定性不定量。
Elu论文:请点我
5.3.6 S-Elu (Exponential Linear Units)
上面那个ELU,
要设多少?后来又出现一种新的方法,叫做SELU。它相对于ELU做了一个新的变化:就是现在把每一个值的前面都乘上一个
,然后他会告诉你,
,
应该是多少。
-
S-Elu函数表达式:2019062216.png
-
S-Elu函数图像:2019062217.png
S-Elu函数的超参
,
的值是证明得到的,而并非训练学习得到。
= 1.6732632423543772848170429916717,
= 1.0507009873554804934193349852946
经过该激活函数后,使得样本服从标准正态分布,保证训练过程中梯度不会爆炸或消失,效果比Batch Normalization 要好。S-Elu其实就是ELU乘了个
,关键在于这个
是大于1的。
以前relu,prelu,elu这些激活函数,都是在负半轴坡度平缓,而S-Elu在activation的方差过大的时候可以让它快速减小,防止了梯度爆炸;在正半轴relu,prelu,elu这些激活函数简单的设成了1。而selu的正半轴大于1,在方差过小的的时候可以让它增大,同时防止了梯度消失。这样激活函数就有一个不动点,网络层数很多层以后,每一层的输出都是均值为0和方差为1。
-
推到 S-Elu有两个假设:
- 第一种假设,每一个神经元的input是mean=0,variance=1的i.i.d,不一定是高斯分布。一般在feature应该要先做一下normalize让input服从mean=0,varaince=1的高斯分布。
- 第二种假设,每一个神经元的weight是mean=0,variance=1/K(K是上一层神经元的个数),但是这种假设,没有办法在training的时候保证weight一直都是处于这个状态,但我们至少可以在initialize的时候把他initialize成这个状态,这样子我们到时候train的时候就不会差太多。一般在initialize的时候,让weight是mean=0,variance=1/K,可以通过kernel_initializer='lecun_normal'来实现。
tensorflow里可以直接使用selu,也可以改进elu,具体代码如下.
def selu(x):
with ops.name_scope('elu') as scope:
alpha = 1.6732632423543772848170429916717
scale = 1.0507009873554804934193349852946
return scale*tf.where(x>=0.0, x, alpha*tf.nn.elu(x))
5.4 Softplus 函数
softplus其实就是 sigmoid 函数的原函数,它的导数就是 sigmoid 函数。softplus的函数图像和ReLU有些类似。它出现的比ReLU早,可以视为ReLU的鼻祖。也可以将Softplus看成 Relu 的平滑形式。一开始想要一个指数函数作为激活函数,但是发现线性变换后,数值足够大时,梯度太大了,难以训练,于是外面套了一个对数函数。
Softplus函数表达式:
-
Softplus和Relu函数图像:2019062218.png
-
Softplus优点:
- 相比sigmoid函数,softplus指数运算,计算量少很多。
- 对于深层网络,反向传播时,softplus相对sigmoid函数,不容易出现梯度消失问题。
5.5 Softmax 函数
- Softmax函数常用来最后的一层,并作为输出层进行多分类判别。 它跟二分类在输出层之后一个单元不同的是,使用softmax的输出层拥有多个单元,实际上我们有多少个分类就会有多少个单元,在softmax的作用下每个神经单元都会计算出当前样本属于本类的概率,并且其和等于1。
- 输出层第i个神经元的Softmax函数表达式:
,其中k为类别的个数。
- 用于分类的softmax激活函数,对应的损失函数一般都是用对数似然函数,这样算出来梯度很简洁,也没有sigmoid训练速度慢的问题。
- softmax与sigmoid函数,多分类对比:
- softmax 函数服从多项式分布,sigmoid 函数服从伯努利分布;
- softmax 进行分类时,类与类之间是互斥的;sigmoid 函数进行分类时,类与类之间并不是互斥的;
- softmax 函数多类分类问题,大多数损失函数为categorical_crossentropy,取概率分布中最大的作为最终的分类结果;
- sigmoid 函数在多标签分类中,大多使用binary_crossentropy损失函数,设置一个概率阈值,如果概率值大于阈值,则判定属于该类别符合,会造成一个样本具有多个类别。