轻量级网络 - PVANet & SuffleNet

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linolzhang/article/details/76285326

一. PVANet

       论文:PVANET: Deep but Lightweight Neural Networks for Real-time Object Detection    【点击下载

       Caffe代码:【Github

       设计了一种轻量级的网络,取名叫 PVANet,特点是 Channel少、Layer多,在 VOC2007 和 VOC2012  精确度分别达到了 84.9% 和 84.2%,但计算量不到采用 ResNet-101 网络的 10%。

       论文的核心要点:

1)改进的 C.ReLU

      前面几层 用到了 CReLU,Concatenated Rectified Linear Units。

      CReLU 来源于在 AlexNet 上的一个有趣的实验(参考论文【CReLU】):低层的卷积层中的一些滤波器核存在着负相关程度很高的滤波器核,而层次越高的卷积层,这一现象越不明显。作者把这一现象称为 pairing phenomenon。

      根据这种特性,通过 Negation 实现 Concatenation,在不损失精度的情况下可以减少一半计算量。

      作者基于 CReLU 进行了改进,添加了 Scale/Bias 层(见下图左),允许每个channel(通道)的斜率和激活阈值与其相反的 Channel 不同。

    

2)使用 Inception Net

扫描二维码关注公众号,回复: 3807897 查看本文章

      “Inception 没有广泛应用在现有网络中”,目前来看使用的确实也不少了,不纠结这个,Inception 的优点是通过不同尺度的卷积核 对应不同大小的感受野,从而适应不同大小的目标。

      上图右侧是 Inception 的网络结构,作者用两个 3*3 的 Conv 替代 5*5 的 Conv,其中 1*1 的 Conv保留特征尺度,直接连接定义 残差。

3)深度网络训练

      a)使用了 Residual Net 和 BN(Batch Norm),ResNet 与 Inception Layer 连接;

      b)通过自定义策略 “Plateu” 动态调整学习率,如果 moving average of loss 在迭代周期内低于一个预设值,触发 “on-plateau”,将学习率动态减少一个常量。

           从一般意义上来说,动态调整学习率 可以有效避免震荡,提高训练精度。

4)整体设计

      以表的形式给出各层的 Detail:

      

5)Hyper-feature concatenation

      多尺度的特征组合在很多文献中都有大量应用,文中用在目标检测上,能够对多尺度的目标进行有效检测。

      如下图所示,采用了三个不同 Scale 进行 Feature 联合。

      

       PVA 是个轻量级网络,基本能够达到实时(Titan X),对于实时系统应用的童鞋可以考虑。

【训练过程】

1)安装 Caffe 依赖库

      必要的 caffe 依赖库:

   sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
   sudo apt-get install --no-install-recommends libboost-all-dev
   sudo apt-get install libatlas-base-dev  # sudo apt-get install libopenblas-dev
   sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev
      安装 CUDA 和 cuDNN (请参考其他教程,这里不再展开)

2)下载 PVANet

      > 下载 Github 源码,直接下载或 命令行:

   Git clone --recursive https://github.com/sanghoon/pva-faster-rcnn.git

       > 根据自己的配置修改 Makefile.config 文件:

   cd $pva-faster-rcnn/caffe-fast-rcnn
   cp Makefile.config.example Makefile.config
          需要修改的几个地方:
   USE_CUDNN := 1
   CUSTOM_CXX := g++
   CUDA_ARCH := -gencode arch=compute_52,code=sm_52
   BLAS := atlas
   PYTHON_INCLUDE := /usr/include/python2.7 \
	             /usr/lib/python2.7/dist-packages/numpy/core/include
   PYTHON_LIB := /usr/lib
   WITH_PYTHON_LAYER := 1 
   INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial/

        MakeFile:

   LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_serial_hl hdf5_serial

       pva-faster-rcnn/lib/setup.py:

   extra_compile_args={'gcc': ["-Wno-unused-function"],
                       'nvcc': ['-arch=sm_52',
  > 编译 Cython:
   cd $pva-faster-rcnn/lib
   make
      > 编译 caffe 和 pycaffe:
   cd $pva-faster-rcnn/caffe-fast-rcnn
   make –j8 & make pycaffe & make distribute

      fatal error: caffe/proto/caffe.pb.h: No such file or directory

   $ protoc src/caffe/proto/caffe.proto --cpp_out=.
   $ mkdir include/caffe/proto
   $ mv src/caffe/proto/caffe.pb.h include/caffe/proto

      执行完后修改bashrc文件,添加python path

   sudo gedit ~/.bashrc
   export PYTHONPATH=${HOME}/caffe/distribute/python:$PYTHONPATH
   export LD_LIBRARY_PATH=${HOME}/caffe/build/lib:$LD_LIBRARY_PATH

    使得python能够找到caffe的依赖。

3)下载VOC数据

      按照顺序执行下载及解压(否则解压不到一个文件夹)

   wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
   wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
   wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar
   tar xvf VOCtrainval_06-Nov-2007.tar
   tar xvf VOCtest_06-Nov-2007.tar
   tar xvf VOCdevkit_08-Jun-2007.tar
      将得到的 VOCdevkit,建立软链接(命名为 VOCdevkit2007),并Copy到 $pva-faster-rcnn/data/ 目录下。

4)测试预训练模型

      进入根目录,按如下脚本测试:

   # Download PVANet detection model for VOC2007
   . ./models/pvanet/download_voc2007.sh
   # Download PVANet detection model for VOC2012 (published model)
   . ./models/pvanet/download_voc_best.sh
   # (Optional) Download all available models (including pre-trained and compressed models)
   . ./models/pvanet/download_all_models.sh
   # (Optional) Download ILSVRC2012 (ImageNet) classification model
   . ./models/pvanet/download_imagenet_model.sh
      测试 demo:
   python ./tools/test_pvanet.py

5)自定义训练

      > 修改训练 类别(num_classes)

          打开文件 /models/pvanet/example_finetune/train.prototxt

          修改 input、cls_score、bbox_pred、roi-data 中的 num_classes(如果只检测1类的话,改为2)

      > 修改 lib/datasets/pascal_voc.py

         self._classes = ('__background__', # always index 0

         'people')(只有这一类)

      > 修改 lib/datasets/imdb.py 

        在代码行 boxes[:, 2] = widths[i] - oldx1 - 1 下面加入代码:

   for b in range(len(boxes)):
       if boxes[b][2]< boxes[b][0]:
           boxes[b][0] = 04)

      > 编译修改脚本

         进入 lib/datasets 目录,删除原来的 pascal_voc.pyc 和 imdb.pyc 文件(.pyc 是Python编译后的文件),重新编译:

   python
   >>>import py_compile
   >>>py_compile.compile(r'pascal_voc.py')
   >>>py_compile.compile(r'imdb.py')

      > 训练及测试数据

   cd $pva-faster-rcnn
   ./tools/train_net.py --gpu 0 --solver models/pvanet/example_finetune/solver.prototxt --weights models/pvanet/full/test.model --iters 100000 --cfg models/pvanet/cfgs/train.yml --imdb voc_2007_trainval
      测试模型
   ./tools/test_net.py --gpu 0 --def models/pvanet/example_finetune/test.prototxt --net output/faster_rcnn_pavnet/voc_2007_trainval/pvanet_frcnn_iter_100000.caffemodel --cfg models/pvanet/cfgs/submit_160715.yml

6)类别设置

(cudaSuccess 8 vs. 0)一般情况下都是因为显卡的计算能力不同而导致的,修改 py-faster-rcnn/lib/setup.py 的第135行,将arch改为与你显卡相匹配的数值,(GTX1080,计算能力是6.1,就将sm_35改成了sm_61)然后删除utils/bbox.c,nms/cpu_nms.c ,nms/gpu_nms.cpp 重新编译即可.


二. SuffleNet

       论文:ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices    【点击下载

       这篇文章出自 Face++ 的孙剑大神组,主要目的是通过减少网络计算量,达到在移动端应用的目的。文章比较 MobileNet (State-of-the-art),在同样计算量的情况下有 6.7% 的提升。

       SuffleNet 是属于模型优化的范畴,对于模型优化有很多种方法,这里先大致列一下,后面会有专门的总结介绍。

> Efficient Model Designs(高效的模型设计)

    这里主要强调两种加速计算的方法,Group Convolution 和 Depthwise Convolution,也正是本文所采用的模型优化设计思路。

    Group Convolution 最早来自于 AlexNet,经典的拓扑图展示了把 Channel 划分到不同 Group 进行卷积,原文是为了在两个 GPU 计算,这是最早的通道拆分概念;

    Depthwise Separable Convolution  将 标准的Conv操作 分解成一个 Depthwise Conv(独立通道) 和一个 PointWise Conv(1*1的卷积),以此减少计算量;

         Depthwise 每个卷积核(Filter)只对一个 Channel 进行卷积计算,Pointwise Conv 执行通道合并,可以理解为:

         Depthwise Separable Convolution = Depthwise Convolution + Pointwise Convolution

    基于该思路设计的框架如 Xception,ResNeXt,我傻傻的分不太清, MobileNet 也是这个思路。

> Model Acceleration(模型加速)

    Pruning(剪枝) 是最直观的一种加速方法,思路比较简单,即去除权值较小的 Connection,或者减少 Channel 数量,得到稀疏的网络连接。

    Quantization(量化) 用于参数压缩,包括下面两个方向:

         a)将 Float32 量化为 8bit 定点数或更少,减少模型计算量 和 参数存储大小(缺点是精度下降),同时借助 SIMD 等策略实现批量计算;二值化网络是参数量化的一个极端情况,比较典型的是 BinaryNet 和 Xnor-net。

         b)权值共享 -通过对权值进行压缩来得到共享权值,共享信息一般通过聚类来得到。

    Factorization(因式分解) 主要用于降低全连接层的计算。

    Distilling(知识迁移)将大模型训练的知识 迁移到 小模型。可以看一下 Hinton 的蒸馏模型 - Distilling the knowledge in a neural network。


  ● Channel Shuffle

       Shuffle 是本文的核心概念,引入 Shuffle 是为了解决 Group Convolution 的问题:

(a)只用 GConv 来做的话,卷积只在 Group Channel 内部计算,Group 之间(下图颜色区分)相互独立;

         问题在于不同 Group 之间没有信息Flow,缺乏 inter 信息,模型精度会比较差。

(b)不同 Group 之间的 Channel 重新分配,增加 Group 之间的信息 Flow;

         重新分配与 原始的 Conv 一样,都加入了 inter 信息,但计算量降低很多。

(c)作者加入的 Channel Shuffle,实现与(b)一样的功能;

         专门提到通过 Shuffle 方式,两个 GConv(GConv1 & GConv2) 之间的 Group 是可以不同的。

        

  ● ShuffleNet Unit

       ShuffleNet 单元引入了上面的 Shuffle 层,先来看图:

        

       图(a)是原始的 Bottle Neck Units,引入了 3*3 的 DepthWise Conv(比较重要),这里 Depthwise 是指在每个独立的通道进行计算,通道之间不交叠,Depthwise Conv 最大层度上减少计算量。前面讲过,采用这总结构的网络包括:ResNet、Xception 和 MobileNet。

       可以看到,图(a)中的 1x1 Conv 并未做优化,可以认为全部计算的(full connection),根据作者统计这部分计算量占比达到 93.4%,这个比例相当惊人,不优化不足以平民愤,于是该 Channel Shuffle 出场了,参考上图(b)来看作者的改进包括哪些:

1)通过 1x1 的 GConv+Shuffle 替代原来的 1x1部分,在不降低计算精度的情况下大大减少计算量;

2)去掉了 DWConv后面的 ReLU部分,这个可以自己看论证;

       上图(c)给出了另一种结构:

1)在 ShortCut 添加了 Avg Pool 实现降采样,同时将 DWConv Stride 改为2,与之匹配;

2)用 Concat 替换原来的 Add,增加 Channel 数量;

  ● 网络架构

       ShuffleNet 网络结构也比较清晰,如下图:

                

       另外 Group 的 size 数量影响分类误差,对于固定计算量的情况,Group越多,对应的channel 通过也就越多,通常精度会提升,当然不会无限提升,在和 Filter 数量达到一定比例的情况下(可以理解为混淆比较均匀),精度最高。

       作者通过 Scale 来控制 Filter 数量,Filter越少,计算量相应也就越少。

       来看下图:

        

  ● 实验对比

       采用ResNeXt 的方法进行训练,只做了两个小的改动:

1)将权值衰减从1e-4 减少为 4e-5;

2)只用了简单的 Scale 做数据增强;

       这样做的依据是 小网络通常容易欠拟合 而不是过拟合,类似的 MobileNet 也采用了同样的策略进行训练。

       Table3 对比了 Channel Shuffle 带来的作用:

        

       下面给出了 ShuffleNet 与 经典网络、轻量级MobileNet 之间的对比:

        

       与经典网络的复杂度比较(在同样准确度的情况下):

        

       在 MS COCO 上测试 ShuffleNet 的泛化性能:

       

       最后给出实测数据,相对于 AlexNet 有 13倍的提高:

                

猜你喜欢

转载自blog.csdn.net/linolzhang/article/details/76285326
今日推荐