理论知识
CondConv理论
问题背景
CNN模型的能力来源于模型的大小和数据集的规模。卷积层设计中的一个基本假设是,相同的卷积核应用于数据集中的每个示例。为了增加模型的容量,模型开发人员通常会添加更多的卷积层或增加现有卷积的大小(内核高度/宽度,输入/输出通道的数量)。这会导致模型增大,影响速度。
CondConv的提出
条件参数化卷积(CondConv),它通过计算卷积核作为输入的函数来挑战静态卷积核的范式。所谓条件:条件计算的目的是在不增加计算成本的情况下增加模型容量;在条件计算模型中,通过为每个示例仅激活整个网络的一部分来实现的。多分支卷积网络:一个层由多个卷积分支组成,这些分支被聚合以计算最终输出,如:ResNet和Inception等。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

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





