ShuffleNet V1 是旷视科技的张翔雨提出的一种适用于移动设备的轻量化网络。
Xception,ResNeXt,MobileNet 等网络都使用了 group conv,他们有一个问题,是采用了密集的1x1 pointwise conv,这一步需要相当大的计算量。为此,作者指出,一个非常自然的解决方案就是把 1x1 pointwise conv 同样应用 group conv ,这样就可以进一步降低计算量。但是,这又带来一个新的问题:“outputs from a certain channel are only derived from a small fraction of input channels”。
为了解决这一问题,作者构建了 channel shuffle,如下图所示。图(a)表示利用两个堆叠的 group conv 提取特征。图(b)表示 channel shuffle ,对 group conv 之后的特征 “重组” ,接下来的 group conv 输入来自不同的组,信息可以在不同组间流转。图(c) 是图(b) 的另一种表示方法。
ShuffleNet的基本单元和标准的 MobileNet 单元的区别如下图所示。 MobileNet 的基本单元如图(a)所示,首先是1x1的卷积降低 feature map 的通道数,然后用 3x3 的 depthwise conv 处理,然一用 1x1 的 pointwise conv 处理。图 (b) 展示了改进思路,把第一个 1x1 的卷积用 group conv 替换,然后增加了一个 channel shuffle 操作。值得注意的是 3x3 卷积后没有加 channel shuffle,作者表示以这个单元中加一个 channel shuffle 就足够了。
图(c)表示的是起到pooling作用,stride=2 的 ShuffleNet 单元,把两个通路的结果百行拼接,而不是相加,作者的解释是 makes it easy to enlarge channel dimension with little extra computation cost。
知乎有文章,实现了 pytorch 的 ShuffleNet ,(文章链接:https://zhuanlan.zhihu.com/p/259781831)
关键一步在于 channel shuffle,代码如下:
class ChannelShuffle(nn.Module):
def __init__(self, groups):
super().__init__()
self.groups = groups
def forward(self, x):
batchsize,channels,height,width=x.data.size()
channels_per_group=int(channels/self.groups)
x = x.view(batchsize,self.groups,channels_per_group,height,width)
# 这里进地了矩阵的转置,然后必须要使用.contiguous()
# 使得张量在内存连续之后才能调用view函数
x = x.transpose(1,2).contiguous()
x = x.view(batchsize,-1,height,width)
return x
原文:https://www.cnblogs.com/gaopursuit/p/14403044.html