前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >卷积神经网络学习路线(十七) | Google CVPR 2017 MobileNet V1

卷积神经网络学习路线(十七) | Google CVPR 2017 MobileNet V1

作者头像
BBuf
发布2020-02-21 11:21:08
5550
发布2020-02-21 11:21:08
举报
文章被收录于专栏:GiantPandaCVGiantPandaCVGiantPandaCV

前言

这是卷积神经网络的第十七篇文章,Google 2017年发表的MobileNet V1,其核心思想就是提出了深度可分离卷积来代替标准卷积,将标准卷积分成Depthwise+Pointwise两部分,来构建轻量级的深层神经网络,这一网络即使现在也是非常常用的。论文原文地址和代码实现见附录。

网络结构

在本节中,论文首先描述MobileNet V1的核心层----深度可分离卷积层。然后介绍MobileNet V1网络结构,并以两个模型缩小参数(Width MultiplierResolution Multiplier)作为总结。

深度可分离卷积

MobileNet V1模型基于深度可分离卷积,它是factorized convolutions的一种,而factorized convolutions将标准化卷积分解为深度卷积和卷积(pointwise convolution)。对于MobileNet V1,深度卷积将单个滤波器应用到每一个输入通道。然后,点卷积用卷积来组合深度卷积的输出。我们知道,标准卷积是直接将输入通过卷积的方式组合成一组新的输出。而深度可分离卷积则将其分成两层,一层用于卷积,一层用于组合。这种分解过程能极大减少计算量和模型大小。Figure 2展示了如何将一个标准卷积分解为深度卷积和的点卷积。

标准卷积使用一个和输入数据通道数相同的卷积核执行逐个通道卷积后求和获得一个通道的输出,计算量为,其中代表输入的通道数,为卷积核的宽和高,一个卷积核处理输入数据时的计算量为: 其中为输入的宽和高,如果在某一个卷积层使用个卷积核,那么这一卷积层的计算量为:

深度可分离卷积首先使用一组通道数为的卷积核,每次只处理一个输入通道,并且这一组卷积核的个数是和输入通道数相同的。执行完上面的深度卷积后,再使用通道数为输入数据通道数大小的的卷积来组合之前输出的特征图,将最终输出通道数变为一个指定的数量。

从理论上来看,一组和输入通道数相同的2D卷积核(通道数为,即深度卷积或者说分组卷积)的运算量为:

而3D(标准卷积)的卷积核的运算量为: 因此这种组合方式的计算量为:

因此,深度可分离卷积相比于标准卷积计算量的比例为:

然后举个例子,给定三个通道的的图像,VGG16网络的第个卷积层输入的是尺寸为的特征图,通道数为,卷积核尺寸为,卷积核个数为,标准卷积计算量按照上面的公式计算就是:

如果采用深度可分离卷积,计算量为:

这两者计算量的比值为:

可以看到将一个标准卷积换成深度可分离卷积之后模型的计算量减少了倍。

MobileNet V1 网络结构

MobileNet网络结构是以深度可分离卷积为基础单元建立的,其中第一层是标准卷积。MobileNet V1的完整网络结构定义在Table1中。所有卷积层后面都接了BN层和ReLU非线性激活层,但最后的全连接层例外,它没有非线性激活函数,是直接馈送到Softmax层进行分类。在Figure 3还比较了标准卷积和深度可分离卷积(都跟着BN层和ReLU层)的区别。深度可分离卷积和第一个标准卷积均可以处理下采样问题,并且在最后一个全连接层前面还接了一个全局平均池化层,将特征图的长宽变成。如果将Depthwise卷积层和Pointwise卷积层算成不同层的话,MobileNet V1一共有28层。

当然,仅仅通过减少网络乘加操作对于网络加速是不够的,确保这些操作能够有效实现也很重要。例如,非结构化的稀疏矩阵操作通常不比密集矩阵运算快,除非是非常稀疏的矩阵。而MobileNet V1的模型结构几乎将全部的计算复杂度放到了卷积中。这可以通过高度优化的通用矩阵乘法(GEMM)来实现。通常标准卷积如卷积,卷积由GEMM算法实现,但需要使用im2col在内存中对数据进行重排,以将其映射到GEMM可以使用的方式。这个方法在流行的Caffe深度学习框架中正在使用。的卷积不需要在内存中重排就可以直接被GEMM(最优化的数值线性代数算法之一)实现。MobileNet V1的卷积占了总计算量的95%,并且也占了75%的参数(见Table 2)。而几乎所有的额外参数都在全连接层。

这里写图片描述

模型瘦身因子

虽然MobileNet V1网络结构已经很小并且高效,但特定场景或应用程序中可能需要更小更快的模型。为了构建这些较小且计算量较少的模型,论文引入了一个非常简单的参数,称为Width multiplier。这个参数的作用是在每层均匀地缩减网络宽度。对于一个给定的卷积层和,输入通道的数量从变成,输出通道的数量从变成。深度可分离卷积的计算复杂度变成:

其中,通常设为,,和。表示基准MobileNet V1,而则表示瘦身的MobileNet V1。有减少计算复杂度和参数数量(大概倍)的作用。并且Width Multiplier参数可以应用于任何模型结构,以定义一个具有可接受准确率,速度和大小的新模型。

分辨率缩减因子

这里要介绍的第二个超参数是分辨率缩减因子,又叫Resolution multiplier。我们将其应用于输入图像,并且每个层的特征图分辨率随之被减去相同的倍。实际操作的时候,我们通过输入分辨率隐式的设置。是最基础的MobileNet V1模型,而示瘦身的MobileNet V1。Resolution multiplier同样可以减少的计算复杂度。

我们以MobileNet V1中的一个典型的卷积层为例,看看深度可分离卷积,Width MultiplierResolution Multiplier具体降低了多少计算复杂度和参数量。Table 3展示了将上述Trick应用于该层,得到的计算复杂度(FLPOs)和参数数量(Params)对比结果。

实验结果

Table4-7展示了上面介绍的一系列参数和深度可分离卷积在ImageNet上的精度以及模型的参数量/计算量 的对比结果。

下面的Figure 4展示了在ImageNet,个模型的准确率(,)和计算复杂度的关系。结果近似为log关系,并在α有一个显著降低。

Figure 5展示了在ImageNet上,个模型的准确率(,)和参数数量的关系。不同颜色代表不同的分辨率。参数数量不会因输入分辨率不同而不同。

Table 8比较了基准的的MobileNet V1和的GoogleNet以及VGG16的一些指标。可以看到MobileNet V1和VGG16准确率相近,但模型大小小了32倍,计算量也小了倍。MobileNet V1比GoogleNet更加精确,并且模型大小更小,计算复杂度也少了倍。

Table 9比较了瘦身后的(Width multiplier ,输入分辨率)的MobileNet V1。瘦身后的MobileNet V1准确率比AlexNet好大约4%,但模型大小小了45倍,计算复杂度也小了倍。在模型尺寸差不多的情况下,它比SqueezeNet有更高的准确率,而计算复杂度降低了倍。

MobileNet V1还可以作为Backbone网络应用在现代目标检测系统中。根据2016 COCO冠军的工作,论文报告了针对COCO数据集使用MobileNet V1做Backbone进行目标检测的结果。从Table 13中可以看到,使用相同Faster-RCNN和SSD框架,MobileNet V1和VGG,InceptionV2分别做检测模型的Backbone进行了比较。其中,SSD使用了的输入分辨率(SSD300),而Faster-RCNN使用了和的分辨率(Faster-RCNN300,Faster-RCNN600)。这个Faster-RCNN模型每张图考虑个候选框。模型通过COCO数据集上训练(排除8000张minival图),然后在minival测试集上测试。对于这两个框架,MobileNet V1可以实现与其他Backbone网络的相似结果,但计算复杂度和模型大小都小了非常多。Figure6展示了一个使用SSD做模板检测的可视化例子。

FaceNet模型是最先进的人脸识别模型。它基于TripletLoss构建人脸特征。为了构建一个移动端的FaceNet模型,论文使用Distillation方法去训练MobileNet FaceNet模型,实验结果可以在Table 14中看到。

结论

这篇论文提出了一种基于深度可分离卷积的新型模型架构,称为MobileNet V1。接着讨论了一些可以得到高效模型的重要设计方法并展示了如何通过使用Width MultiplierResolution Multiplier来构建更小更快的MobileNet V1模型,以合理的精度损失来减少模型尺寸和提高模型运行速度。最后,将不同的MobileNet V1结构与SOTA的网络模型进行比较,展示了尺寸,速度和精度方面的差异。

Pytorch代码实现

import torch
import torch.nn as nn
import torch.nn.functional as F


class Block(nn.Module):
    '''Depthwise conv + Pointwise conv'''
    def __init__(self, in_planes, out_planes, stride=1):
        super(Block, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=in_planes, bias=False)
        self.bn1 = nn.BatchNorm2d(in_planes)
        self.conv2 = nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=1, padding=0, bias=False)
        self.bn2 = nn.BatchNorm2d(out_planes)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = F.relu(self.bn2(self.conv2(out)))
        return out


class MobileNet(nn.Module):
    # (128,2) means conv planes=128, conv stride=2, by default conv stride=1
    cfg = [64, (128,2), 128, (256,2), 256, (512,2), 512, 512, 512, 512, 512, (1024,2), 1024]

    def __init__(self, num_classes=10):
        super(MobileNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(32)
        self.layers = self._make_layers(in_planes=32)
        self.linear = nn.Linear(1024, num_classes)

    def _make_layers(self, in_planes):
        layers = []
        for x in self.cfg:
            out_planes = x if isinstance(x, int) else x[0]
            stride = 1 if isinstance(x, int) else x[1]
            layers.append(Block(in_planes, out_planes, stride))
            in_planes = out_planes
        return nn.Sequential(*layers)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.layers(out)
        out = F.avg_pool2d(out, 2)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out

附录

  • 论文原文:https://arxiv.org/pdf/1704.04861.pdf
  • 参考:https://baijiahao.baidu.com/s?id=1566004753349359&wfr=spider&for=pc
  • 代码实现:https://github.com/kuangliu/pytorch-cifar

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GiantPandaCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 网络结构
    • 深度可分离卷积
      • MobileNet V1 网络结构
        • 模型瘦身因子
          • 分辨率缩减因子
          • 实验结果
          • 结论
          • Pytorch代码实现
          • 附录
          相关产品与服务
          人脸识别
          腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档