激活函数
接触机器学习大概一年多了,自己对于激活函数感觉还是停留在表面,因此想重新学习一下,加深一下对于“激活函数”的理解。
文章目录
前言
假设有一个问题,对如下面这样的图片进行一个二分类的任务,没用激活函数,该如何拟合出一条曲线呢?(默认做不到!)
再考虑一个矩阵运算(毕竟我们使用的神经网络的运算过程就是比较复杂的矩阵运算过程):
转化得:
我们对 x 作多次线性变换得到最终的输出 y:
用图像表示为:
大家是不是看着有点眼熟?这不就是多层感知机吗,
h2,h1,h3可以描述为关于x的线性函数,也称之为神经元。接收上一层发出的信号 x,进行运算后将结果信号传递到下一层与其连接的神经元。如果某一层的任意神经元都分别连接到上一层的所有神经元,则该层称为全连接层。全连接层的每一个神经元节点都与上一层的所有神经元节点相连,相当于一个线性函数进行了一次线性变换(映射),所以神经网络(不带激活函数)就相当于进行着一次又一次的线性变换,那么对于一个非线性的分类任务(举个例子而已),它又如何去完成呢?–答案已经呼之欲出了!
上面我们已经得到了此矩阵运算的一个式子:
以Sigmoid激活函数为例进行探讨,公式如下:
假如只有一个隐藏层,激活函数接在当前隐藏层后面,带入激活函数的式子,则计算得输出y为:
假设隐藏层有 N 个神经元且当前层的输出 y 为实数,则 y 可以表示为如下形式;
不要去追究细节,要去理解整体(因为涉及到许多的矩阵变换),大家可以认为这就是一个通用的近似器,能够近似拟合任何函数,因为当引入了类似于Sigmoid这样的非线性函数,神经网络就不在是一个一个的线性组合了,可以看出输出y很明显就是一个非线性函数!能不能解决一开始的非线性二分类问题不清楚,但是至少说明有可能!(其实在我们学的数学中就可以知道,有各种各样的曲线,但只要你的函数多项式够复杂,就能够得到近似的曲线,是这样的吧?)–Sigmoid激活函数曲线如下:
总结:相信大家通过上述的一个梳理过程,已经大概了解激活函数为什么要使用?以及激活函数在神经网络中如何使用的一个过程。(后面的改进主要在于解决各种各样的激活函数运用于网络搭建所产生的一系列问题,而激活函数的一个具体的计算就是上述的大概过程)
激活函数
经过上述的讨论可以得出激活函数的大概定义了,定义如下(引用自tyhj_sf
):
神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数(又称激励函数)
为什么需要激活函数?
经过上述的讨论也可以得出激活函数的大概用途(引用自tyhj_sf
):
如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下你每一层节点的输入都是上层输出的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数
二、各种激活函数的介绍
Sigmoid
在sigmoid函数中我们可以看到,其输出是在(0,1)这个开区间内,这点很有意思,可以联想到概率,但是严格意义上讲,不要当成概率。sigmoid函数曾经是比较流行的,它可以想象成一个神经元的放电率,在中间斜率比较大的地方是神经元的敏感区(也就是sigmoid函数实际起作用的区域),在两边斜率很平缓的地方是神经元的抑制区(就是饱和区域–梯度趋于0)。
当然,流行也是曾经流行,这说明函数本身是有一定的缺陷的。
-
当输入稍微远离了坐标原点,函数的梯度就变得很小了,几乎为零。在神经网络反向传播的过程中,我们都是通过微分的链式法则来计算各个权重w的微分的。当反向传播经过了sigmoid函数,这个链条上的微分就很小很小了,况且还可能经过很多个sigmoid函数,最后会导致权重w对损失函数几乎没影响,这样不利于权重的优化,这个问题叫做梯度消失(弥散)。
-
函数输出不是以0为中心的,这样会使权重更新效率降低。对于这个缺陷,在斯坦福的课程里面有详细的解释(解释如下-仅供参考)。
解释:假设我们有一个多层的sigmoid神经网络,如果你的输入x都是正数,然后sigmoid不关于原点对称的输出值都集中在0和1之间,那么在反向传播中w的梯度会传播到网络的某一处,那么权值的变化是要么全正要么全负,也就是说权值范围只能分别位于图中一三象限,即梯度更新的方向只能在一三象限,当我们想要输入一三象限区域以外的点时,我们将会得到这种并不理想的红色曲折路线(zig zag path)(因为梯度更新允许的方向在一三象限),图中红色曲折路线,收敛速度变得非常缓慢。
- sigmoid函数要进行指数运算,这个对于计算机来说是比较慢的。
softmax与sigmoid的区别:
简单理解:sigmoid针对标量,softmax针对向量。都是将任意的实数值映射到(0,1)区间内的小数
softmax一般用于多分类的结果,一般和one-hot的真实标签值配合使用,大多数用于网络的最后一层;而sigmoid是原本一种隐层之间的激活函数,但是因为效果比其他激活函数差,目前一般也只会出现在二分类的输出层中,与0 1真实标签配合使用
tanh
tanh是双曲正切函数,tanh函数和sigmoid函数的曲线是比较相近的,咱们来比较一下看看。首先相同的是,这两个函数在输入很大或是很小的时候,输出都几乎平滑,梯度很小,不利于权重更新;不同的是输出区间,tanh的输出区间是在(-1,1)之间,而且整个函数是以0为中心的,这个特点比sigmoid的好。
一般二分类问题中,隐藏层用tanh函数,输出层用sigmoid函数(为什么?)。不过这些也都不是一成不变的,具体使用什么激活函数,还是要根据具体的问题来具体分析,还是要靠调试的
为什么RNN中常用tanh函数作为激活函数而不是ReLU?
RNN中将tanh函数作为激活函数本身就存在梯度消失的问题,而ReLU本就是为了克服梯度消失问题而生的,那为什么不能直接(注意:这里说的是直接替代,事实上通过截断优化ReLU仍可以在RNN中取得很好的表现)用ReLU来代替RNN中的tanh来作为激活函数呢?这是因为ReLU的导数只能为0或1,而导数为1的时候在RNN中很容易造成梯度爆炸问题。因为在RNN中,每个神经元在不同的时刻都共享一个参数W,因此在前向和反向传播中,每个神经元的输出都会作为下一个时刻本神经元的输入,从某种意义上来讲相当于对其参数矩阵W作了连乘,如果W中有其中一个特征值大于1,则多次累乘之后的结果将非常大,自然就产生了梯度爆炸的问题。
那为什么ReLU在CNN中不存在连乘的梯度爆炸问题呢?,因为在CNN中,每一层都有不同的参数w,有的特征值大于1,有的小于1,在某种意义上可以理解为抵消了梯度爆炸的可能。
ReLU、Leaky ReLU、PReLU、RReLU
ReLU计算公式:
Leaky ReLU计算公式:
PReLU计算公式:
RReLU计算公式:
ReLU优点:
1.**不会发生梯度消失(梯度爆炸呢?)**问题。Sigmoid函数在 x>0 会发生梯度消失问题,造成信息损失,从而无法完成深度网络的训练。而 ReLU 函数当 x>0 为线性结构,有固定的梯度,不会消失。
2.ReLU激活函数在 x<0 时会输出为0(失活),这可以造成网络的稀疏性。这样可以很好的模拟人脑神经元工作的原理,且可以减少参数间的相互依赖,缓解了过拟合问题的发生。
稀疏性:神经元数量少,通常分散在很大的区域。在神经网络中,这意味着激活的矩阵含有许多 0。这种稀疏性能让我们得到什么?当某个比例(比如 50%)的激活饱和时,我们就称这个神经网络是稀疏的。这能提升时间和空间复杂度方面的效率——常数值(通常)所需空间更少,计算成本也更低。Yoshua Bengio 等人发现 ReLU 这种分量实际上能让神经网络表现更好,而且还有前面提到的时间和空间方面的效率
3.Sigmoid/tanh 函数复杂,指数运算,计算量大(前向传播+反向传播求导),速度慢;而ReLU函数简单,计算量小,速度快。
ReLU缺点:
1.(重要)ReLU在训练的时候很”脆弱”,很可能产生 Dead ReLU Problem(神经元坏死现象):某些神经元可能永远不会被激活,导致相应参数永远不会被更新(在负数部分,梯度为0)。举个例子:由于ReLU在x<0时梯度为0,这样就导致负的梯度在这个ReLU被置零,而且这个神经元有可能再也不会被任何数据激活。如果这个情况发生了,那么这个神经元之后的梯度就永远是0了,也就是ReLU神经元坏死了,不再对任何数据有所响应。
2.输出不是以0为中心的——改动了输入数据的分布,下一层输入数据的分布跟前一层输入数据分布不同,会大大降低模型的训练速度,因为需要不断的适应不同的输入分布,拖慢了训练速度(这个和sigmoid那的解释是一个意思吗?)
3.ReLU不会对数据做幅度压缩,所以数据的幅度会随着模型层数的增加不断扩张(这意思是???)
4.由于激活函数是没有上界的,有可能出现神经网络输出为NaN的情况
正是为了解决上面的 Dead ReLU Problem(神经元坏死现象),先后提出了Leaky ReLU、PReLU、RReLU三种方法,在 x<0 部分不武断的赋为0,而是给它一个很小的斜率,这样可以有效的缓解/解决这个问题。Leaky ReLU及其变体(PReLU、RReLU)的性能都要优于ReLU激活函数(有论文在较小的数据集上证明了,而在大数据集上则不一定);而RReLU由于具有良好的训练随机性,可以很好的防止过拟合。
————————————————
版权声明:ReLU、Leaky ReLU、PReLU、RReLU激活函数介绍为CSDN博主「满船清梦压星河HK」的原创文章
原文链接:https://blog.csdn.net/qq_38253797/article/details/119030643
relu在0的位置可导吗,不可导怎么处理?
对于relu函数,当x>0时,导数为1,当x<0时导数为0。因此relu函数在x=0的次梯度c ∈ [ 0 , 1 ] c\in[0,1]c∈[0,1],c可以取[0,1]之间的任意值,通常可以取0。
神经网络反向求导不可导情况处理
Swish/SiLU
Swish是使用自动搜索技术自动的搜索最佳的激活函数(多个一元或者二元函数组合)。暴力搜索出来的,并没有解释为什么好。
Swish优点:(**)
1.无上界(避免梯度饱和:比如sigmoid,tanh激活函数通常存在梯度饱和问题,在两边极限情况下,梯度趋近于1)
2.有下界(产生更强的正则化效果:并不是像relu函数那样完全截断而是允许比较小的负梯度流入从而保证信息流动,当输入为负时,通过梯度下降反向传播时,梯度不为0)
3.平滑(处处可导 更容易训练–反向:梯度下降效果更好,正向传播:平滑的激活函数允许更好的信息深入神经网络,从而得到更好的准确性和泛化)
4.x<0具有非单调性(对分布有重要意义 这点也是Swish和ReLU的最大区别 不太理解!!!)
搜索总结了一些激活函数的设计准则:
1.复杂的激活函数性能始终要低于简单的激活函数的性能。可能是因为复杂的激活函数优化难度增加。最好的激活函数一般都是由一到两个核心单元组成。
2.一般使用原始预激活x(raw preactivation x)作为最终的二元函数的输入效果会比较好。
3.使用除法的效果一般都会比较差,因为一旦分母趋于0时输出就会爆炸(梯度爆炸)。
4.常常会使用一些周期函数(periodic functions),如 sin 或 cos等。
h-Swish
Mish
一种新型的自正则化的非单调激活函数
优点:
无上界,非饱和,避免了因饱和而导致梯度为0(梯度消失/梯度爆炸),进而导致训练速度大大下降;
有下界,在负半轴有较小的权重,可以防止ReLU函数出现的神经元坏死现象;同时可以产生更强的正则化效果(不理解!!!);
自身本就具有自正则化效果(公式可以推导),可以使梯度和函数本身更加平滑(Smooth),且是每个点几乎都是平滑的,这就更容易优化而且也可以更好的泛化(为啥呀!!)。随着网络越深,信息可以更深入的流动。
x<0,保留了少量的负信息,避免了ReLU的Dying ReLU现象,这有利于更好的表达和信息流动。
4.x<0具有非单调性(对分布有重要意义 这点也是Mish和ReLU的最大区别 不太理解!!!)
AconC、meta-AconC–自适应控制激活
下图a是ACON-C的函数图像随 p1 和 p2变化的情况(p1和p2使用的是两个可学习参数来自适应调整):
论文主要工作(这就是它的优点吧!):
1.提出一种新颖的Swish函数解释:Swish函数是ReLU函数的平滑近似(Smooth maximum)。
2.基于这个发现,论文进一步分析ReLU的一般形式Maxout系列激活函数,再次利用Smoth maximum将Maxout系列扩展得到简单且有效的ACON系列激活函数:ACON-A、ACON-B、ACON-C;
3.提出meta-ACON,动态的学习(自适应)激活函数的线性/非线性,显著提高了表现。另外还证明了ACON的参数 P1 和 P2 负责控制函数的上下限(这个对最终效果由很大的意义);参数 β负责动态的控制激活函数属于线性/非线性(如下图)。
未完待续!!!
更全的激活函数列举
深度学习—激活函数详解(Sigmoid、tanh、ReLU、ReLU6及变体P-R-Leaky、ELU、SELU、Swish、Mish、Maxout、hard-sigmoid、hard-swish)
参考资料
CSDN 满船清梦压星河HK-【YOLOV5-5.x 源码解读】activations.py
CSDN tyhj_sf-常用激活函数(激励函数)理解与总结
CSDN 一文详解神经网络与激活函数的基本原理
CSDN 斯坦福cs231n学习笔记(7)------神经网络训练细节(激活函数)
知乎 机器之心 机器之心-激活函数介绍