前言:相信很多接触过cv的同学都有去研究过激活函数,激活函数相对于一个神经元来说是非常重要的,一个好的激活函数可以让你的模型得到质的飞跃,那到底什么是激活函数?常见的激活函数有哪些?它们的优缺点是什么?
1. 什么是激活函数?
相信大家高中生物都有学过神经系统,其实神经网络借助了生物学对脑神经的研究成果,我们拿一个生物大脑的神经元打个比方~
分叉凸起的部分是树突也叫突触,它用来接收外界传入的电信号,突触包围着的就是神经元,它把突触接收到的信号(多个电信号,类似多个inputs)整合成一个反馈信息。
但是,并不是每一批的电信号都会引起反馈,当输入给神经元的电信号强度不够时,神经元就不会产生任何反应。如果电信号大于某个界限,它就才会出反应,并把它产生的电信号传递给其他神经元。
而如何扩大或缩小电信号,就需要一种类似放大缩小器的东西,神经网络中的激活函数,就充当着这一作用。
另外,神经网络学习能力非常有限,无法去解决非线性问题,叠加简单神经网络解决不了非线性分类问题,而激活函数可以,这也是激活函数存在一大重要意义,就是为了激活神经元。
2. 常见的激活函数
2.1 Sigmoid 激活函数
优点:
- sigmoid 函数的输出范围在 0 和 1 之间。由于输出值介于 0 和 1 之间,因此它标准化了每个神经元的输出。
- 由于任何事物的概率只存在于0 和 1 之间,所以sigmoid 是完美的选择。
- 平滑渐变,防止输出值“跳跃”。
- 该函数是可微的,这意味着,我们可以找到任意两点的 sigmoid 曲线的斜率。
- 明确的预测,即非常接近 1 或 0(要么true,要么false)
缺点:
- 容易出现梯度消失(当sigmoid函数值过高或过低时,导数变得非常小,即 << 1。这会导致梯度消失和深度网络学习不佳。)
- 函数输出不以0为中心,会降低权重更新的效率。 sigmoid 函数执行指数运算,这对计算机来说代价昂贵,速度更慢。
2.2 Tanh双曲正切激活函数![在这里插入图片描述](https://img-blog.csdnimg.cn/2021063016032787.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTgyOTQ2Mg==,size_16,color_FFFFFF,t_70)
Tanh 是一个双曲正切函数。 tanh 函数和 sigmoid 函数的曲线比较相似。但它比 sigmoid 函数有一些优势,具体如下(sigmoid与tanh对比):
特点:
- 首先,当输入或大或小时,两个输出几乎是平滑的,梯度很小,不利于权重更新。不同之处在于输出间隔。tanh的输出区间为(-1,1),整个函数以0为中心,优于sigmoid。
- 在 tanh 图中,负输入将被强映射为负,而零输入被映射为接近零。
2.3 ReLU(Rectified Linear Unit)激活函数
优点:
- 当输入为正时,不存在梯度饱和问题——梯度饱和常常是和激活函数相关的,比如sigmod和tanh就属于典型容易进入梯度饱和区的函数,即自变量进入某个区间后,梯度变化会非常小,表现在图上就是函数曲线进入某些区域后,越来越趋近一条直线,梯度变化很小,梯度饱和会导致训练过程中梯度变化缓慢,从而造成模型训练缓慢)
- 计算速度要快得多。ReLU 函数只有线性关系。无论是向前还是向后,都比sigmoid和tanh快得多。(sigmoid和tanh需要计算指数,会比较慢。)
- 目前很多嵌入式的fp16、int8量化模型都常用relu函数,因为快
缺点:
- Dead ReLU问题——当输入为负数时,ReLU是完全不活动的,也就是说一旦输入一个负数,ReLU就会死亡。在前向传播过程中,出现这类问题的影响比较小。但是在反向传播过程中,如果输入负数,梯度将完全为零,这与sigmoid函数和tanh函数有同样的问题。
- ReLU函数的输出要么是0要么是正数,说明ReLU函数不是以0为中心的函数。
2.4 Leaky ReLU 激活函数
优点(相比relu):
- Leaky ReLU通过将x的非常小的线性分量赋予负输入(通常a=0.01)来调整负值的零梯度问题。 Leaky ReLU有助于增加
- ReLU 函数的范围,值域由0到正无穷→负无穷到正无穷
注:理论上,Leaky ReLU 具有 ReLU 的所有优点,加上 Dead ReLU 不会有任何问题,但在实际操作中,并没有充分证明 Leaky ReLU 总是优于 ReLU。不过,用过YOLO系列的朋友对这个函数再熟悉不过了,在tiny版本可以经常看到这个函数。
2.5 ELU指数线性激活函数
优点(相对于Leaky ReLU和ReLU而言):
- 没有 Dead ReLU问题,输出的均值接近于 0,以0为中心。
- ELU 通过减少偏置偏移的影响,使正常梯度更接近于单位自然梯度,从而使均值向零加速学习
- ELU 在输入较小的情况下饱和为负值,从而减少前向传播的信息变化。
2.6 PRelu(Parametric ReLU)激活函数
参数α一般是0到1之间的一个数,一般比较小,0.01就变成了leaky relu函数。
- 如果 α =0, f(x) 变成 ReLU
- 如果 α=0.01,f(x)成为leaky relu
- 如果 α 是可学习参数,则 f(x) 变为 PReLU
优点:
- 在负区域,PReLU有一个小斜率,也可以避免Dead ReLU的问题。
- 与 ELU 相比,PReLU 是负区域的线性运算。斜率虽小,但并不趋向于0,这是有一定优势的,a可根据网络进行调整,相比其他rule衍生系列更具灵活性。
2.7 Softmax激活函数
这个真找不到图,有待大佬的补充。。。。。
Softmax用作多类分类问题的激活函数,对于长度为 K 的任意实向量,Softmax 可以将其压缩为一个长度为 K 的实向量,其值在(0, 1) 范围内,向量中元素之和为 1。
Sigmoid =多标签分类问题=多个正确答案=非独占输出(例如胸部X光检查、住院)。构建分类器,解决有多个正确答案的问题时,用Sigmoid函数分别处理各个原始输出值。
Softmax =多类别分类问题=只有一个正确答案=互斥输出(例如手写数字,鸢尾花)。构建分类器,解决只有唯一正确答案的问题时,用Softmax函数处理各个原始输出值。Softmax函数的分母综合了原始输出值的所有因素,这意味着,Softmax函数得到的不同概率之间相互关联。
softmax与sigmoid函数的区别:
- 如果模型输出为非互斥类别,且可以同时选择多个类别,则采用Sigmoid函数计算该网络的原始输出值。
- 如果模型输出为互斥类别,且只能选择一个类别,则采用Softmax函数计算该网络的原始输出值。
- Sigmoid函数可以用来解决多标签问题(山羊既是羊又是动物),Softmax函数用来解决单标签问题(人脸ID确认常见)。
- 对于某个分类场景,当Softmax函数能用时,Sigmoid函数一定可以用(取top-1)
2.8 Swish激活函数(YOLOv5中为SiLU函数)
Swish 的设计受到了 LSTM 和高速网络中 gating 的 sigmoid 函数使用的启发。我们使用相同的 gating 值来简化 gating 机制,这称为 self-gating(自控)。
self-gating 的优点在于它只需要简单的标量输入,而普通的 gating 则需要多个标量输入。这使得诸如 Swish 之类的 self-gated 激活函数能够轻松替换以单个标量为输入的激活函数(例如 ReLU),而无需更改隐藏容量或参数数量。
优点:
- 「无界性」有助于防止慢速训练期间,梯度逐渐接近 0
并导致饱和;(同时,有界性也是有优势的,因为有界激活函数可以具有很强的正则化,并且较大的负输入问题也能解决); - 平滑度在优化和泛化中起了重要作用。
2.9 Maxout激活函数
maxout激活函数并不是一个固定的函数,不像Sigmod、Relu、Tanh等函数,是一个固定的函数方程,它是一个可学习的激活函数,因为我们的参数是学习变化的,它是一个分段线性函数,如下所示。
在 Maxout 层,激活函数是输入的最大值,因此只有 2 个 maxout 节点的多层感知机就可以拟合任意的凸函数
凸函数是数学函数的一类特征。凸函数就是一个定义在某个向量空间的凸子集C(在欧氏空间中,凸集是对于集合内的每一对点,连接该对点的直线段上的每个点也在该集合内)上的实值函数。
单个 Maxout 节点可以解释为对一个实值函数进行分段线性近似 (PWL) ,其中函数图上任意两点之间的线段位于图(凸函数)的上方。
假设两个凸函数 h_1(x) 和 h_2(x),由两个 Maxout 节点近似化,函数 g(x) 是连续的 PWL 函数。
因此,由两个 Maxout 节点组成的 Maxout 层可以很好地近似任何连续函数。
那到底什么是逼近?
任何一个凸函数,都可以由线性分段函数进行逼近近似。其实我们可以把以前所学到的激活函数:relu、abs激活函数,看成是分成两段的线性函数,如下示意图所示
maxout的拟合能力是非常强的,它可以拟合任意的的凸函数。最直观的解释就是任意的凸函数都可以由分段线性函数以任意精度拟合(学过高等数学应该能明白),而maxout又是取k个隐隐含层节点的最大值,这些”隐隐含层"节点也是线性的,所以在不同的取值范围下,最大值也可以看做是分段线性的(分段的个数与k值有关)
2.10 hard-Swish激活函数
卷积之后通常会接一个 ReLU 非线性激活,ReLU6 就是普通的ReLU,但是限制最大输出为 6,这是为了在移动端设备 float16/int8 的低精度的时候也能有很好的数值分辨率。如果对 ReLU 的激活范围不加限制,输出范围为 0 到正无穷,如果激活值非常大,分布在一个很大的范围内,则低精度的 float16/int8 无法很好地精确描述如此大范围的数值,会带来精度损失。下图是ReLU和ReLU6的函数曲线图。
Hard-Swish函数相比Swish函数的优点:
paper:https://arxiv.org/pdf/1905.02244.pdf
- 在论文中,作者提到,虽然这种Swish非线性提高了精度,但是在嵌入式环境中,他的计算成本是昂贵的,因为在移动设备上要比计算sigmoid函数代价要大得多。
- 作者使用hard-Swish和hard-Sigmoid替换了ReLU6和SE-block中的Sigmoid层,但是只是在网络的后半段才将ReLU6替换为h-Swish,因为作者发现Swish函数只有在更深的网络层使用才能体现其优势。
- 在量化模式下,Sigmoid函数比ReLU6的计算代价大的多,所以才有了这个ReLU6版本的h-Swish。
2.11 hard-Swish激活函数
优点:
- 至上无边界(即正值可以达到任何高度)避免了由于封顶而导致的饱和。
- 理论上对负值的轻微允许允许更好的梯度流,而不是像ReLU中那样的硬零边界(RuLU Dead的情况)。
- 平滑的激活函数允许更好的信息深入神经网络,从而得到更好的准确性和泛化。
缺点:
- 计算量肯定比relu大,占用的内存也多了不少
YOLOv4使用了Mish函数作为激活函数,确实有涨点功效:
参考:
[1] https://medium.com/analytics-vidhya/activation-functions-all-you-need-to-know-355a850d025e
[2] https://en.wikipedia.org/wiki/Activation_function
[3]https://github.com/ultralytics/yolov5/blob/31336075609a3fbcb4afe398eba2967b22056bfa/utils/activations.py%23L30