YOLO改进:动态卷积之有效推理的条件参数化卷积CondConv

本文介绍了CondConv,一种通过动态调整卷积核参数来增加模型容量的方法。文章详细讲解了CondConv的原理,提供了PyTorch实现代码,并展示了如何在YOLO架构中集成C3_CondConv模块,以及在VisDrone数据集上的实验示例。

理论知识

CondConv理论

CondConv论文地址
CondConv代码地址

问题背景

CNN模型的能力来源于模型的大小和数据集的规模。卷积层设计中的一个基本假设是,相同的卷积核应用于数据集中的每个示例。为了增加模型的容量,模型开发人员通常会添加更多的卷积层或增加现有卷积的大小(内核高度/宽度,输入/输出通道的数量)。这会导致模型增大,影响速度。

CondConv的提出

条件参数化卷积(CondConv),它通过计算卷积核作为输入的函数来挑战静态卷积核的范式。所谓条件:条件计算的目的是在不增加计算成本的情况下增加模型容量;在条件计算模型中,通过为每个示例仅激活整个网络的一部分来实现的。多分支卷积网络:一个层由多个卷积分支组成,这些分支被聚合以计算最终输出,如:ResNet和Inception等。CondConv层在数学上相当于多分支卷积层,其中每个分支是单个卷积,输出通过加权和聚合,但只需要计算一个卷积。

CondConv的思路不难,具体来说:
CondConv
卷积核将按照上图(a)的方式进行参数化,其中W1、W2、W3就相当于多个卷积核;ROUTE FN就相当于W1、W2、W3前的权重参数。通过(a1W1+a2W2+a3W3)组合得到一个卷积核,使用这个新得到的卷积核进行卷积操作。

CondConv代码

从代码可以更为直观的理解CondConv做的事情
CondConv-Pytorch

# 权值计算,num_experts是设置的专家数量
class _routing(nn.Module):

    def __init__(self, in_channels, num_experts, dropout_rate):
        super(_routing, self).__init__()

        self.dropout = nn.Dropout(dropout_rate)
        self.fc = nn.Linear(in_channels, num_experts)

    def forward(self, x):
        x = torch.flatten(x)
        x = self.dropout(x)
        x = self.fc(x)
        return F.sigmoid(x)

# CondConv卷积过程
class CondConv2D(_ConvNd):
    def __init__(self, in_channels, out_channels, kernel_size, stride=1,
                 padding=0, dilation=1, groups=1,
                 bias=True, padding_mode='zeros', num_experts=3, dropout_rate=0.2):
        kernel_size = _pair(kernel_size) # 3 -> (3,3)
        stride = _pair(stride)
        padding = _pair(padding)
        dilation = _pair(dilation)
        super(CondConv2D, self).__init__(
            in_channels, out_channels, kernel_size, stride, padding, dilation,
            False, _pair(0), groups, bias, padding_mode)

		# 全局平均池化会将输入特征由尺寸(bs, c, w, h) -> (bs, c, 1, 1),为后续的权重计算做准备
        self._avg_pooling = functools.partial(F.adaptive_avg_pool2d, output_size=(1, 1))
        # 调用权重计算函数,输入由(bs, c, 1, 1) -> (bs, num_experts, 1, 1),通道数发生改变,和专家数量的多少有关
        self._routing_fn = _routing(in_channels, num_experts, dropout_rate)

		# 构建了一个尺寸为(num_experts, out_channels, in_channels , kernel_size, kernel_size)的Tensor变量
        self.weight = Parameter(torch.Tensor(
            num_experts, out_channels, in_channels // groups, *kernel_size))

        self.reset_parameters()

    def _conv_forward(self, input, weight):
        if self.padding_mode != 'zeros':
            return F.conv2d(F.pad(input, self._padding_repeated_twice, mode=self.padding_mode),
                            weight, self.bias, self.stride,
                            _pair(0), self.dilation, self.groups)
        return F.conv2d(input, weight, self.bias, self.stride,
                        self.padding, self.dilation, self.groups)

    def forward(self, inputs):
        b, _, _, _ = inputs.size
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值