前言
在卷积神经网络中,激活函数通过在神经网络中引入非线性,使网络能够学习和逼近复杂函数,从而处理复杂的模式识别与分类问题。
文章目录
- 前言
- 一、YOLOv11激活函数
- SiLU激活函数
- 特性
- 与其他激活函数的比较
- 实现代码
- 二、替换激活函数:Mish
- 实现代码
- 替换方法
- 模型训练
- 三、PReLU
- 四、Hardswish
- 五、LeakyReLU
- 六、ReLU6
一、YOLOv11激活函数
YOLOv11官方代码:https://github.com/ultralytics/ultralytics
YOLOv11的卷积模块中使用的基础激活函数为SiLU()。
SiLU激活函数
SiLU函数的公式定义为:
SiLU ( x ) = x ⋅ S i g m o i d ( x ) \text{SiLU}(x) = x \cdot \ Sigmoid(x) SiLU(x)=x⋅ Sigmoid(x)
其中 S i g m o i d ( x ) = 1 1 + e − x \ Sigmoid(x) = \frac{1}{1 + e^{-x}} Sigmoid(x)=1+e−x1是常见的S型非线性函数。
特性
- 非线性:SiLU函数能够将线性关系转换为非线性关系,这对于神经网络学习复杂模式至关重要。
- 连续可导:在整个定义域内都是可微的,这使得在反向传播过程中的梯度计算更加稳定。
- 无上界有下界:其输出没有上界,但存在下界(接近0),这种特性有助于防止网络饱和和梯度消失问题。
- 平滑、非单调:与ReLU相比,SiLU函数更加平滑,并且在x≈−1.28时达到全局最小值−0.28,这可以起到一个隐式正则化的作用,抑制过大的权重。
与其他激活函数的比较
- 相比Sigmoid函数,SiLU函数不易出现梯度消失问题,且计算成本更低。
- 相比ReLU函数,SiLU函数在负数区域内具有非零梯度,这有助于避免神经元“死亡”问题,并且在整个定义域内都是可微的,有利于优化。
实现代码
class SiLU(nn.Module):@staticmethoddef forward(x):return x * torch.sigmoid(x)
二、替换激活函数:Mish
Mish激活函数以其无上限但有下限、光滑且非单调的特性,为深度学习模型提供了更好的拟合复杂数据分布的能力。
Mish ( x ) = x ⋅ tanh ( ln ( 1 + e x ) ) \text{Mish}(x) = x \cdot \tanh(\ln(1 + e^x)) Mish(x)=x⋅tanh(ln(1+ex))
实现代码
class Mish(nn.Module):@staticmethoddef forward(x):return x * F.softplus(x).tanh()
替换方法
在ultralytics/nn/modules/conv.py
文件中的Conv模块
实现中,定义了默认的激活函数,在torch
中已经实现了Mish激活函数
,需要修改的是在Conv模块,将Conv模块中的默认激活函数修改成nn.Mish()
,其它不动。
# default_act = nn.SiLU() # default activationdefault_act = nn.Mish() # default activation
模型训练
根据本机电脑算力,数据集划分信息,权重等相关配置设置好后运行运行。
训练效果根据各自数据集及使用的显卡配置不同而不同。
三、PReLU
PReLU的添加方式:
class PReLU(nn.Module):def __init__(self, num_parameters=1, init=0.25):super(PReLU, self).__init__()self.num_parameters = num_parametersself.weight = nn.Parameter(torch.Tensor(num_parameters).fill_(init))def forward(self, input):return torch.max(input, 0) + self.weight * torch.min(input, 0)
激活函数的修改方法均一致。
# default_act = nn.SiLU() # default activationdefault_act = nn.PReLU() # default activation
四、Hardswish
Hardswish的实现代码:
def hardswish(x):return x * torch.clamp(x + 3, min=0, max=6) / 6
激活函数的修改方法均一致。
# default_act = nn.SiLU() # default activationdefault_act = nn.Hardswish() # default activation
五、LeakyReLU
LeakyReLU的实现代码:
class LeakyReLU(nn.Module):def __init__(self, negative_slope=0.01):super(LeakyReLU, self).__init__()self.negative_slope = negative_slopedef forward(self, x):return torch.max(x, self.negative_slope * x)
激活函数的修改方法均一致。
# default_act = nn.SiLU() # default activationdefault_act = nn.LeakyReLU() # default activation
六、ReLU6
ReLU6的实现代码:
def relu6(x):return torch.clamp(x, min=0, max=6)
激活函数的修改方法均一致。
# default_act = nn.SiLU() # default activationdefault_act = nn.ReLU6() # default activation