GhostNet再升级,GPU上大显身手的G-GhostNet

作者设计出相比C-Ghost更适用于GPU等设备的G-Ghost,在实际延迟与性能之间取得了良好的权衡。Source Code

1、摘要

本文针对网络部署时面临的内存和资源有限的问题,提出两种不同的Ghost模块,旨在利用成本低廉的线性运算来生成Ghost特征图。C-Ghost模块被应用于CPU等设备,并通过简单的模块堆叠实现C-GhostNet。适用于GPU等设备的G-Ghost模块利用阶段性特征冗余构建。最终实验结果表明两种模块分别实现了对应设备上精度和延迟的最佳权衡。

2、引言

在GhostNet(CVPR 2020)出现之前,笔者对冗余特征一直保持刻板的偏见。但不管是过分的抑制冗余,还是过分的增加冗余,都会对架构性能造成不好的影响(存在即合理)。在GhostNet中,作者的等人通过细致的实验观察,提出“以有效方式接受冗余特征图”的思想,将以往的特征生成过程用更廉价的线性运算来替代,从而在保证性能的同时实现轻量化。

如下图所示,对中间特征图进行可视化之后,可以明显看出一些特征表达近似(图中用相同颜色标出的方框),因此作者等人提出,近似的特征图可以通过一些廉价的操作来获得。

据此,作者等人提出GhostNet,并在本文中称作C-GhostNet,因此笔者将解读的重点放在G-Ghost,对C-Ghost仅做回顾。

C-GhostNet中为实现轻量化,使用了一些低运算密度的操作。低运算密度使得GPU的并行计算能力无法被充分利用,从而导致C-GhostNet在GPU等设备上糟糕的延迟,因此需要设计一种适用于GPU设备的Ghost模块。

作者等人发现,现有大多数CNN架构中,一个阶段通常包括几个卷积层/块,同时在每个阶段中的不同层/块,特征图的尺寸大小相同,因此一种猜想是:特征的相似性和冗余性不仅存在于一个层内,也存在于该阶段的多个层之间。下图的可视化结果验证了这种想法(如右边第三行第二列和第七行第三列的特征图存在一定相似性)。

作者等人利用观察到的阶段性特征冗余,设计G-Ghost模块并应用于GPU等设备,实现了一个在GPU上具有SOTA性能的轻量级CNN。

3、C-GhostNet(也就是之前的GhostNet)回顾

4、G-GhostNet

C-GhostNet中使用低运算密度的depth-wise卷积作为生成Ghost特征的廉价操作,对于GPU等设备来说,无法充分利用其并行计算能力。另一方面,如果能去除部分特征图并减少激活,便可以概率地减少 GPU 上的延迟

如何实现这一目标?就得利用导读部分提及的“特征的相似性和冗余性不仅存在于一个层内,也存在于该阶段的多个层之间”。由于现有流行CNN架构中,同一阶段的不同层,其输出特征图的尺寸大小不会发生变化,因此一种跨层的廉价替代便可以通过这一特点来实现。其具体实现过程如下:
在CNN的某个阶段中,深层特征被分为Ghost特征(可通过浅层廉价操作获得)和复杂特征(不可通过浅层廉价操作获得),以图2为例:

但是,直接的特征拼接带来的影响是显而易见的。复杂特征经过逐层提取,包含更丰富的语义信息;而Ghost特征由浅层进行廉价操作所得,可能缺乏一部分深层信息。因此一种信息补偿的手段是有必要的,作者等人使用如下操作来提升廉价操作的表征能力:

如图5,复杂特征经过连续的n个卷积块生成,Ghost特征则由第一个卷积块经过廉价操作所得。其中mix模块用于提升廉价操作表征能力,即先将复杂特征分支中第2至第n层的中间特征进行拼接,再使用变换函数,变换至与廉价操作的输出同域,最后再进行特征融合(如简单的逐元素相加)。


除了大小为1的卷积核,廉价操作还可以用3×3、5×5的卷积核,或者直接的恒等映射来计算。

5、性能对比

6、代码展示

本文只对表2中Ghost-RegNetX-3.2GF进行复现。

代码位置: gghostregnetp.pyPaddleDetection/ppdet/modeling/backbones/gghostregnetp.py

核心代码展示(图5就是核心块)

class Stage(nn.Layer):def __init__(self, block, inplanes, planes, group_width, blocks, stride=1, dilate=False, cheap_ratio=0.5):super(Stage, self).__init__()norm_layer = nn.BatchNorm2Ddownsample = Noneself.dilation = 1previous_dilation = self.dilationself.inplanes = inplanesif dilate:self.dilation *= stridestride = 1if stride != 1 or self.inplanes != planes:downsample = nn.Sequential(conv1x1(inplanes, planes, stride),norm_layer(planes),)#===========获取每个block=============self.base = block(inplanes, planes, stride, downsample, group_width,previous_dilation, norm_layer)self.end = block(planes, planes, group_width=group_width,dilation=self.dilation,norm_layer=norm_layer)#===============================================group_width = int(group_width * 0.75)raw_planes = int(planes * (1 - cheap_ratio) / group_width) * group_widthcheap_planes = planes - raw_planesself.cheap_planes = cheap_planesself.raw_planes = raw_planes#===============block融合=======================self.merge = nn.Sequential(nn.AdaptiveAvgPool2D(1),nn.Conv2D(planes+raw_planes*(blocks-2), cheap_planes,kernel_size=1, stride=1, bias_attr=False),nn.BatchNorm2D(cheap_planes),nn.ReLU(),nn.Conv2D(cheap_planes, cheap_planes, kernel_size=1, bias_attr=False),nn.BatchNorm2D(cheap_planes),
#             nn.ReLU(inplace=True),)#==========文中提出的cheap操作=====================self.cheap = nn.Sequential(nn.Conv2D(cheap_planes, cheap_planes,kernel_size=1, stride=1, bias_attr=False),nn.BatchNorm2D(cheap_planes),
#             nn.ReLU(inplace=True),)self.cheap_relu = nn.ReLU()layers = []downsample = nn.Sequential(LambdaLayer(lambda x: x[:, :raw_planes]))layers = []layers.append(block(raw_planes, raw_planes, 1, downsample, group_width,self.dilation, norm_layer))inplanes = raw_planesfor _ in range(2, blocks-1):layers.append(block(inplanes, raw_planes, group_width=group_width,dilation=self.dilation,norm_layer=norm_layer))self.layers = nn.Sequential(*layers)def forward(self, input):"""可以对照图5进行理解前向传播过程"""x0 = self.base(input)m_list = [x0]e = x0[:,:self.raw_planes]        for l in self.layers:e = l(e)m_list.append(e)m = paddle.concat(m_list,1)m = self.merge(m)c = x0[:,self.raw_planes:]c = self.cheap_relu(self.cheap(c)+m)x = paddle.concat((e,c),1)x = self.end(x)return x

7、ImageNet效果验证

#解压数据集
!mkdir data/ILSVRC2012
!tar -xf ~/data/data105740/ILSVRC2012_val.tar -C ~/data/ILSVRC2012
#导入必要的库
import os
import cv2
import numpy as np
import warnings
import paddle
import paddle.vision.transforms as T
from PIL import Image
warnings.filterwarnings('ignore')# 构建数据集
class ILSVRC2012(paddle.io.Dataset):def __init__(self, root, label_list, transform, backend='pil'):self.transform = transformself.root = rootself.label_list = label_listself.backend = backendself.load_datas()def load_datas(self):self.imgs = []self.labels = []with open(self.label_list, 'r') as f:for line in f:img, label = line[:-1].split(' ')self.imgs.append(os.path.join(self.root, img))self.labels.append(int(label))def __getitem__(self, idx):label = self.labels[idx]image = self.imgs[idx]if self.backend=='cv2':image = cv2.imread(image)else:image = Image.open(image).convert('RGB')image = self.transform(image)return image.astype('float32'), np.array(label).astype('int64')def __len__(self):return len(self.imgs)val_transforms = T.Compose([T.Resize(int(224 / 0.96), interpolation='bicubic'),T.CenterCrop(224),T.ToTensor(),T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])val_transform_384 = T.Compose([T.Resize(int(384 / 0.96), interpolation='bicubic'),T.CenterCrop(384),T.ToTensor(),T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
#获得模型
from g_ghost_regnet_p import regnetx_032
model = regnetx_032()
W0804 23:55:57.808670   145 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.2, Runtime API Version: 10.1
W0804 23:55:57.813205   145 gpu_resources.cc:91] device: 0, cuDNN Version: 7.6.
#加载权重
model.load_dict(paddle.load('/home/aistudio/g_ghost_regnet_p.pdparams'))
model = paddle.Model(model)
#查看模型结构
model.summary((1,3,224,224))
#验证模型效果
model.prepare(metrics=paddle.metric.Accuracy(topk=(1, 5)))
val_dataset = ILSVRC2012('/home/aistudio/data/ILSVRC2012/ILSVRC2012_val', transform=val_transforms, label_list='/home/aistudio/data/ILSVRC2012/ILSVRC2012_val/val_list.txt', backend='pil')
acc = model.evaluate(val_dataset, batch_size=32, num_workers=4, verbose=1)
print(acc)
Eval begin...
step 1563/1563 [==============================] - acc_top1: 0.7756 - acc_top5: 0.9382 - 227ms/step
Eval samples: 50000
{'acc_top1': 0.77562, 'acc_top5': 0.93816}

8、VOC目标检测应用

本项目还将G-GhostNet应用到目标检测中,结合PaddleDetection实现,在VOC上准确率为74.83%。

训练好的VOC权重在/home/aistudio/model_final

!unzip -d /home/aistudio/data/ /home/aistudio/data/data63105/PascalVOC07_12.zip
%cd PaddleDetection/
/home/aistudio/PaddleDetection
!pip install -r requirements.txt
!python setup.py install
!python tools/train.py -c configs/yolov3/yolov3_gghost_voc.yml --eval
#这里使用预先提供好的VOC权重进行验证
yolov3_gghost_voc.yml --eval
#这里使用预先提供好的VOC权重进行验证
!python tools/eval.py -c configs/yolov3/yolov3_gghost_voc.yml -o weights=/home/aistudio/model_final

9、总结与思考

本文利用可视化观察到的现象和大量的实验结果,提出了Ghost特征的思想,利用“特征的相似性和冗余性不仅存在于一个层内,也存在于该阶段的多个层之间”这一猜测,设计出相比C-Ghost更适用于GPU等设备的G-Ghost,并在实际延迟与性能之间取得了良好的权衡。

参考文献

华为轻量级神经网络架构GhostNet再升级,GPU上大显身手的G-GhostNet(IJCV22)

声明

此项目为搬运
原项目链接

CV顶刊!IJCV2022:G-GhostNet相关推荐

  1. 【深度学习】CV顶会|CV顶刊

    CV三大会议 CVPR: International Conference on Computer Vision and Pattern Recognition (每年,6月开会) ICCV: Int ...

  2. CV顶会 CV顶刊

    CV三大会议 CVPR: International Conference on Computer Vision and Pattern Recognition (每年,6月开会) ICCV: Int ...

  3. 顶刊TIP 2022|武汉大学遥感国重团队提出二元变化引导的高光谱遥感多类变化检测网络BCG-Net

    论文标题:Binary Change Guided Hyperspectral Multiclass Change Detection 论文链接:https://ieeexplore.ieee.org ...

  4. 顶刊IJCV 2022!华为GhostNet再升级!全系列硬件上最优极简AI网络

    作者丨王云鹤@知乎 来源丨https://zhuanlan.zhihu.com/p/540547718 编辑丨CVer GhostNet作为近年来最流行的轻量级神经网络架构,其在ARM和CPU端的应用 ...

  5. #今日论文推荐# 顶刊IJCV 2022!华为GhostNet再升级,全系列硬件上最优极简AI网络

    #今日论文推荐# 顶刊IJCV 2022!华为GhostNet再升级,全系列硬件上最优极简AI网络 GhostNet作为近年来最流行的轻量级神经网络架构,其在ARM和CPU端的应用已经非常广泛.而在G ...

  6. 半个月3篇Nature/Science,95后曹原3年8篇顶刊,网友:杀疯了杀疯了

    金磊 萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI "曹原又中了1篇Science!" "你听错了吧,上周不是中的Nature吗?还是2篇." & ...

  7. 顶刊TPAMI 2021!南开大学提出深度霍夫变换:语义线检测新方法

    Deep Hough Transform for Semantic Line Detection 主页:https://mmcheng.net/dhtline/ 论文:http://mftp.mmch ...

  8. 打破985校史!她以独作身份投中顶刊,曾因换方向重读博士7年,科研之路也“坎坎坷坷”……...

    来源:募格学术整理自华中科技大学.量子位.微博.知乎等. 十年磨一剑,打破校史,以独作身份投中数学顶刊,甚至在中国都算是独一份是种什么样的体验? 近日,华中科技大学郇真的论文引起热议,迅速登上知乎热榜 ...

  9. 2022年顶会、顶刊SNN相关论文----------持续更新中

    原文链接:https://blog.csdn.net/qq_43622216/article/details/124163883 2022年顶会.顶刊SNN相关论文 目录 说明 AAAI2022(共7 ...

最新文章

  1. C# 中泛型与非泛型?(摘)
  2. 跨链(5)“蚂蚁区块链”之跨链系统框架
  3. C/C++指针函数和函数指针
  4. 删除排序数组中的重复数字 II
  5. 另一种将线程并入应用程序的方法-委托
  6. TiDB在360云平台的落地
  7. 使用RAID进行磁盘管理
  8. python中异常处理的两种方式_Python 之异常处理
  9. 计算机英语国家线,2018考研英语二国家线是多少
  10. Spark深入浅出企业级最佳实践
  11. 计算H时M分S秒以后是_泵所需轴功率的计算方式
  12. JAVAweb开发中Ajax教程
  13. 国产系统银河麒麟(龙芯MIPS)远程访问自研windows程序
  14. 「Remmina」- 远程桌面客户端(SSH、SFTP、VNC、Windows Remote Desktop、...) @20210402
  15. X上面有一道横线,怎么打出来?
  16. java设置打印机默认纸张_java 打印设置打印A4 A5纸
  17. 计算机画图是什么软件,电脑上画图用什么软件
  18. App瘦身最佳实践(分析了微信、淘宝、微博图片文件的放法)
  19. 蓝汛之,关于硬件设计导致的RF干扰GND导致产生的底噪问题【篇】
  20. 工具箱(安卓)中国特供版。

热门文章

  1. 静态服务器--动态页面 (python)
  2. virtualbox php mac,mac下virtualbox+vagrant安装
  3. 理光Aficio MP C2500扫描到文件夹设置方法
  4. Flutter i18n插件使用
  5. linux---设置环境变量
  6. 关于NX二次开发嵌入MFC的相关入门
  7. 山火賁 (易經大意 韓長庚)
  8. arangodb mysql_ArangoDB数据库入门
  9. 计算机的发展史以及未来 App和Cloud这10年发展很快,被忽略的硬性的螺旋上升 QCon 大会2022
  10. STM32 IO口三种配置方式