参考博文:

1.激活函数介绍

2.pytorch激活函数官方文档)

什么是激活函数

活函数(Activation functions)对于神经网络模型学习与理解复杂和非线性的函数来说具有十分重要的作用。它们将非线性特性引入到我们的网络中。

如果网络中不使用激活函数,网络每一层的输出都是上层输入的线性组合,无论神经网络有多少层,输出都是输入的线性组合。

如果使用的话,激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,此时神经网络就可以应用到各类非线性场景当中了。

常见的激活函数如sigmoid、tanh、relu等,它们的输入输出映射均为非线性,这样才可以给网络赋予非线性逼近能力。

常用的激活函数

sigmoid

Sigmoid函数是一个在生物学中常见的S型函数,它能够把输入的连续实值变换为0和1之间的输出,如果输入是特别小的负数,则输出为0,如果输入是特别大的正数,则输出为1。即将输入量映射到0到1之间。

Sigmoid可以作为非线性激活函数赋予网络非线性区分能力,也可以用来做二分类。其计算公式为:

优点:

1.曲线过渡平滑,处处可导;
缺点:

1.幂函数运算较慢,激活函数计算量大;
2.求取反向梯度时,Sigmoid的梯度在饱和区域非常平缓,很容易造称梯度消失的问题,减缓收敛速度。

Tanh

Tanh是一个奇函数,它能够把输入的连续实值变换为-1和1之间的输出如果输入是特别小的负数,则输出为-1,如果输入是特别大的正数,则输出为1解决了Sigmoid函数的不是0均值的问题。

在这里插入图片描述

Tanh可以作为非线性激活函数赋予网络非线性区分能力。其计算公式为:

优点:

1.曲线过渡平滑,处处可导;
2.具有良好的对称性,网络是0均值的。
缺点:

1.与Sigmoid类似,幂函数运算较慢,激活函数计算量大;
2.与Sigmoid类似,求取反向梯度时,Tanh的梯度在饱和区域非常平缓,很容易造称梯度消失的问题,减缓收敛速度。

Relu

线性整流函数(Rectified Linear Unit, ReLU),是一种深度神经网络中常用的激活函数,整个函数可以分为两部分,在小于0的部分,激活函数的输出为0;在大于0的部分,激活函数的输出为输入

在这里插入图片描述

计算公式为:

优点:

1.收敛速度快,不存在饱和区间,在大于0的部分梯度固定为1,有效解决了Sigmoid中存在的梯度消失的问题;
2.计算速度快,ReLU只需要一个阈值就可以得到激活值,而不用去算一大堆复杂的指数运算,具有类生物性质。
缺点:

1.它在训练时可能会“死掉”。如果一个非常大的梯度经过一个ReLU神经元,更新过参数之后,这个神经元的的值都小于0,此时ReLU再也不会对任何数据有激活现象了。如果这种情况发生,那么从此所有流过这个神经元的梯度将都变成 0。合理设置学习率,会降低这种情况的发生概率。

Swish

Swish是Sigmoid和ReLU的改进版,类似于ReLU和Sigmoid的结合,β是个常数或可训练的参数。Swish 具备无上界有下界、平滑、非单调的特性。Swish 在深层模型上的效果优于 ReLU。

在这里插入图片描述

计算公式为:

image-20220421221448860

优点:

  • Swish具有一定ReLU函数的优点;
  • Swish具有一定Sigmoid函数的优点;
  • Swish函数可以看做是介于线性函数与ReLU函数之间的平滑函数。

缺点:

  • 运算复杂,速度较慢。

Mish

Mish与Swish激活函数类似,Mish具备无上界有下界、平滑、非单调的特性。Mish在深层模型上的效果优于 ReLU。无上边界可以避免由于激活值过大而导致的函数饱和。

在这里插入图片描述

计算公式:

image-20220421222005130

优点:

  • Mish具有一定ReLU函数的优点,收敛快速
  • Mish具有一定Sigmoid函数的优点,函数平滑
  • Mish函数可以看做是介于线性函数与ReLU函数之间的平滑函数

缺点:

  • 运算复杂,速度较慢

Swish和Mish的梯度对比

在这里插入图片描述

绘制代码

pytorch官方文档中的激活函数基本都在这里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import matplotlib.pyplot as plt
import numpy as np

def Sigmoid(x):
y = np.exp(x) / (np.exp(x) + 1)
return y

def Tanh(x):
y = (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
# y = np.tanh(x)
return y

def ReLU(x):
y = np.where(x < 0, 0, x)
return y

def LeakyReLU(x, a):
# LeakyReLU的a参数不可训练,人为指定。
y = np.where(x < 0, a * x, x)
return y

def PReLU(x, a):
# PReLU的a参数可训练
y = np.where(x < 0, a * x, x)
return y

def ReLU6(x):
y = np.minimum(np.maximum(x, 0), 6)
return y

def Swish(x, b):
y = x * (np.exp(b*x) / (np.exp(b*x) + 1))
return y

def Mish(x):
# 这里的Mish已经经过e和ln的约运算
temp = 1 + np.exp(x)
y = x * ((temp*temp-1) / (temp*temp+1))
return y

def Grad_Swish(x, b):
y_grad = np.exp(b*x)/(1+np.exp(b*x)) + x * (b*np.exp(b*x) / ((1+np.exp(b*x))*(1+np.exp(b*x))))
return y_grad

def Grad_Mish(x):
temp = 1 + np.exp(x)
y_grad = (temp*temp-1) / (temp*temp+1) + x*(4*temp*(temp-1)) / ((temp*temp+1)*(temp*temp+1))
return y_grad


if __name__ == '__main__':
x = np.arange(-10, 10, 0.01)

plt.plot(x, Sigmoid(x))
plt.title("Sigmoid")
plt.grid()
plt.show()

plt.plot(x, Tanh(x))
plt.title("Tanh")
plt.grid()
plt.show()

plt.plot(x, ReLU(x))
plt.title("ReLU")
plt.grid()
plt.show()

plt.plot(x, LeakyReLU(x, 0.1))
plt.title("LeakyReLU")
plt.grid()
plt.show()

plt.plot(x, PReLU(x, 0.25))
plt.title("PReLU")
plt.grid()
plt.show()

plt.plot(x, ReLU6(x))
plt.title("ReLU6")
plt.grid()
plt.show()

plt.plot(x, Swish(x, 1))
plt.title("Swish")
plt.grid()
plt.show()

plt.plot(x, Mish(x))
plt.title("Mish")
plt.grid()
plt.show()

plt.plot(x, Grad_Mish(x))
plt.plot(x, Grad_Swish(x, 1))
plt.title("Gradient of Mish and Swish")
plt.legend(['Mish', 'Swish'])
plt.grid()
plt.show()