前言
CVPR是计算机视觉领域的顶级国际会议之一,每年都吸引了来自全球各地的学者和从业人员参与,2023年的CVPR也不例外。在本文中为大家介绍今年新出炉的网络——Backbone FasterNet。
在这里大家想要知道更详细的关于论文的内容,大家可以点击上方的论文链接,翻阅原文查看。博主在这里从尝试实操给大家带来Backbone FasterNet。
导读
在FasterNet中解决的核心问题是低FLOPS运算的高频次访问带来的延迟,为了解决这个痛点,论文作者们提出了一种新的卷积结构:partial convolution(PConv)。该卷积通过减少冗余计算和内存访问可以更有效的提取空间特征。基于PConv进一步提出FasterNet。
Pconv算子
Pconv它只对几个输入通道应用滤波器,而不影响其余的输入通道。PConv比常规卷积获得更低的FLOPs,而比深度/组卷积获得更高的FLOPs。PConv的FLOPs比常规Conv低,而比DWConv/GConv有更高的FLOPs。换句话说,PConv更好地利用了设备上的计算能力。PConv在提取空间特征方面也很有效。
贡献如下:
- 我们指出实现更高的FLOPS的重要性,而不仅仅是为了更快的神经网络而简单地降低FLOPS。
- 我们介绍了一个简单而快速且有效的运算符PConv,它有很大的潜力取代现有的首选DWConv。
- 我们介绍了fastnet,它在各种设备(如GPU、CPU和ARM处理器)上运行良好且统一快速。
- 我们对各种任务进行了广泛的实验,并验证了我们的PConv和FasterNet的高速和有效性。
python
复制代码
import torch import torch.nn as nn from torch import Tensor class PConv(nn.Module): """ Partial convolution (PConv). """ def __init__(self, dim: int, n_div: int, forward: str = "split_cat", kernel_size: int = 3) -> None: """ Construct a PConv layer. :param dim: Number of input/output channels :param n_div: Reciprocal of the partial ratio. :param forward: Forward type, can be either ’split_cat’ or ’slicing’. :param kernel_size: Kernel size. """ super().__init__() self.dim_conv = dim // n_div self.dim_untouched = dim - self.dim_conv self.conv = nn.Conv2d( self.dim_conv, self.dim_conv, kernel_size, stride=1, padding=(kernel_size - 1) // 2, bias=False ) if forward == "slicing": self.forward = self.forward_slicing elif forward == "split_cat": self.forward = self.forward_split_cat else: raise NotImplementedError def forward_slicing(self, x: Tensor) -> Tensor: """ Apply forward pass for inference. """ x[:, :self.dim_conv, :, :] = self.conv(x[:, :self.dim_conv, :, :]) return x def forward_split_cat(self, x: Tensor) -> Tensor: """ Apply forward pass for training. """ x1, x2 = torch.split(x, [self.dim_conv, self.dim_untouched], dim=1) x1 = self.conv(x1) x = torch.cat((x1, x2), 1) return x
FasterNet Block
PWConv的基本思想是在每个像素点上分别进行卷积计算,从而实现卷积操作。相对于传统的卷积操作,PWConv具有计算效率高和模型参数较少等优势,其主要优势在于它可以用较少的参数实现模型的有效表达,从而减少模型计算量和内存消耗。此外,PWConv还可以用于实现多通道特征的通道关系转换和压缩。
由下图所示的fasterNet Block(下述简称FNB)图,我们可以得到主要组成的结构是PConv conv_1x1、BN、Relu组合而成。在本文中上面已经得到了PConv层,剩下的就是组件FNB层了。
python
复制代码
import torch import torch.nn as nn from torch import Tensor def Conv1x1(nin, nf, stride=1): return nn.Sequential( nn.Conv2d(nin, nf, 3, stride, 1, bias=False), nn.BatchNorm2d(nf), nn.ReLU(inplace=True) ) class PConv(nn.Module): pass class FasterNetBlock(nn.Module): def __init__(self, inp: int, outp: int, dim: int, n_div: int, forward: str = "split_cat", kernel_size: int = 3) -> None: super().__init__() self.pconv = PConv(dim=dim, n_div=n_div, forward=forward, kernel_size=kernel_size) self.conv1_1 = Conv1x1(inp, outp) self.bn = nn.BatchNorm2d(outp) self.relu = nn.ReLU(inplace=True) def forward(self, x): x = self.pconv(x) x = self.conv1_1(x) x = self.bn(x) x = self.relu(x) x = self.conv_1x1(x) return x