我的前馈神经网络系列文章如下,便于读者成体系学习:
2、📈 激活函数
2.1 激活函数的作用
-
增加模型的非线性分割能力
图1 | 图2 |
---|---|
![]() | ![]() |
在神经元中引入激活函数的本质是向神经网络中引入非线性因素,通过激活函数,神经网络就可以拟合各种曲线。如果不用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合
如图2,在图1基础上增加了一层隐藏层
输出由
变为了
但仍然为线性,没有任何改进
引入非线性函数作为激活函数,那输出不再是输入的线性组合,可以逼近任意函数。
-
提高模型鲁棒性
-
缓解梯度消失问题
-
加速模型收敛等
2.2 激活函数的种类
2.2.1 Sigmoid 函数
-
数学公式
-
函数及其导数图像
Sigmoid 函数 Sigmoid 导数 -
使用场景
-
sigmoid 在定义域内处处可导,且两侧导数逐渐趋近于0。如果 x 的值很大或者很小的时候,那么函数的梯度(函数的斜率)会非常小,在反向传播的过程中,导致了向低层传递的梯度也变得非常小。此时,网络参数很难得到有效训练。这种现象被称为梯度消失 。一般来说, sigmoid 网络在 5 层之内就会产生梯度消失现象。而且,该激活函数并不是以 0 为中心的(是以 0.5 为中心的),所以在实践中这种激活函数使用的很少。
-
sigmoid函数将输入映射到 (0, 1) 区间,一般只用于二分类的输出层
-
-
实现代码
import torch import torch.nn as nn import torch.nn.functional as F # 方法1:使用类(作为网络层) sigmoid_layer = nn.Sigmoid() # 方法2:使用函数式接口 x = torch.tensor([-2.0, 0.0, 2.0]) output1 = sigmoid_layer(x) # 类调用 output2 = F.sigmoid(x) # 函数调用 print("Sigmoid输出:", output1) # 输出:tensor([0.1192, 0.5000, 0.8808])
2.2.2 Tanh函数
-
数学公式
-
函数及其导数图像
Tanh 函数 Tanh 导数 -
使用场景
tanh 也是一种非常常见的激活函数。与 sigmoid 相比,它是以 0 为中心的,使得其收敛速度要比 sigmoid 快(相比之下,tanh 曲线更为陡峭一些),减少迭代次数。然而,从图中可以看出,tanh 两侧的导数也为 0,同样会造成梯度消失。
若使用时可在隐藏层使用 tanh 函数,在输出层使用 sigmoid 函数。
-
实现代码
import torch import torch.nn as nn import torch.nn.functional as F # 方法1:使用类 tanh_layer = nn.Tanh() # 方法2:使用函数式接口 x = torch.tensor([-1.0, 0.0, 1.0]) output1 = tanh_layer(x) # 类调用 output2 = F.tanh(x) # 函数调用 print("Tanh输出:", output1) # 输出:tensor([-0.7616, 0.0000, 0.7616])
2.2.3 ReLU函数
-
数学公式
-
函数及其导数图像
ReLU 函数 ReLU 导数 -
使用场景
-
ReLU是目前最常用的激活函数。 从图中可以看到,当 x<0 时,ReLU导数为0,而当 x>0 时,则不存在饱和问题。所以,ReLU 能够在 x>0 时保持梯度不衰减,从而缓解梯度消失问题。然而,随着训练的推进,部分输入会落入小于0区域,导致对应权重无法更新。这种现象被称为“神经元死亡”。
-
Relu是输入只能大于0,如果你输入含有负数,Relu就不适合,如果你的输入是图片格式,Relu就挺常用的,因为图片的像素值作为输入时取值为[0,255]。
-
与sigmoid相比,RELU的优势是:
-
采用sigmoid函数,计算量大(指数运算),反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。
-
sigmoid函数反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练。
-
Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题。
-
-
-
实现代码
import torch import torch.nn as nn import torch.nn.functional as F # 方法1:使用类 relu_layer = nn.ReLU() # 方法2:使用函数式接口 x = torch.tensor([-1.0, 0.0, 1.0]) output1 = relu_layer(x) # 类调用 output2 = F.relu(x) # 函数调用 # 类接口(如nn.ReLU): # 适合在__init__中定义为网络的固定层,参数可通过model.parameters()管理(如 Swish 的\(\beta\)) # 函数接口(如F.relu): # 适合在forward中灵活调用,无需在__init__中预先定义 print("ReLU输出:", output1) # 输出:tensor([0., 0., 1.])
2.2.4 Leaky ReLU 函数
-
数学公式(一般取
)
-
函数及其导数图像
Leaky ReLU 函数 Leaky ReLU 导数 -
使用场景
该激活函数是对RELU的改进,一定程度上缓解了神经元死亡问题
-
实现代码
import torch import torch.nn as nn import torch.nn.functional as F # 方法1:使用类(可指定alpha) leaky_relu_layer = nn.LeakyReLU(negative_slope=0.01) # negative_slope即alpha # 方法2:使用函数式接口 x = torch.tensor([-1.0, 0.0, 1.0]) output1 = leaky_relu_layer(x) # 类调用 output2 = F.leaky_relu(x, negative_slope=0.01) # 函数调用 print("Leaky ReLU输出:", output1) # 输出:tensor([-0.0100, 0.0000, 1.0000])
2.2.5 ELU(Exponential Linear Unit)函数
-
数学公式
-
函数及其导数图像
ELU 函数 ELU 导数 -
使用场景
ELU激活函数是一种改进的激活函数,它在处理负值时具有独特的优势。ELU函数通过引入指数函数来处理负输入,从而在理论上可以提供更好的性能。因此,ELU激活函数适用于需要处理大量负值输入的各种深度学习任务。
-
实现代码
import torch import torch.nn as nn import torch.nn.functional as F # 方法1:使用类(可指定alpha) elu_layer = nn.ELU(alpha=1.0) # 方法2:使用函数式接口 x = torch.tensor([-1.0, 0.0, 1.0]) output1 = elu_layer(x) # 类调用 output2 = F.elu(x, alpha=1.0) # 函数调用 print("ELU输出:", output1) # 输出:tensor([-0.6321, 0.0000, 1.0000])
2.2.6 Softmax函数
-
数学公式
-
使用场景
softmax用于多分类过程中,它是二分类函数 sigmoid 在多分类上的推广,目的是将多分类的结果以概率的形式展现出来。
softmax 直白来说就是将网络输出的 logits 通过softmax函数,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们将它理解成概率,选取概率最大(也就是值对应最大的)接点,作为我们的预测目标类别。
-
实现代码
import torch import torch.nn as nn import torch.nn.functional as F # 方法1:使用类(dim参数指定计算维度,通常为-1表示最后一维) softmax_layer = nn.Softmax(dim=-1) # 方法2:使用函数式接口 x = torch.tensor([[1.0, 2.0, 3.0]]) # 假设是批次中的一个样本(形状:[1, 3]) output1 = softmax_layer(x) # 类调用 output2 = F.softmax(x, dim=-1) # 函数调用 print("Softmax输出:", output1) # 输出:tensor([[0.0900, 0.2447, 0.6652]]) print("概率和:", output1.sum()) # 输出:tensor(1.0)(满足概率分布性质)
2.3 激活函数的选择
-
隐藏层
-
优先选择RELU激活函数
-
如果ReLu效果不好,那么尝试其他激活,如Leaky ReLu等
-
如果使用了Relu, 需要注意避免出现大的梯度从而导致过多的神经元死亡
-
不要使用sigmoid激活函数,可以尝试使用tanh激活函数
-
-
输出层
-
二分类问题选择sigmoid激活函数
-
多分类问题选择softmax激活函数
-