GhostNet

作者: 海盗船长_coco | 来源:发表于2020-03-07 13:30 被阅读0次

论文地址:https://arxiv.org/abs/1911.11907
Pytorch实现代码:https://github.com/iamhankai/ghostnet.pytorch

灵感来源

作者发现将ResNet-50第一层残差网络的feature map可视化后,发现有大量冗余相似的feature map,这些冗余特征可以保证对输入数据有全面的理解。下图中配对的feature map就非常相近,当前情况用feature map A经过卷积后得到feature map B。
现在产生的想法是通过一系列固有特征(intrinsic feature maps),也就是feature map A。不经过卷积操作,而是使用更加廉价的线性运算得到大量的feature map B。这些大量的特征更有助于揭示固有特征的信息。


可视化后的feature map

GhostModule

论文中提出新的模块,叫做GhostModule。既然普通卷积提取的feature map有大量冗余的部分。那么只需生成少数固有特征feature map A,再用feature map A通过廉价的线性变化得到大量的feature map B不就行了。
红色部分就是提取那些固有特征feature map A的过程。而绿色部分表示利用固有特征进行线性变换得到大量的feature map B,该操作针对的是单个通道,类似深度可分离卷积中的深度卷积。最后参考ResNet的skip connect,进行通道维度的叠加。Output的通道数是固有特征的通道数的s倍,故剩余其他部分是固有特征的(s-1)倍。s为一个超参数,下图为不同的s的参数量和准确率。

GhostModule
不同s的权重和准确率
实现代码:黄色部分指红框中的固定特征,红色部分指Output底下的feature map。
class GhostModule(nn.Module):
    def __init__(self, in_channel, out_channel, kernel_size=1, ratio=2, dw_size=3, stride=1, relu=True):
        super(GhostModule, self).__init__()
        self.out_channel = out_channel
        mid_channel = math.ceil(out_channel / ratio)  # 黄色部分通道数
        rest_channels = mid_channel * (ratio - 1)  # 剩余红色部分通道数
        # 生成黄色部分
        self.primary_conv = nn.Sequential(
            nn.Conv2d(in_channel, mid_channel, kernel_size, stride, kernel_size // 2, bias=False),
            nn.BatchNorm2d(mid_channel),
            nn.ReLU6(inplace=True)
        )
        # 黄色部分提取剩余红色部分
        self.cheap_operation = nn.Sequential(
            nn.Conv2d(mid_channel, rest_channels, dw_size, 1, dw_size // 2, groups=mid_channel, bias=False),
            nn.BatchNorm2d(rest_channels)
        )
        self.bn = nn.BatchNorm2d(out_channel)
        if relu:
            self.relu = nn.ReLU6(inplace=True)
        else:
            self.relu = None

    def forward(self, x):
        x1 = self.primary_conv(x)
        x2 = self.cheap_operation(x1)
        out = torch.cat([x1, x2], dim=1)
        out = out[:, :self.out_channel, :, :]
        out = self.bn(out)
        if self.relu != None:
            out = self.relu(out)
        return out

参数量和计算量与标准卷积核进行比较:

Ghost module与普通卷积核
其中卷积核大小KxK与dxd大小相近,即K约等于d。且比值S远小于C,那么两者的参数量对比为
Ghost module与普通卷积核的参数量对比

Ghost bottleneck

Ghost bottleneck由GhostModule组成,并且也有残差网络的skip connect的部分。但是downsample采用的是深度可分离卷积,不是ResNet的传统卷积核。

Ghost bottleneck
代码部分:
class GhostBottleneck(nn.Module):
    def __init__(self, in_channel, mid_channel, out_channel, kernel_size, stride, use_se):
        super(GhostBottleneck, self).__init__()
        assert stride in [1, 2]

        self.conv = nn.Sequential()
        self.conv.add_module('GhostModule1', GhostModule(in_channel, mid_channel, kernel_size=1, relu=True))
        if stride == 2:
            self.conv.add_module('DWconv', depthwise_conv(mid_channel, mid_channel, kernel_size, stride,
                                                          relu=False) if stride == 2 else nn.Sequential())
        if use_se:
            self.conv.add_module('se block', SE_block(mid_channel))
        self.conv.add_module('GhostModule2', GhostModule(mid_channel, out_channel, kernel_size=1, relu=False))

        if stride == 1 and in_channel == out_channel:
            self.downsample = None
        else:
            self.downsample = nn.Sequential(
                depthwise_conv(in_channel, in_channel, 3, stride, relu=True),
                nn.Conv2d(in_channel, out_channel, kernel_size=3, stride=stride, padding=1, bias=False),
                nn.BatchNorm2d(out_channel),
            )

    def forward(self, x):
        if self.downsample == None:
            return self.conv(x) + x
        else:
            return self.conv(x) + self.downsample(x)

最终的主体网络其实就是由一个个Ghost bottleneck搭建而成


网络结构

可视化feature map

作者还可视化了Ghost模块的特征图,下图展示了Ghost-VGG-16的第二层特征,左上方的图像是输入,红色框中的特征图来自初始卷积,而绿色框中的特征图是经过廉价深度变换后的特征图。尽管生成的特征图来自原始特征图,但它们之间确实存在显着差异,这意味着生成的特征足够灵活,可以满足特定任务的需求。


可视化feature map

问题

文中提到普通卷积提取的feature map存在冗余的部分,那么如何判断ghost module中convolution操作输出的feature maps(即下图红框中卷积得到的feature map)不含有冗余的部分呢?如何确定该部分filter的channel数以保证fm不含有冗余的fm?


ghost module

答案是没法保证

参考博客

论文作者王云鹤的知乎回答:https://www.zhihu.com/search?type=content&q=GhostNet
https://blog.csdn.net/weixin_44317740/article/details/104546632#comments

相关文章

网友评论

      本文标题:GhostNet

      本文链接:https://www.haomeiwen.com/subject/jywvrhtx.html