一句话介绍:使用多用卷积核构建轻量网络模型
优势:不改变原来的网络结构,只需要换一下卷积的接口
论文地址
开源代码
原作者的知乎专栏有简单介绍

一、背景知识介绍

1. 感受野

感受野在卷积中是个非常重要的概念。大的感受野允许神经元在一个广阔的维度上发现其变换规律,但感知不够精确。小的感受野则允许神经元发现细节。所以为了提取复杂而精确的特征,有必要整合有大感受野和小感受野的神经元。

对不同尺寸的输入信息直接使用不同尺寸的卷积核是个很方法,但内存开销的增加也不容忽视。最重要的是,由于同一层网络中不同尺寸的卷积核有不同的感受野,他们检测的信息会有一定的冗余,进一步说明了卷积核信息之间的关联性。

2. 传统卷积核

  • 输入数据x,尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图1,分别为高度,宽度和通道数。
  • 一个卷积核f,尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图2Learning Versatile Filters for Efficient Convolutional Neural Networks - 图3表示卷积核的尺寸。
  • 输出数据y,假设相应的输出尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图4
    Learning Versatile Filters for Efficient Convolutional Neural Networks - 图5表示卷积运算

其时间复杂度为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图6

二、空间多用卷积核

1. 概括

一句话介绍其思想:针对尺寸大于3*3的卷积核,通过逐步舍弃边缘的元素,抽取出多个不同感受野的二级卷积核,得到更多的特征图。

以下图为例,初始为5*5的卷积核,分别保留5*53*31*1位置的元素,可以得到3个二级卷积核,得到3倍的特征图。(反过来说就是,原来要x个卷积核才能得到的输出,现在只需要x/3个卷积核了)
Learning Versatile Filters for Efficient Convolutional Neural Networks - 图7

2. 具体分析

  • 输入数据x,尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图8,分别为高度,宽度和通道数。
  • 一个卷积核f,尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图9Learning Versatile Filters for Efficient Convolutional Neural Networks - 图10表示卷积核的尺寸。
  • 输出数据y,假设相应的输出尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图11

我们将传统卷积里的卷积核Learning Versatile Filters for Efficient Convolutional Neural Networks - 图12作为主卷积核,从中推导出一系列的二级卷积核Learning Versatile Filters for Efficient Convolutional Neural Networks - 图13,其中Learning Versatile Filters for Efficient Convolutional Neural Networks - 图14。推导规则如下:

  1. 定义掩膜M

Learning Versatile Filters for Efficient Convolutional Neural Networks - 图15

  1. 定义二级卷积核为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图16
    Learning Versatile Filters for Efficient Convolutional Neural Networks - 图17 表示元素对应相乘。分析这个二级卷积核,Learning Versatile Filters for Efficient Convolutional Neural Networks - 图18表示f本身,Learning Versatile Filters for Efficient Convolutional Neural Networks - 图19舍弃了f最外层的元素,Learning Versatile Filters for Efficient Convolutional Neural Networks - 图20只有f的最内层元素。
    假设主卷积核尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图21, 则可以生成三个二级卷积核,尺寸为别为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图22Learning Versatile Filters for Efficient Convolutional Neural Networks - 图23Learning Versatile Filters for Efficient Convolutional Neural Networks - 图24,
  2. 从二级卷积核中得到输出
    Learning Versatile Filters for Efficient Convolutional Neural Networks - 图25
    这里的Learning Versatile Filters for Efficient Convolutional Neural Networks - 图26表示偏置

通过这种方式,我们可以同时得到s个不同感受野的二级卷积核,输出的尺寸是使用传统卷积的s倍

3. 与传统卷积的比较

上文可知,空间多用卷积核在不增加卷积核数量的情况下获得更多的特征图。

  • 输入数据x,尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图27,分别为高度,宽度和通道数。
  • 一个卷积核f,尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图28Learning Versatile Filters for Efficient Convolutional Neural Networks - 图29表示卷积核的尺寸。
  • 输出数据y,假设相应的输出尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图30

对于输出Learning Versatile Filters for Efficient Convolutional Neural Networks - 图31

  1. 传统方法需要n个卷积核,每个主卷积核的尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图32, 其总的空间消耗为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图33,计算复杂度为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图34
  2. 使用本文方法需要s个主卷积核,每个主卷积核的尺寸为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图35,其总的空间消耗为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图36,计算复杂度为Learning Versatile Filters for Efficient Convolutional Neural Networks - 图37。当s>2时,空间和时间消耗都能显著降低

4. 为什么能这么做

前面提到了一个感受野的问题。能这样做的依据如下。

  1. 卷积核可视化就能发现存在大量冗余,利用主卷积核生成二级卷积核能一定程度上消除这种冗余
  2. 感受野的问题。多个尺寸的二级卷积核使得既有大感受野,又有小的感受野,更得于后续的任务。

5. 补充

Tips:
使用空间多用卷积核的过程中,多个二级卷积核使用了相同的stride和padding,理由有二。一,由二级卷积核生成的特征图尺寸需要保持一致;二,二级卷积核的中心元素是一样的,s维特征是x中某个特征像素的多尺度表示。

Discuss:
上文提到的卷积方式,最后是将多个卷积核的结果做了一个concat操作,作者在discuss中有提到如果做的是add操作会如何,这有待进一步的探究。

三、通道多用卷积核

1. 概括

通道多用卷积核本质上和空间多用卷积核是一样的。区别在于,一个是基于平面生成二级卷积核(会有不同的尺寸),一个是在基于通道生成二级卷积核(尺寸一样,对应的通道不一样)。
Learning Versatile Filters for Efficient Convolutional Neural Networks - 图38

2. 具体过程

使用通道多用卷积核得到的输出为
Learning Versatile Filters for Efficient Convolutional Neural Networks - 图39
g是通道上的stride,Learning Versatile Filters for Efficient Convolutional Neural Networks - 图40是二级卷积核的通道数
Learning Versatile Filters for Efficient Convolutional Neural Networks - 图41是主卷积核在给定Learning Versatile Filters for Efficient Convolutional Neural Networks - 图42和g的情况下得到的第i个二级卷积核
因此,一个卷积核会被同时使用n次以产生更多的特征图。

假设初始卷积核1个,尺寸为5*5*24, 生成了一个特征图;g=1, Learning Versatile Filters for Efficient Convolutional Neural Networks - 图43=23, 则生成了两个二级卷积核,尺寸为5*5*23,只在对应通道执行计算,舍弃不能计算的部分,可得到两个特征图。

四、实验

1. MNIST上的结果

空间多用卷积核
baseline是LeNet, Versatile-Model 1表示的是空间多用卷积核采用Add操作(我觉得这个可以忽略),Versatile-Model 2和3使用了空间多用卷积核,区别在于Model 3的bias(Learning Versatile Filters for Efficient Convolutional Neural Networks - 图44)是共享的。
Learning Versatile Filters for Efficient Convolutional Neural Networks - 图45

卷积核可视化结果
Learning Versatile Filters for Efficient Convolutional Neural Networks - 图46
原始卷积核还是有比较多冗余的,本文使用的卷积核则差异较大,结构更复杂。

通道多用卷积核
不同取值下的结果对比
Learning Versatile Filters for Efficient Convolutional Neural Networks - 图47

2. ImageNet 2012上的结果

Learning Versatile Filters for Efficient Convolutional Neural Networks - 图48
Versatile-AlexNet用的是空间多用卷积核,Versatile v2-AlexNet在Versatile-AlexNet基础上使用了$c-\hat{c}=1, g=1$的通道多用卷积核。

3. 和其它轻量化网络的比较

Learning Versatile Filters for Efficient Convolutional Neural Networks - 图49

五、代码探究

作者开源了代码,使用的是pytorch0.4,定义了多用卷积接口VConv2d,能替代任何CNN网络中的nn.Conv2d

源码如下:

  1. class VConv2d(nn.modules.conv._ConvNd):
  2. """
  3. Versatile Filters
  4. Paper: https://papers.nips.cc/paper/7433-learning-versatile-filters-for-efficient-convolutional-neural-networks
  5. """
  6. def __init__(self, in_channels, out_channels, kernel_size, stride=1,
  7. padding=0, dilation=1, groups=1, bias=True, delta=0, g=1):
  8. kernel_size = _pair(kernel_size)
  9. stride = _pair(stride)
  10. padding = _pair(padding)
  11. dilation = _pair(dilation)
  12. super(VConv2d, self).__init__(
  13. in_channels, out_channels, kernel_size, stride, padding, dilation,
  14. False, _pair(0), groups, bias)
  15. self.s_num = int(np.ceil(self.kernel_size[0]/2)) # s in paper, 空间多用卷积核的数量
  16. self.delta = delta # c-\hat{c} in paper, 为0的时候表示不使用通道卷积核
  17. self.g = g # g in paper,表示通道上的stride
  18. self.weight = nn.Parameter(torch.Tensor(
  19. int(out_channels/self.s_num/(1+self.delta/self.g)), in_channels // groups, *kernel_size)) # weight的维度(卷积核数量,每组的通道数,卷积核的维度)
  20. self.reset_parameters()
  21. def forward(self, x):
  22. x_list = []
  23. s_num = self.s_num # 空间多用卷积核的数量
  24. ch_ratio = (1+self.delta/self.g) # 通道多用卷积核的数量
  25. ch_len = self.in_channels - self.delta # 通道多用卷积核的通道数
  26. for s in range(s_num):
  27. for start in range(0, self.delta+1, self.g):
  28. # 取出卷积核的相关数据
  29. weight1 = self.weight[:, :ch_len, s:self.kernel_size[0]-s, s:self.kernel_size[0]-s]
  30. # s:self.kernel_size[0]-s可以取出某一尺寸的卷积核
  31. # 取出输入数据中需要用来计算的相关部分
  32. if self.padding[0]-s < 0:
  33. h = x.size(2) # x:(batch_size, 通道数,宽,高)
  34. x1 = x[:,start:start+ch_len,s:h-s,s:h-s] # 通道+尺度(?)上的舍弃
  35. padding1 = _pair(0)
  36. else:
  37. x1 = x[:,start:start+ch_len,:,:]
  38. padding1 = _pair(self.padding[0]-s)
  39. # 执行卷积计算
  40. x_list.append(F.conv2d(x1, weight1, self.bias[int(self.out_channels*(s*ch_ratio+start)/s_num/ch_ratio):int(self.out_channels*(s*ch_ratio+start+1)/s_num/ch_ratio)], self.stride,
  41. padding1, self.dilation, self.groups)) # 保存结果
  42. x = torch.cat(x_list, 1) # 拼接
  43. return x