一、sigmoid( Logistic function)
公式:
图像:
特点:它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1。
缺点:
1.在深度神经网络中梯度反向传递时导致梯度爆炸和梯度消失,其中梯度爆炸发生的概率非常小,而梯度消失发生的概率比较大。
2. 其解析式中含有幂运算,计算机求解时相对来讲比较耗时。对于规模比较大的深度网络,这会较大地增加训练时间。
二、Hard Sigmoid
公式:
图像:
特点:是 Logistic Sigmoid 激活函数的分段线性近似。它更易计算,这使得学习计算的速度更快,尽管首次派生值为零可能导致静默神经元/过慢的学习速率(详见 ReLU)。
三、Symmetrical Sigmoid
公式:
图像:
特点:Symmetrical Sigmoid是另一个Tanh 激活函数的变种(实际上,它相当于输入减半的 Tanh) 。和 Tanh一样,它是反对称的、零中心、可微分的,值域在-1到1之间。它更平坦的形状和更慢的下降派生表明它可以更有效地进行学习。
四、 Signum(或者简写为 Sign)
公式:
图像:
特点:是二值阶跃激活函数的扩展版本。它的值域为 [-1,1],原点值是 0。尽管缺少阶跃函数的生物动机,Signum 依然是反对称的,这对激活函数来说是一个有利的特征。
五、Hyperbolic Tangent (tanh)
公式:
/
图像:
特点:
1.解决了Sigmoid函数的不是zero-centered输出问题,然而,梯度消失(gradient vanishing)的问题和幂运算的问题仍然存在。
2.与 sigmoid 函数相比,使用 tanh 函数的一个优点是 tanh 函数以零为中心。这使得优化过程更加容易。
3.tanh 函数的梯度比 sigmoid 函数的梯度更陡
tanh替代选择:Softsign
Softsign 是 Tanh 激活函数的另一个替代选择。就像 Tanh 一样,Softsign 是反对称、去中心、可微分,并返回-1 和 1 之间的值。其更平坦的曲线与更慢的下降导数表明它可以更高效地学习。另一方面,导数的计算比 Tanh 更麻烦。
六、The ReLU family
1. Rectified Linear Unit (ReLU)
公式:
图像:
特点:
1) 解决了gradient vanishing问题 (在正区间)
2)计算速度非常快,只需要判断输入是否大于0
3)收敛速度远快于sigmoid和tanh
ReLU也有几个需要特别注意的问题:
1)ReLU的输出不是zero-centered
2)Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生: (1) 非常不幸的参数初始化,这种情况比较少见 (2) learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
尽管存在这两个问题,ReLU目前仍是最常用的activation function,在搭建人工神经网络的时候推荐优先尝试!
原文链接:https://blog.csdn.net/tyhj_sf/article/details/79932893
2. Leaky Rectified Linear Unit (Leaky ReLU)
图像:
特点:人们为了解决Dead ReLU Problem,提出了将ReLU的前半段设为α x而非0,通常α =0.01。另外一种直观的想法是基于参数的方法,即,其中α 可由方向传播算法学出来。理论上来讲,Leaky ReLU有ReLU的所有优点,外加不会有Dead ReLU问题,但是在实际操作当中,并没有完全证明Leaky ReLU总是好于ReLU。
3. Parametric Rectified Linear Unit (PReLU)
公式:
图像:
特点:如果ai=0,那么PReLU退化为ReLU;如果ai是一个很小的固定值(如ai=0.01),则PReLU退化为Leaky ReLU(LReLU)。 有实验证明,与ReLU相比,LReLU对最终的结果几乎没什么影响。
链接:https://www.jianshu.com/p/d49905dee072
4. Exponential Linear Unit (ELU)
公式:
图像:
特点:
(右侧的线性部分能够缓解梯度消失,左侧的软饱和能够对于输入变化鲁棒.而且收敛速度更快。)
1.不会有Dead ReLU问题
2.输出的均值接近0,zero-centered
计算量稍大。类似于Leaky ReLU,理论上虽然好于ReLU,但在实际使用中目前并没有好的证据ELU总是优于ReLU。
3.ELU包含了ReLU的所有优点。
来源:神经网络常见的激活函数汇总_神经网络激活函数-CSDN博客
5. S-shaped Rectified Linear Activation Unit,SReLU) 、FReLU、AReLU、
来源:https://www.ai2news.com/paper/1512.07030/
6.ReLU代替选择:SoftPlus
公式:
图像:
特点: 能够返回任何大于 0 的值。与 ReLU 不同,SoftPlus 的导数是连续的、非零的,无处不在,从而防止出现静默神经元。然而,SoftPlus 另一个不同于 ReLU 的地方在于其不对称性,不以零为中心,这兴许会妨碍学习。此外,由于导数常常小于 1,也可能出现梯度消失的问题。
Softplus函数可以看作是ReLU函数的平滑。根据神经科学家的相关研究,Softplus函数和ReLU函数与脑神经元激活频率函数有神似的地方。也就是说,相比于早期的激活函数,Softplus函数和ReLU函数更加接近脑神经元的激活模型,而神经网络正是基于脑神经科学发展而来,这两个激活函数的应用促成了神经网络研究的新浪潮
原文链接:https://blog.csdn.net/hy592070616/article/details/120623303
7.SiLU(也叫做Swish函数)具体看下面的Swish
8. Relu6
公式
图像:
特点:
1.ReLU 和 ReLU6 之间的主要区别在于,ReLU 允许正侧的值非常高,而 ReLU6 限制为正侧的值 6。 任何 6 或大于 6 的输入值都将被限制为值 6(因此得名)。
2.ReLU6 函数由三个线性分量组成。 它是一个非线性函数
比较有意思的是,为什么是6,不是7或者其他呢?结合原文的说明,可能是作者尝试了多种,ReLU6 效果最好。
七、 Identity
公式:
图像:
特点:
1.这也被称为线性激活函数。
2.当我们讨论激活函数时,这是唯一一个被认为是线性函数的函数。
3.这个函数按原样输出输入值。对输入不做任何更改。
用法:
该函数仅用于解决回归问题的神经网络模型的输出层。
不要在隐藏层中使用这个函数。
八、 Bent Identity
公式:
图像:
特点:激活函数 Bent Identity 是介于 Identity 与 ReLU 之间的一种折衷选择。它允许非线性行为,尽管其非零导数有效提升了学习并克服了与 ReLU 相关的静默神经元的问题。由于其导数可在 1 的任意一侧返回值,因此它可能容易受到梯度爆炸和消失的影响。
九、Exponential Linear Unit(ELU)
公式:
图像:
特点:
ELU 主要是对小于等于 0 的部分进行了改进,使得函数在 x = 0 处可导, 而且 使得神经元的平均激活均值趋近为 0,对噪声更具有鲁棒性。
缺点是由于又引入了指数,计算量增大了。
十、Gaussian Error Linear Unit (GELU)高斯误差线性单元
公式:
我们可以用GELU来近似
/
特点:它一种高性能的神经网络激活函数。GELU的非线性是随机正则化器的预期变换,随机正则化器(防止过拟合)将等式或零映射随机应用于神经元的输入。GELU的非线性按其幅度输入,而不是按照ReLU中的符号进行门控输入
来源:https://blog.csdn.net/qq_28385535/article/details/89839154?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171206365116800186544984%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171206365116800186544984&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-89839154-null-null.nonecase&utm_term=GELU&spm=1018.2226.3001.4450
八、Swish
公式:
图像:
特点:
- 该函数是通过将 sigmoid 函数乘以输入 z 构成的。
- 这是一个非线性函数。
- 该图与 ReLU 激活函数的图非常相似。
- 曲线比 ReLU 激活函数更平滑。 在训练模型时,这种平滑度很重要。 该函数在训练时很容易收敛。
用法:
- 仅在隐藏层中使用。
- 不在神经网络模型的输出层使用这个函数。
缺点:
- Swish 函数的主要缺点是计算量很大,因为函数中包含了 e^z 项。 这可以通过使用下面定义的称为“Hard Swish”的特殊函数来避免。
来源:https://zhuanlan.zhihu.com/p/460177194
十一、HardSwish
公式:
/
图像:
特点:HardSwish平滑地在Re LU和线性函数之间进行了非线性差值。HardSwish的属性与Swish相似,但非线性提高了精度。因为它们都是上下无界的,它是非单调的。该函数与Swish相比,它的计算速度更快。
十二、Gaussian
图像:
特点:高斯激活函数(Gaussian)并不是径向基函数网络(RBFN)中常用的高斯核函数,高斯激活函数在多层感知机类的模型中并不是很流行。该函数处处可微且为偶函数,但一阶导会很快收敛到零
十三、 Absolute
公式:
图像:
特点:绝对值(Absolute)激活函数返回输入的绝对值。该函数的导数除了零点外处处有定义,且导数的量值处处为 1。这种激活函数一定不会出现梯度爆炸或消失的情况
十四、 Sinusoid
公式:
图像:
特点:Sinusoid(或简单正弦函数)激活函数为神经网络引入了周期性。该函数的值域为 [-1,1],且导数处处连续。此外,Sinusoid 激活函数为零点对称的奇函数。
十五、Cos
公式:
图像:
特点:如同正弦函数,余弦激活函数(Cos/Cosine)为神经网络引入了周期性。它的值域为 [-1,1],且导数处处连续。和 Sinusoid 函数不同,余弦函数为不以零点对称的偶函数。
十六、Sinc
公式:
图像:
特点:Sinc 函数(全称是 Cardinal Sine)在信号处理中尤为重要,因为它表征了矩形函数的傅立叶变换(Fourier transform)。作为一种激活函数,它的优势在于处处可微和对称的特性,不过它比较容易产生梯度消失的问题。
十七、Log Log
公式:
图像:
十八、Mish
公式:
图像:
特点:
重点对比了 Mish 和 Swish,结论是 Mish 更牛逼。但是 YOLO v5 用的 Swish。
十九、Softmax
公式:
特点:Softmax 函数可视为 Sigmoid 函数的泛化形式, 其本质就是将一个 K 维的任意实数向量压缩(映射)成另一个 K 维的实数向量, 其中向量中的每个元素的取值范围都介于 [ 0 , 1 ] [0,1][0,1] 之间(可以理解为概率)。Softmax 常常是作为多分类神经网络的输出,比如 LeNet-5 中就用Softmax 映射到最后的输入结果,其表示1~10的概率。
原文链接:https://blog.csdn.net/kuweicai/article/details/93926393
部分绘制激活函数代码
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import math
def single_sigmoid(x):
return 1/(1 + np.e**(-x))
def sigmoid(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
y[i] = single_sigmoid(ele)
return y
def swish(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
y[i] = single_sigmoid(ele)*ele
return y
def swish_d1(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
temp = single_sigmoid(ele)
y[i] = temp + ele * temp * (1-temp)
return y
def hard_sigmoid(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
if ele < -2.5:
y[i] = 0
elif ele > 2.5:
y[i] = 1
else:
y[i] = 0.2 * ele + 0.5
return y
def hard_sigmoid_d1(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
if ele < -2.5:
y[i] = 0
elif ele > 2.5:
y[i] = 0
else:
y[i] = 0.2
return y
def relu6(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
if ele < 0:
y[i] = 0
elif ele > 6:
y[i] = 6
else:
y[i] = ele
return y
def relu6_d(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
if ele < 0:
y[i] = 0
elif ele > 6:
y[i] = 0
else:
y[i] = 1
return y
def hardswish(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
if ele < -3:
y[i] = 0
elif ele > 3:
y[i] = ele
else:
y[i] = ele*(ele+3)/6
return y
def hardswish_d(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
if ele < -3:
y[i] = 0
elif ele > 3:
y[i] = 1
else:
y[i] = ele/3 + 0.5
return y
def tanh(k):
a = np.e**(k)
b = np.e**(-k)
return (a - b)/(a+b)
def mish(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
y[i] = ele * tanh(math.log(1 + np.e**ele))
return y
def mish_d(x):
y = np.zeros_like(x)
for i, ele in enumerate(x):
n = np.e**ele
m = math.log(1 + n)
y[i] = ele * (1 - (tanh(m))**2) * n /(1 + n) + tanh(m)
return y
def draw(X, *args):
plt.figure(figsize=(8, 5), dpi=80)
ax = plt.subplot(111)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
color = ['blue', 'red', 'green', 'yellow', 'brown']
for i, F in enumerate(args):
clr = color[i%6]
Y = F(X)
plt.plot(X, Y, color=clr, linewidth=2.5, linestyle="-", label=F.__name__)
plt.xlim(X.min()*1.1, X.max()*1.1)
plt.ylim(Y.min()*4, Y.max()*1.1)
plt.legend(loc='upper left', frameon=False)
#
# t = 2*np.pi/3
# plt.plot([t,t],[0,np.cos(t)],
# color ='blue', linewidth=1.5, linestyle="--")
# plt.scatter([t,],[np.cos(t),], 50, color ='blue')
# plt.annotate(r'$\sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$',
# xy=(t, np.sin(t)), xycoords='data',
# xytext=(+10, +30), textcoords='offset points', fontsize=16,
# arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
#
# plt.plot([t,t],[0,np.sin(t)],
# color ='red', linewidth=1.5, linestyle="--")
# plt.scatter([t,],[np.sin(t),], 50, color ='red')
# plt.annotate(r'$\cos(\frac{2\pi}{3})=-\frac{1}{2}$',
# xy=(t, np.cos(t)), xycoords='data',
# xytext=(-90, -50), textcoords='offset points', fontsize=16,
# arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
#
#
# plt.savefig("exercice_10.png",dpi=72)
plt.show()
if __name__ == '__main__':
x = np.linspace(-10, 10, 500, endpoint=True)
# draw(x, hard_sigmoid, hard_sigmoid_d1)
# draw(x, relu6, relu6_d)
# draw(x, hardswish)
draw(x, mish, mish_d)