当前位置: 首页 > news >正文

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,即代码中的x0self.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广播和多播路由选择第六章 链路层&#xff08…...

【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学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…...

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 既是一个质数又是一个回文数&#xff08;从左到右和从右到左是看一样的&#xff09;&#xff0c;所以 151151151 是回文质数。 写一个程序来找出范围 [a,b](5≤a<b≤100,000,000)[a,b] (5 \le a < b \l…...

用大白话给你科普,到底什么是 API(应用程序编程接口)?

何为API&#xff1f;如果你在百度百科上搜索&#xff0c;你会得到如下结果&#xff1a;API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件得以访问一组…...

企业电子招采系统源码——信息数智化招采系统

​ 信息数智化招采系统 服务框架&#xff1a;Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构&#xff1a;VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术&#xff1a;Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monitor、…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…...