出自论文:GhostNet: More Features from Cheap Operations
论文链接:https://arxiv.org/pdf/1911.11907.pdf
原理和实现都很简单!
核心解析:
在ImageNet的分类任务上,GhostNet在相似计算量情况下Top-1正确率达75.7%,高于MobileNetV3的75.2%。其主要创新点就是提出了Ghost 模块。在CNN模型中,特征图是存在大量的冗余,当然这也是非常重要和有必要的。如下图所示,其中标“小扳手”的特征图都存在冗余的特征图。那么能否降低卷积的通道数,然后利用某种变换生成冗余的特征图?事实上这就是GhostNet的思路。
而本文就从特征图冗余问题出发,提出一个仅通过少量计算(论文称为cheap operations)就能生成大量特征图的结构——Ghost Module。而cheap operations就是线性变换,论文中采用卷积操作实现。具体过程如下:
使用比原始更少量卷积运算,比如正常用64个卷积核,这里就用32个,减少一半的计算量。
利用深度分离卷积,从上面生成的特征图中变换出冗余的特征。
上面两步获取的特征图concat起来输出,送入后续的环节。
核心代码:
class GhostModule(nn.Module):
def __init__(self, inp, oup, kernel_size=1, ratio=2, dw_size=3, stride=1, relu=True):
super(GhostModule, self).__init__()
self.oup = oup
init_channels = math.ceil(oup / ratio)
new_channels = init_channels*(ratio-1)
self.primary_conv = nn.Sequential(
nn.Conv2d(inp, init_channels, kernel_size, stride, kernel_size//2, bias=False),
nn.BatchNorm2d(init_channels),
nn.ReLU(inplace=True) if relu else nn.Sequential(), )
# cheap操作,注意利用了分组卷积进行通道分离
self.cheap_operation = nn.Sequential(
nn.Conv2d(init_channels, new_channels, dw_size, 1, dw_size//2, groups=init_channels, bias=False),
nn.BatchNorm2d(new_channels),
nn.ReLU(inplace=True) if relu else nn.Sequential(),)
def forward(self, x):
x1 = self.primary_conv(x) #主要的卷积操作
x2 = self.cheap_operation(x1) # cheap变换操作
out = torch.cat([x1,x2], dim=1) # 二者cat到一起
return out[:,:self.oup,:,:]