文章目录
- 1. 什么是激活函数
- 2. sigmoid 激活函数
- 3. tanh 激活函数
- 4. ReLU 激活函数
- 5. SoftMax 激活函数
- 6. 其他常见的激活函数
- 7. 激活函数的选择方法
1. 什么是激活函数
激活函数用于对每层的输出数据进行变换, 进而为整个网络注入了非线性因素。此时, 神经网络就可以拟合各种曲线。
- 没有引入非线性因素的网络等价于使用一个线性模型来拟合。
- 通过给网络输出增加激活函数, 实现引入非线性因素, 使得网络模型可以逼近任意函数, 提升网络对复杂问题的拟合能力。
如果不使用激活函数,整个网络虽然看起来复杂,其本质还相当于一种线性模型,如下公式所示:

常见的激活函数有:sigmoid、tanh、ReLU、SoftMax。
2. sigmoid 激活函数
激活函数公式:
激活函数求导公式:
sigmoid 激活函数的函数图像如下:

- sigmoid 函数可以将任意的输入映射到 (0, 1) 之间,当输入的值大致在 <-6 或者 >6 时,意味着输入任何值得到的激活值都是差不多的,这样会丢失部分的信息。比如:输入 100 和输出 10000 经过 sigmoid 的激活值几乎都是等于 1 的,但是输入的数据之间相差 100 倍的信息就丢失了。
- 对于 sigmoid 函数而言,输入值在 [-6, 6] 之间输出值才会有明显差异,输入值在 [-3, 3] 之间才会有比较好的效果。
- 通过上述导数图像,我们发现导数数值范围是 (0, 0.25),当输入 <-6 或者 >6 时,sigmoid 激活函数图像的导数接近为 0,此时网络参数将更新极其缓慢,或者无法更新。
- 一般来说, sigmoid 网络在 5 层之内就会产生梯度消失现象。而且,该激活函数并不是以 0 为中心的,所以在实践
中这种激活函数使用的很少。sigmoid函数一般只用于二分类的输出层。
sigmoid 函数的代码实现:
# sigmoid 激活函数
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import torch
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 创建画布和坐标轴
_, axes = plt.subplots(1, 2)
# 函数图像
x = torch.linspace(-20,20,1000)
# 输入值x通过sigmoid 函数转换成激活值y
y = torch.sigmoid(x)
axes[0].plot(x,y)
axes[0].grid()
axes[0].set_title("sigmoid 函数图像")
# 导数图像
x = torch.linspace(-20,20,1000,requires_grad=True)
torch.sigmoid(x).sum().backward()
# x.detach():输入值x的数值
# x.grad:计算梯度,求导
axes[1].plot(x.detach(),x.grad)
axes[1].grid()
axes[1].set_title("sigmoid 导数图像")
plt.show()
输出结果:

3. tanh 激活函数
激活函数公式:
激活函数导数:
Tanh 的函数图像、导数图像如下:

- Tanh 函数将输入映射到 (-1, 1) 之间,图像以 0 为中心,在 0 点对称,当输入 大概<-3 或者3 时将被映射为 -1 或者 1。其导数值范围 (0, 1),当输入的值大概 <-3 或者 > 3 时,其导数近似 0。
- 与 Sigmoid 相比,它是以 0 为中心的,且梯度相对于sigmoid大,使得其收敛速度要比Sigmoid 快,减少迭代次数。然而,从图中可以看出,Tanh 两侧的导数也为 0,同样会造成梯度消失。
- 若使用时可在隐藏层使用tanh函数,在输出层使用sigmoid函数。
tanh 代码实现:
# -*- coding: utf-8 -*-
# tanh激活函数
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import torch
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 创建画布和坐标轴
_, axes = plt.subplots(1, 2)
# 函数图像
x = torch.linspace(-20, 20, 100)
y = torch.tanh(x)
axes[0].plot(x,y)
axes[0].grid()
axes[0].set_title("tanh 函数图像")
#导数图像
x = torch.linspace(-20, 20, 100,requires_grad=True)
torch.tanh(x).sum().backward()
# x.detach():输入值x的数值
# x.grad:计算梯度,求导
axes[1].plot(x.detach(),x.grad)
axes[1].grid()
axes[1].set_title("tanh 导数图像")
plt.show()
输出结果:

4. ReLU 激活函数
激活函数公式:
激活行数导数:
ReLu 的函数图像、导数图像如下:
ReLu代码实现:
# -*- coding: utf-8 -*-
# tanh激活函数
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import torch
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 创建画布和坐标轴
_, axes = plt.subplots(1, 2)
# 函数图像
x = torch.linspace(-20, 20, 100)
y = torch.relu(x)
axes[0].plot(x,y)
axes[0].grid()
axes[0].set_title("ReLU 函数图像")
#导数图像
x = torch.linspace(-20, 20, 100,requires_grad=True)
torch.relu(x).sum().backward()
# x.detach():输入值x的数值
# x.grad:计算梯度,求导
axes[1].plot(x.detach(),x.grad)
axes[1].grid()
axes[1].set_title("ReLU 导数图像")
plt.show()
输出结果:
5. SoftMax 激活函数
softmax 用于多分类过程中,它是二分类函数sigmoid在多分类上的推广,目的是将多分类的结果以概率的形式展现出来。计算方法如下图所示:
Softmax 就是将网络输出的 logits 通过 softmax 函数,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们将它理解成概率,选取概率最大(也就是值对应最大的)节点,作为我们的预测目标类别。
scores = torch.tensor([0.2, 0.02, 0.15, 0.15, 1.3, 0.5, 0.06, 1.1, 0.05, 3.75])
probabilities = torch.softmax(scores, dim=0)
print(probabilities)
输出结果:
tensor([0.0212, 0.0177, 0.0202, 0.0202, 0.0638, 0.0287, 0.0185, 0.0522, 0.0183,
0.7392])
6. 其他常见的激活函数
7. 激活函数的选择方法
对于隐藏层:
-
优先选择ReLU激活函数
-
如果ReLu效果不好,那么尝试其他激活,如Leaky ReLu等。
-
如果你使用了ReLU, 需要注意一下Dead ReLU问题, 避免出现大的梯度从而导致过多的神经元死亡。
-
少用使用sigmoid激活函数,可以尝试使用tanh激活函数
对于输出层:
- 二分类问题选择sigmoid激活函数
- 多分类问题选择softmax激活函数
- 回归问题选择identity激活函数