CV顶刊!IJCV2022:G-GhostNet

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)

声明

此项目为搬运
原项目链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1619394.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

免费OCR图像识别文字识别API

免费OCR图像识别文字识别API 一、OCR图像识别文字识别二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例 三、温馨提示 一、OCR图像识别文字识别 光学字符识别(Optical Character Recognition, OCR)是指对文本资料的图像文件进行分析识别…

nginx-获取客户端IP地址

上有服务器与客户端中间是有nginx代理服务器的,上游服务器如何获取客户端真实ip地址? nginx代理服务器设置X-Forwarded-For的header参数,代理服务器通过remote_addr获取客户端ip地址,将ip地址写入nginx代理服务器的X-Forwarded-Fo…

企业使用CRM如何统一销售流程管理?

销售流程我们可以理解为,销售人员从寻找潜在客户到最终达成交易的一系列步骤。很多企业通过CRM系统来进行销售流程管理,提高销售效率,实现销售目标。下面我们就来说说,CRM如何进行销售流程管理。 制定统一的销售流程:…

Git基本操作(Idea版)

第一次发布项目(本地->远程) 方式一 通过push的方式推送本地库到远程库(远程已创建好仓库) 这种方式需要提前创建好仓库。 右键点击项目,可以将当前分支的内容 push 到 GitHub 的远程仓库中。 注意&#xff1a…

推荐两个杀毒软件测试网站

VirScan - 多引擎文件在线检测平台 VirusTotal 软件发布前查一下毒还是很有必要的

vue拖拽div盒子实现上下拖动互换

vue拖拽div盒子实现上下拖动互换 <div v-for"(item, index) in formList" :key"index" draggable"true"dragstart"handleDragStart($event, item)"dragenter"handleDragEnter($event, item)"dragover.prevent"han…

深入理解Reactor模型的原理与应用

1、什么是Reactor模型 Reactor意思是“反应堆”&#xff0c;是一种事件驱动机制。 和普通函数调用的不同之处在于&#xff1a;应用程序不是主动的调用某个 API 完成处理&#xff0c;而是恰恰相反&#xff0c;Reactor逆置了事件处理流程&#xff0c;应用程序需要提供相应的接口并…

继域名解析后------------我的网页进不去了!!!(修复方法)

昨天域名解析之后&#xff0c;今天来公司上班发现公司网页进不去了&#xff0c;好在现在是平台升级维护期间&#xff0c;没什么业务。统计过后&#xff0c;发现有一半的公司员工登录不进去。这一半能登陆上的同事所使用的网络是500M电信宽带&#xff0c;而我们这边登录不上的都…

html打开d盘文件,为什么ie浏览器打不开c/d盘的html文件,直接跳出保存

满意答案 pvgpl 2014.02.05 采纳率&#xff1a;42% 等级&#xff1a;12 已帮助&#xff1a;12615人 清理一下磁盘碎片和系统垃圾。 不行就---------------- 请不要盗用我的答案!! 一号方案(新X) 注意(原创): 1.安全模式下&#xff0c;效果更好! 2. 以下所要使用的软件&#…

手把手教会你|Sockets多用户-服务器数据库编程

网络编程经常涉及数据库访问,电子商务更离不开数据库。例如用户请求股票报价、产品价格查询、网上交易等请求,服务器则需要连接对应的数据库,发送查询指令,得到数据库记录,经过处理后,发送给提出这个请求的用户。 在实际应用中,数据库经常由专门管理数据库的服务器运行。…

股票交易规则

交易时间 股票交易时要遵循 价格优先 时间优先&#xff0c;但如果同价又同时报价&#xff0c;那大单优先 具体交易时间规定&#xff1a; 每周一至周五&#xff0c;每天上午9:30至11:30&#xff0c;下午13:00至15:00&#xff0c;法定假期除外。 A股 上海交易所 集合竞价&#…

股票交易接口有没有提供试用的?

我们做量化交易&#xff0c;是需要使用工具的&#xff0c;因为量化交易交易频率很高&#xff0c;如果人工操作经历有限&#xff0c;一般是无法执行到位的&#xff0c;不过股票交易接口一般都需要收费&#xff0c;而且还不便宜&#xff0c;如果可以试用的话&#xff0c;那一定是…

股票自动委托下单html,股票怎么设置自动挂单?股票挂单的方式

股票怎么设置自动挂单?接下来小编为大家介绍。 股票挂单指在股票交易时把所要买进或卖出的股票的名称、数量、价格填写后提交给交易系统等待成交的过程。 传统网上交易下单&#xff0c;需要①从行情软件切换到委托软件&#xff0c;②输入需要买卖股票的代码&#xff0c;③输入…

基于SpringBoot实现MySQL与Redis的数据一致性

问题场景 在并发场景下&#xff0c;MySQL和Redis之间的数据不一致性可能成为一个突出问题。这种不一致性可能由网络延迟、并发写入冲突以及异常情况处理等因素引起&#xff0c;导致MySQL和Redis中的数据在某些时间点不同步或出现不一致的情况。数据一致性问题的级别可以分为三…

list(介绍与实现)

目录 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modififiers 1.2.6 list的迭代器失效 2. list的模拟实现 2.1 模拟实现list 2.2 list的反向迭代器 1.…

代码随想录第32天|122.买卖股票的最佳时机 II,55. 跳跃游戏 ,45. 跳跃游戏 II

122.买卖股票的最佳时机 II 122. 买卖股票的最佳时机 II 思路比较简单 class Solution {public int maxProfit(int[] prices) {int res0,sum0;for(int i0;i<prices.length-1;i){if(prices[i1]-prices[i]>0){sumprices[i1]-prices[i];}ressum>res?sum:res;}return …

笔记本重装win7旗舰版原版操作系统

正常开机的电脑&#xff1a;直接重装&#xff08;最简单&#xff0c;最快&#xff09;、Ghost重装、U盘重装、光盘重装、硬盘安装 不能正常开机的电脑&#xff1a;U盘重装、光盘重装、硬盘安装 注意&#xff1a; 1.windows7原版系统是不带任何驱动程序的&#xff0c;请事先准…

w ndows7旗舰版怎么重装系统,windows7旗舰版iso怎么安装

现在安装系统要求操作简单、方便。硬盘安装方式就是最简单、最方便的系统安装方法。保证电脑能进入系统的前提下&#xff0c;本地硬盘安装windows7旗舰版iso系统&#xff0c;能够让你快速体验新的windows7旗舰版iso系统。接下来详细讲解下安装windows7旗舰版iso系统的操作过程&…

w ndows7旗舰版网卡驱动,Ghost windows7 64位系统旗舰版网卡驱动工具推荐下载

雨林木风Ghost windows7 64位系统旗舰版网卡驱动工具可以使系统能够快速的链接网络&#xff0c;提供丰富的驱动文件&#xff0c;雨林木风Ghost windows7 64位系统旗舰版网卡驱动工具是很多的用户遇到问题都可以解决的一种工具&#xff0c;所以今天我们就来看看吧。 深度技术Gho…

windows7旗舰版安装过程

一&#xff0c;首先我提供一个windows7旗舰版<带激活工具>的下载地址: 7600_x86_zh-cn_Ultimate_DVD.iso 4 s5 T: O7 L. P* g如果连接错误就复制下面地址到迅雷thunder://QUFodHRwOi8vZG93bjIuZ2hvc3QyLmNuLzc2MDBfeDg2X3poLWNuX1VsdGltYXRlX0RWRC5pc29aWg泗水,泗水论坛,…