RepVGG: Making VGG-style ConvNets Great Again

news2024/11/16 18:34:02

文章地址:《RepVGG: Making VGG-style ConvNets Great Again》

代码地址:https://github.com/megvii-model/RepVGG

文章发表于CVPR2021,文章提出一种将训练态和推断态网络结构解耦的方法。文章认为目前复杂的网络结构能够获取更高的精度,但是存在很明显的缺点:

  1. 多分支结构可能会降低推断速度以及更占用显存。例如resnet的残差结构在多个分支的地方需要复制一份tensor用于分支之间的计算,如下图所示
    在这里插入图片描述

  2. depthwise conv或者shufflenet中的channel shuffle操作对实际落地的支持可能不太好等

对应的只有简单的由 3 × 3 3\times 3 3×3卷积和relu激活组成的网络,有如下几点优势:

  1. 许多多分支的网络虽然在FLOPs上小于VGG,但是推断时并没有更快(例如VGG-16的FLOPs是EfficientNet-B3的8.4倍,但在1080Ti上运行,VGG-16还要快1.6倍)

  2. 多分支网络更耗显存,因为每个分支都需要有一份tensor用于计算直到分支通过加(addition)或者串联(concatenation)的方式合并

  3. 多分支网络更不灵活,例如resnet必须由resnet block组成,而resnet block中最后一个卷积必须与输入保持一致,否则shortcut结构就不能工作了。更不灵活的是,在对网络进行通道剪枝时,多分支的网络剪枝起来很麻烦而且不合理(因为block内,通道数会互相影响)

为了取长补短,文字提出一种重参(re-parameterization)的方式,将训练态的网结构与推断态的网络结构解耦。即训练时利用多分支的网络结构,推断只有普通的 3 × 3 3\times 3 3×3和relu激活组成的网络。

一、重参的原理

重参的原理就是通过代数的方式将多分支合并为一个分支。

更具体的,我们可以将 1 × 1 1\times 1 1×1的卷积看成是 3 × 3 3\times 3 3×3大小卷积的特例,identity和BN分支可以看成是 1 × 1 1\times 1 1×1卷积的特例。这句话可以用下图表示:

上图A是将重参前的结构演变为 3 × 3 3\times 3 3×3卷积的流程图,流程分为如下几步:

  1. 3 × 3 3\times 3 3×3的卷积和bn层合并成 3 × 3 3\times 3 3×3卷积

  2. 1 × 1 1\times 1 1×1的卷积转换为 3 × 3 3\times 3 3×3的卷积,然后与bn合并成 3 × 3 3\times 3 3×3的卷积

  3. 将BN转换为 3 × 3 3\times 3 3×3的卷积

  4. 将转换后的三个 3 × 3 3\times 3 3×3的并联的卷积合并为最终的 3 × 3 3\times 3 3×3的卷积

这里在合并前就是训练态的结构,合并后就是推断态的网络结构。

上图B是具体的参数转换流程,为了方便理解这里加以说明一下。上图假设当前网络块的输入 C 1 C_1 C1和输出通道 C 2 C_2 C2都为2。图中对于一个卷积来说,水平方向为输入的通道数,竖直方向为输出通道数。

  1. 对于 1 × 1 1\times 1 1×1的卷积来说,将其转换为 3 × 3 3\times 3 3×3的卷积,就是将 1 × 1 1\times 1 1×1的卷积核进行周围补0,补成 3 × 3 3\times 3 3×3的大小即可

  2. 对于BN层或者shortcut结构来说,将其转换为 3 × 3 3\times 3 3×3的卷积,就是对应通道数除当前输出通道的中心为对应的值,其它值都为0。例如identity结构,当前中心值为1,其它值都为0,这样与输入相乘后,仍然为输入的值。

具体用公式表示如下(对公式不感兴趣的可以不看,上图已经很清晰了,这里是想说明代数方式如何将网络进行化简合并的):

先定义一些符号, 3 × 3 3\times 3 3×3大小输入通道为 C 1 C_1 C1输出通道为 C 2 C_2 C2的卷积参数表示为 W ( 3 ) ∈ R C 2 × C 1 × 3 × 3 W^{(3)}\in R^{C_2 \times C_1 \times 3\times 3} W(3)RC2×C1×3×3,对应输入输出通道数的 1 × 1 1\times 1 1×1卷积参数表示为 W ( 1 ) ∈ R C 2 × C 1 W^{(1)}\in R^{C_2 \times C_1} W(1)RC2×C1。跟在 3 × 3 3\times 3 3×3大小卷积后的BN层参数为 μ ( 3 ) , θ ( 3 ) , γ ( 3 ) , β ( 3 ) \mu^{(3)}, \theta^{(3)}, \gamma^{(3)}, \beta^{(3)} μ(3),θ(3),γ(3),β(3),跟在 1 × 1 1\times 1 1×1大小卷积后的BN层参数为 μ ( 1 ) , θ ( 1 ) , γ ( 1 ) , β ( 1 ) \mu^{(1)}, \theta^{(1)}, \gamma^{(1)}, \beta^{(1)} μ(1),θ(1),γ(1),β(1),identity分支中的BN层参数为 μ ( 0 ) , θ ( 0 ) , γ ( 0 ) , β ( 0 ) \mu^{(0)}, \theta^{(0)}, \gamma^{(0)}, \beta^{(0)} μ(0),θ(0),γ(0),β(0)。这里假设 C 1 = C 2 , H 1 = H 2 , W 1 = W 2 C_1=C_2, H_1=H_2, W_1=W_2 C1=C2,H1=H2,W1=W2,符号 ∗ * 表示卷积。那么对于输入 M ( 1 ) ∈ R N × C 1 × H 1 × W 1 M^{(1)}\in R^{N \times C_{1} \times H_{1} \times W_1} M(1)RN×C1×H1×W1和输出 M ( 2 ) ∈ R N × C 2 × H 2 × W 2 M^{(2)}\in R^{N\times C_2 \times H_2 \times W_2} M(2)RN×C2×H2×W2存在如下关系:

M ( 2 ) = b n ( M ( 1 ) ∗ W ( 3 ) , μ ( 3 ) , θ ( 3 ) , γ ( 3 ) , β ( 3 ) ) + b n ( M ( 1 ) ∗ W ( 1 ) , μ ( 1 ) , θ ( 1 ) , γ ( 1 ) , β ( 1 ) ) + b n ( M ( 1 ) , μ ( 0 ) , θ ( 0 ) , γ ( 0 ) , β ( 0 ) ) M^{(2)}=bn(M^{(1)} * W^{(3)}, \mu^{(3)}, \theta^{(3)}, \gamma^{(3)}, \beta^{(3)}) \\ +bn(M^{(1)} * W^{(1)}, \mu^{(1)}, \theta^{(1)}, \gamma^{(1)}, \beta^{(1)}) \\ + bn(M^{(1)}, \mu^{(0)}, \theta^{(0)}, \gamma^{(0)}, \beta^{(0)}) M(2)=bn(M(1)W(3),μ(3),θ(3),γ(3),β(3))+bn(M(1)W(1),μ(1),θ(1),γ(1),β(1))+bn(M(1),μ(0),θ(0),γ(0),β(0))

其中推断态的BN可以写成下式:
b n ( M , μ , θ , γ , β ) : , i , : , : = ( M : , i , : , : − μ i ) θ i γ i + β i bn(M, \mu, \theta, \gamma, \beta)_{:, i, :, :}=(M_{:, i, :, :}-\mu_i)\frac{\theta_i}{\gamma_i}+\beta_i bn(M,μ,θ,γ,β):,i,:,:=(M:,i,:,:μi)γiθi+βi

上式中体现了bn的操作索引是在C维度进行的,详细可参考GN-Group Normalization

上式可以化简为:

b n ( M ∗ W , μ , θ , γ , β ) ∗ : , i , : , : = ( M ∗ W ′ ) ∗ : , i , : , : + b ‘ i bn(M* W, \mu, \theta, \gamma, \beta)*{:, i, :, :}=(M* W')*{:, i, :, :}+b‘_{i} bn(MW,μ,θ,γ,β):,i,:,:=(MW):,i,:,:+bi

其中 W ′ ∗ i , : , : , : = θ i γ i W ∗ i , : , : , : W'*{i, :, :, :}=\frac{\theta_i}{\gamma_i}W*{i, :, :, :} Wi,:,:,:=γiθiWi,:,:,:, b i ′ = − μ i γ i θ i + β i b'_i=-\frac{\mu_i \gamma_i}{\theta_i}+\beta_i bi=θiμiγi+βi

到这里重参的原理基本就介绍完了,具体实验请查看原文。

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

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

相关文章

学大数据需要java学到什么程度

大数据需求越来越多,只有技术在手不愁找不到工作。 学习大数据需要掌握什么语言基础? 1、Java基础 大数据框架90%以上都是使用Java开发语言,所以如果要学习大数据技术,首先要掌握Java基础语法以及JavaEE方向的相关知识。 2、My…

记一次OJ在线代码编辑器(代码编译+运行,C、C++、Java)

如何在SpringBootVue的项目中实现在线代码编译及执行(支持编译运行C、C、Java),研究了一天,真实能用,下面直接上源码!!! ————————————————————————————…

MySQL 知识:迁移数据目录到其他路径

一、系统环境 操作系统:Centos 7 已安装环境:MySQL 8.0.26 二、开始操作 2.1 关闭SELinux 为了提高 Linux 系统的安全性,在 Linux 上通常会使用 SELinux 或 AppArmor 实现强制访问控制(Mandatory Access Control MAC&#xff…

中间件的概念

中间件(middleware)是基础软件的一大类,属于可复用的软件范畴。中间件在操作系统软件,网络和数据库之上,应用软件之下,总的作用是为处于自己上层的应用软件提供运行于开发的环境,帮助用户灵活、高效的开发和集成复杂的…

阶段二38_面向对象高级_网络编程[UDP单播组播广播代码实现]

知识: InetAddresss:getByName,getHostName,getHostAddress方法UDP通信程序:单播,组播,广播代码实现一.InetAddress 的使用 1.static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称&#x…

【Java】通过反射方法不改变HashCode以修改String的值

如何修改String的值? 我们首先会想到如下两种方法 方式一:通过StringBuild/StringBuffer String s1 "Hello World!"; System.out.println("s1"s1" HashCode"s1.hashCode()); StringBuilder sb new StringBuilder(s1…

Android JNI配置CMakeLists.txt修改.cpp在logcat打印日志

Android JNI配置CMakeLists.txt修改.cpp在logcat打印日志 C/C代码里面常用的printf没法在Android 的logcat输出显示。需要特别配置C才能显示在logcat里面。 (1)CMakeLists.txt定义: find_library( # Sets the name of the path variable.l…

yolov1原理

目标检测方法 传统的方法可以按照检测系统分为两种: DPM,Deformatable Parts Models,采用sliding window检测R-CNN、Fast R-CNN。采用region proposal的方法,生成一些可能包含待检测物体的potential bounding box,再…

opencv_c++学习(三)

一、获取图像像素指针 CV Assert(mylmage.depth() CV 8U); CV_Assert()函数判断图像数据的类型是否为uchar类型,不满足则抛出异常。 Mat.ptr(int i0)获取像素矩阵的指针,索引i表示第几行,从0开始计行数。 Mat.ptr(int i0)获取像素矩阵的指针…

【五一创作】【远程工具】- Tabby 下载、安装、使用、配置【ssh/Serial】-免安装、解压即用

目录 一、Tabby 概述 二、Tabby 下载、安装 三、Tabby 的使用  👉3.1 使用SSH协议连接Linux开发主机  👉3.2 使用Serial(串口)协议连接开发板 一、Tabby 概述 在远程终端工具中,secureCrt 和 XShell 是两款比较有名的远程工具,但…

shell脚本之例题详解

文章目录 1 检查用户家目录中的test.sh文件是否存在,并且检查是否有执行权限2 提示用户输入100米赛跑的秒数,要求判断秒数大于0且小于等于10秒的进入选拔赛,大于10秒的都淘汰,如果输入其它字符则提示重新输入;进入选拔…

Selenium:集成测试报告

目录 一、分拆后的实现代码 二、创建用于执行所有用例的ALL_HTMLtest.py文件 三、集成测试报告 随着软件不断迭代功能越来越多,对应的测试用例也会呈指数增长。一个实现几十个功能的项目,对应的用例可能有上百个甚至更多,如果全部集成在一…

RocketMQ中单消费者订阅多个Topic,会阻塞消费吗?

RocketMQ 问题 背景是这样: 最近有个项目用MQ做消息流转,在RocketMQ集群模式下,一个消费者实例,订阅了两个Topic A、B。 Topic A:存储的是批量业务消息。 Topic B:存储的是单个业务消息。 有个小伙伴问我…

基于C++的职工管理系统

1、管理系统需求 职工管理系统可以用来管理公司内所有员工的信息 本教程主要利用C++来实现一个基于多态的职工管理系统 公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责 普通员工职责:完成经理交给的任务 经理职责:完成…

分布式系统概念和设计-分布式文件系统服务体系结构和实践经验

分布式系统概念和设计 文件系统的特点 负责文件的组织,存储,检索,命名,共享和保护 文件包含数据和属性 数据:包含一系列数据项——8比特的字节,读写操作可访问任何一部分数据属性:用一个记录表…

一文详解 SCTP 协议

SCTP(Stream Control Transmission Protocol)流控制传输协议,由 RFC2960 定义。SCTP的设计目的是提供一种可靠的、面向消息的数据传输服务,以便于支持多点通信以及满足传输的可靠性需求。SCTP 目前广泛应用于VoIP、移动通信和云计算等领域。 SCTP 主要特点SCTP 消息结构SCTP …

Android9.0 原生系统SystemUI下拉状态栏和通知栏视图之锁屏通知布局

1.前言 在9.0的系统rom定制化开发中,对于系统原生systemui的锁屏界面的功能也是非常重要的,所以在锁屏页面布局中,也是有通知栏布局的,所以接下来对于息屏亮屏 通知栏布局的相关流程分析,看下亮屏后锁屏页面做了哪些功能 2.原生系统SystemUI下拉状态栏和通知栏视图之锁…

应用层开发想转Android framework开发要从何开始

前言 现如今,由于市面上应用App的更新逐渐变少,很多Android移动应用开发者都开始转型做系统开发,这比开发应用有趣多了,因为你可以探索系统模块的运行原理,从框架层面去了解它。 在应用层,你只需要配置好…

JAVA-异常

文章目录 1.异常的体系1.3异常的分类 2.异常的处理2.2异常的抛出throw2.3异常的捕获2.3.1异常声明throws2.3.2 try-catch捕获并处理2.3.3 finally 2.4 异常的处理流程 3.自定义异常类 1.异常的体系 Throwable:是异常体系的顶层类,其派生出两个重要的子类…

前端框架篇学习--选择命令式还是声明式

命令式与声明式定义 大白话:假期回家了,我想吃老妈的大盘鸡,然后老妈就去采购食材,剁鸡块,卤鸡肉,切土豆,然后爆炒起来,想方设法给我做好吃的大盘鸡。老妈上菜的餐桌,我…