G-GhostNet(IJCV 2022)原理与代码解析
paper:GhostNets on Heterogeneous Devices via Cheap Operations
code:https://github.com/huawei-noah/Efficient-AI-Backbones/blob/master/g_ghost_pytorch/g_ghost_regnet.py
前言
本文提出了两种轻量网路,用于CPU端的C-GhostNet和用于GPU端的G-GhostNet。前者就是20年的原版GhostNet,这里只是换了个名字,具体可见GhostNet(CVPR 2020) 原理与代码解析,这里不再详细介绍。本文主要介绍新提出的基于GPU端的G-GhostNet。
存在的问题
之前的轻量型骨干网络大都以降低模型FLOPs为准则专门为CPU设计的,但由于CPU和GPU的硬件架构存在明显的差异,一些FLOPs较小的操作(特别是depth-wise convolution和channel shuffle)在GPU上并不是那么高效。实际上这些操作通常具有较低的arithemetic intensity,即计算和内存操作的比值,无法充分利用GPU的并行计算能力。
本文的创新点
在许多CNN骨干网络的架构中,一个stage通常包含多个卷积层或block,C-GhostNet研究的是一个卷积层生成的特征图中通道信息的冗余,而G-GhostNet研究的是多个block之间的特征相似性和冗余,并通过观察发现跨block的特征冗余是存在的,提出了G-Ghost stage,一个stage的最终输出一部分是和原来一样经过多个block得到的,另一部分通过廉价操作得到,最终将两部分拼接得到输出,大大降低了计算成本。
方法介绍
低FLOPs的操作比如深度可分离卷积在GPU上不那么高效,Radosavovic等人提出用激活activation来衡量网络的复杂度,在GPU上相比于FLOPs延迟和激活的相关性更大,也就是说,如果我们可以删去部分特征图减少激活大概率就能降低网络的延迟。通常一个CNN网络由多个stage构成,每个stage又包含多个block,本文旨在减少stage中的特征冗余大大减少中间特征,从而降低计算成本和内存使用。
对于CNN中的某个stage,有 \(n\) 层比如AlexNet或 \(n\) 个block表示为 \(\left \{ L_{1},L_{2},...,L_{n} \right \} \),对于输入 \(X\) 第一个block和最后一个block的输出为

要获得最终的输出 \(Y_{n}\),输入需要经过多个block的处理,这需要大量的计算。下图是ResNet34的第三个stage中第一个block和最后一个block的输出特征图,尽管最后一个block的输出经过了前5个block的处理,其中有些特征与第一个block的输出仍然非常相似,这意味着这些特征可以通过对低级特征的简单转换来得到。

作者将深层特征分为comlicated特征和ghost特征,前者仍然通过多个block来生成,后者可以通过对浅层特征的简单转换来得到。对于一个有 \(n\) 个block的stage,其输出为 \(X\in \mathbb{R}^{c\times h\times w}\),我们将复杂特征表示为 \(Y^{c}_{n}\in \mathbb{R}^{(1-\lambda)c\times h\times w}\),ghost特征表示为 \(Y^{c}_{g}\in \mathbb{R}^{\lambda c\times h\times w}\),其中 \(0\le \lambda \le 1\)。复杂特征通过 \(n\) 个block得到

其中 \(L'_{2},...,L'_{n}\) 是相比于式(7)宽度为 \((1-\lambda)\times width\) 的thin block。\(Y^{g}_{n}\) 可以通过对 \(Y_{1}\) 的廉价操作 \(C\) 得到

其中廉价操作 \(C\) 可以是1x1或3x3卷积。将 \(Y^{c}_{n}\) 和 \(Y^{g}_{n}\) 拼接起来就得到了最终输出

Intrinsic Feature Aggregation
尽管简单特征可以通过廉价操作近似得到,但式(9)中的 \(Y^{g}_{n}\) 可能缺乏需要多层才能提取到的深层信息,为了弥补缺乏的信息,作者提出用complicated分支的中间特征来提高廉价操作的表示能力。首先提取复杂分支的中间特征 \(Z\in \mathbb{R}^{c'\times h\times w}=[Y^{c}_{2},Y^{c}_{3},...,Y^{c}_{n}]\) 将其按通道concat起来,其中 \(c'\) 是通道总数,如下图所示

通过转换函数 \(\tau \) 对 \(Z\) 进行变换,然后与 \(Y^{g}_{n}\) 进行融合。

转换函数 \(\tau\) 包括一个全局平均池化和一个全连接层

其中 \(W\in \mathbb{R}^{c'\times \lambda c}\),\(b\in \mathbb{R}^{\lambda c}\) 分别是权重和偏置。
下图分别是原始的CNN结构、没有特征聚合的G-Ghost stage和有特征聚合的G-Ghost stage

代码解析
下面是G-Ghost stage的官方实现,好像和文章中的描述有些出入。forward函数中首先self.base就是上图中的Block 1,出入一是文中Block 1的输出好像是完整的分别进入complicated分支和cheap分支,而实现中是将Block 1的输出按 \(\lambda\) 沿通道分为两部分分别进入两个分支。出入二是从上图可以看出是对Block 2 - Block n进行特征聚合,而实现中还包括Block 1,即代码中的x0。self.merge是转换函数 \(\tau\),其中全连接层用卷积层实现。
class Stage(nn.Module):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.dilationif dilate:self.dilation *= stridestride = 1if stride != 1 or self.inplanes != planes:downsample = nn.Sequential(conv1x1(inplanes, planes, stride),norm_layer(planes),)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_planesself.merge = nn.Sequential(nn.AdaptiveAvgPool2d(1),nn.Conv2d(planes + raw_planes * (blocks - 2), cheap_planes,kernel_size=1, stride=1, bias=False),nn.BatchNorm2d(cheap_planes),nn.ReLU(inplace=True),nn.Conv2d(cheap_planes, cheap_planes, kernel_size=1, bias=False),nn.BatchNorm2d(cheap_planes),)self.cheap = nn.Sequential(nn.Conv2d(cheap_planes, cheap_planes,kernel_size=1, stride=1, bias=False),nn.BatchNorm2d(cheap_planes),)self.cheap_relu = nn.ReLU(inplace=True)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):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 = torch.cat(m_list, 1)m = self.merge(m)c = x0[:, self.raw_planes:]c = self.cheap_relu(self.cheap(c) + m)x = torch.cat((e, c), 1)x = self.end(x)return x
相关文章:
G-GhostNet(IJCV 2022)原理与代码解析
paper:GhostNets on Heterogeneous Devices via Cheap Operationscode:https://github.com/huawei-noah/Efficient-AI-Backbones/blob/master/g_ghost_pytorch/g_ghost_regnet.py前言本文提出了两种轻量网路,用于CPU端的C-GhostNet和用于GPU端…...
Ethercat系列(5)TWcat3激活过程的协议分析(续1)
顺序写系统时间偏移从-》主顺序写时间延迟主-》从从-》主顺序写分布式时钟启动主-》从从-》主读多重写系统时间主-》从从-》主顺序写应用层控制主-》从从-》主顺序读错误计数器主-》从从-》主顺序读应用层状态主-》从从-》主顺序读应用层,广播写错误计数器主-》从从…...
QT入门Input Widgets之QScrollBar
目录 一、界面布局功能 1、界面位置介绍 2、控件界面基本属性 2.1 horizontalScrollBar界面属性 3、样式设置 此文为作者原创,创作不易,转载请标明出处! 一、界面布局功能 1、界面位置介绍 QScrollBar主要分为两种,一种垂直…...
【ML】基于机器学习的心脏病预测研究(附代码和数据集,多层感知机模型)
写在前面: 首先感谢兄弟们的订阅,让我有创作的动力,在创作过程我会尽最大努力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 之前创作过心脏病预测研究文章如下: 【ML】基于机器学习的心脏病预测研究(附代码和数据集,逻辑回归模型) 【ML】基于机…...
工序排序问题--约翰逊法精讲
什么是约翰逊法?约翰逊法是作业排序中的一种排序方法。选出最短加工时间i*,若最短加工时间有多个,任选1个.若i*出现在机床1,它对应的工件先安排加工,否则放在最后安排,安排后划去该工件,重复上两个步骤,直…...
WebDAV之葫芦儿·派盘+网盘精灵
网盘精灵 支持WebDAV方式连接葫芦儿派盘。 推荐一款让您的iPhone、iPod、iPad 变成WebDav客户端的软件,支持从WebDav服务器连接葫芦儿派盘服务进行上传和下载件。 网盘精灵让您的iPhone、iPod、iPad 变成WebDav客户端。功能:WebDav操作、文件共享、本地文件管理...
计算机网络期末知识点总结
计算机网络期末知识点总结第四章—网络层:数据面4.1概述4.2虚电路和数据报网络4.3路由器工作原理4.4网际协议:因特网中的转发和编址第五章 网络层:控制面5.1路由选择算法5.2路由器中的路由选择5.3广播和多播路由选择第六章 链路层(…...
【Vue3 组件封装】vue3 轮播图组件封装
文章目录轮播图功能-获取数据轮播图-通用轮播图组件轮播图-数据渲染轮播图-逻辑封装轮播图功能-获取数据 目标: 基于pinia获取轮播图数据 核心代码: (1)在types/data.d.ts文件中定义轮播图数据的类型声明 // 所有接口的通用类型 export typ…...
电力国家(行业)标准目录
1、3~63kV交流高压负荷开关 GB 3804-90 代替 GB 3804-882、电气装置安装工程35kV及以下架空电力线路施工及验收规范Code for construction and acceptance of 35kVand umder over head power levels electricequipment installation engineeringGB50173—923、带电作…...
如何实现倒序输出
问题 如何实现字符串的大小写转换并倒序输出。 方法 采用Java自带的类方法进行倒序。 package homework4; public class Blog09 { public static void main(String[] args) { String a "HelloWord"; String a2 a.toUpperCase(); String a3 …...
遗留系统的自动化测试策略和实践方法
1 什么是遗留系统 遗留系统是一种旧的方法、旧的技术、旧的计算机系统或应用程序,属于或与以前的、过时的计算机系统有关,但仍在使用中。通常,将系统称为“遗留系统”意味着它可能已经过时或需要更换,但是系统还在对外提供服务,还在不断的迭代,有新的需求不断的交付。Ma…...
【Android】系统源码下载及编译
源码及编译 步骤 1:创建一个空目录来存放源码: mkdir aosp cd aosp步骤 2:获取最新版本的 repo 并签出 android-8.1.0_r1 分支: repo init -u https://android.googlesource.com/platform/manifest -b android-8.1.0_r1其中&am…...
基于HTML实现浪漫情人节表白代码(附源代码)
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
PCL 平面拟合——RANSAC
文章目录 一、基本思想二、代码示例1、参数选择2、核心代码3、完整代码4、结果展示三、关于 RANSAC 的一些思考参考文献一、基本思想 随机抽样一致性算法RANSAC(Random sample consensus)是一种迭代的方法,从一系列包含有离群值的数据中计算数学模型参数的方法。RANSAC算法本…...
【Linux之Shell脚本实战】监控系统的磁盘空间使用率
【Linux之Shell脚本实战】监控系统的磁盘空间使用率 一、脚本要求二、检查本地系统环境1.检查系统版本2.检查系统内核版本三、编写disk.sh脚本1.创建脚本目录2.编写disk.sh脚本3.执行测试脚本四、查看脚本执行日志文件五、本次实践总结1.脚本定时执行2.实践总结一、脚本要求 1.…...
【Python安全编程】Python实现网络主机和端口扫描
文章目录前言环境准备Python实现主机扫描基于ARP协议基于ICMP协议普通版本多线程版本Python实现端口扫描扫描单个端口利用多线程扫描端口后记前言 本文主要讲几个利用Python实现网络扫描的小例子,可以结合多线程或多进程编程改进实例 我曾经走过多遥远的路 跨越过多…...
四大垃圾回收算法七大垃圾回收器
JVM的运行时内存也叫做JVM堆,从GC的角度可以将JVM分为新生代、老年代和永久代。其中新生代默认占1/3堆内存空间,老年代默认占2/3堆内存空间,永久代占非常少的对内存空间。新生代又分为Eden区、SurvivorFrom区和SurvivorTo区, Eden…...
P1217 [USACO1.5]回文质数 Prime Palindromes
[USACO1.5]回文质数 Prime Palindromes 题目描述 因为 151151151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151151151 是回文质数。 写一个程序来找出范围 [a,b](5≤a<b≤100,000,000)[a,b] (5 \le a < b \l…...
用大白话给你科普,到底什么是 API(应用程序编程接口)?
何为API?如果你在百度百科上搜索,你会得到如下结果:API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组…...
企业电子招采系统源码——信息数智化招采系统
信息数智化招采系统 服务框架:Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构:VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术:Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monitor、…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
