YOLOv9改进系列(一):替换激活函数为Mish、MetaAconC、FReLU、PReLU、Swish

前言

在卷积神经网络中,激活函数通过在神经网络中引入非线性,使网络能够学习和逼近复杂函数,从而处理复杂的模式识别与分类问题。


一、YOLOv9激活函数

YOLOv9官方代码:https://github.com/WongKinYiu/yolov9
YOLOv9的卷积模块中使用的基础激活函数为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+ex1是常见的S型非线性函数。

特性

  • 非线性:SiLU函数能够将线性关系转换为非线性关系,这对于神经网络学习复杂模式至关重要。
  • 连续可导:在整个定义域内都是可微的,这使得在反向传播过程中的梯度计算更加稳定。
  • 无上界有下界:其输出没有上界,但存在下界(接近0),这种特性有助于防止网络饱和和梯度消失问题。
  • 平滑、非单调:与ReLU相比,SiLU函数更加平滑,并且在x≈−1.28时达到全局最小值−0.28,这可以起到一个隐式正则化的作用,抑制过大的权重。
    在这里插入图片描述

与其他激活函数的比较

  • 相比Sigmoid函数,SiLU函数不易出现梯度消失问题,且计算成本更低。
  • 相比ReLU函数,SiLU函数在负数区域内具有非零梯度,这有助于避免神经元“死亡”问题,并且在整个定义域内都是可微的,有利于优化。

实现代码

class SiLU(nn.Module):
    @staticmethod
    def 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)=xtanh(ln(1+ex))
在这里插入图片描述

实现代码

class Mish(nn.Module):
    @staticmethod
    def forward(x):
        return x * F.softplus(x).tanh()

替换方法

在yolov9-main/utils/activations.py文件中官方已自带了Mish激活函数的实现代码,需要修改的是在yolov9-main/models/common.py文件夹下,将Conv模块中的默认激活函数修改成nn.Mish(),其它不动。

    # default_act = nn.SiLU()  # default activation
    default_act = nn.Mish()  # default activation

模型训练

在yolov9-main/train_dual.py文件中,根据本机电脑算力,数据集划分信息,权重等相关配置设置好后运行运行。
在这里插入图片描述
训练效果根据各自数据集及使用的显卡配置不同而不同。

三、MetaAconC

MetaAconC 是一种自适应控制的激活函数,通过引入可学习的参数来优化神经元的激活程度,进而提升神经网络的性能。
MetaAconC ( x ) = ( α ⋅ x − β ⋅ x ) ⋅ σ ( γ ⋅ ( α ⋅ x − β ⋅ x ) ) + β ⋅ x \text{MetaAconC}(x) = (\alpha \cdot x - \beta \cdot x) \cdot \sigma(\gamma \cdot (\alpha \cdot x - \beta \cdot x)) + \beta \cdot x MetaAconC(x)=(αxβx)σ(γ(αxβx))+βx
其中,αβγ 是可学习的参数,x 是神经元的输入,σsigmoid函数。
在这里插入图片描述

实现代码

class MetaAconC(nn.Module):

    def __init__(self, c1, k=1, s=1, r=16):  # ch_in, kernel, stride, r
        super().__init__()
        c2 = max(r, c1 // r)
        self.p1 = nn.Parameter(torch.randn(1, c1, 1, 1))
        self.p2 = nn.Parameter(torch.randn(1, c1, 1, 1))
        self.fc1 = nn.Conv2d(c1, c2, k, s, bias=True)
        self.fc2 = nn.Conv2d(c2, c1, k, s, bias=True)
        # self.bn1 = nn.BatchNorm2d(c2)
        # self.bn2 = nn.BatchNorm2d(c1)

    def forward(self, x):
        y = x.mean(dim=2, keepdims=True).mean(dim=3, keepdims=True)
        # batch-size 1 bug/instabilities https://github.com/ultralytics/yolov5/issues/2891
        # beta = torch.sigmoid(self.bn2(self.fc2(self.bn1(self.fc1(y)))))  # bug/unstable
        beta = torch.sigmoid(self.fc2(self.fc1(y)))  # bug patch BN layers removed
        dpx = (self.p1 - self.p2) * x
        return dpx * torch.sigmoid(beta * dpx) + self.p2 * x

替换方法

在yolov9-main/utils/activations.py文件中官方已自带了MetaAconC激活函数的实现代码,需要修改的是在yolov9-main/models/common.py文件夹下,导入MetaAconC包,并修改Conv模块,其它不动。

#在common.py文件顶端加入
from utils.activations import MetaAconC
#在Conv模块中修改如下
# self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
self.act = MetaAconC(c1=c2) if act is True else act if isinstance(act, nn.Module) else nn.Identity()

模型训练

在yolov9-main/train_dual.py文件中,根据本机电脑算力,数据集划分信息,权重等相关配置设置好后运行。
在这里插入图片描述

FReLU、PReLU、Swish…

总结

今天先记录一下Mish、MetaAconC激活函数的使用方法,后续会陆续补充其它经典激活函数和新发布的激活函数的调用方法。

  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Limiiiing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值