VoVNet(CVPR workshop 2019)原理与代码解析

news2024/11/16 18:08:53

paper:An Energy and GPU-Computation Efficient Backbone Network for Real-Time Object Detection

third-party implementation:https://github.com/huggingface/pytorch-image-models/blob/main/timm/models/vovnet.py 

存在的问题

DenseNet通过密集连接保留不同感受野的中间特征,在目标检测任务中表现出了良好的性能。虽然特征重用使DenseNet能够通过少量的模型参数和FLOPs产生强大的特征,但用DenseNet骨干网络的检测模型的速度很慢能效也很低。作者发现通过密集连接而线性增加的输入通道,导致了沉重的内存访问成本,从而导致了计算开销和更多的能耗。

本文的创新点

为了解决DenseNet的低效问题,本文提出了一种高效的架构VoVNet,由One-Shot Aggregation(OSA)组成。OSA不仅保留了DenseNet的优势即具有多种感受野的多样性特征,同时通过在最后一个特征图只聚合所有特征一次克服了密集连接的低效问题。基于VoVNet的检测模型与基于DenseNet的检测模型相比,速度快了2x,能耗减少了1.6x - 4.1x。同时与在速度和能耗方面还优于广泛使用的ResNet骨干网络的检测模型。特别是,小目标的检测性能比DenseNet和ResNet得到了显著提升。

方法介绍

Factors of Efficient Network Design

作者首先分析高效网络设计的一些影响因素。当设计高效网络时,许多研究例如MobileNet v1、MobileNet v2、ShuffleNet v1、ShuffleNet v2、Pelee主要关注于使用深度卷积和1x1卷积的bottleneck结构来减少FLOPs和模型大小。但减小FLOPs和模型尺寸并不总是意味着GPU推理时间和能耗的减少。ShuffleNet v2通过实验表明在GPU上比具有相似数量FLOPs的MobileNet v2运行速度更快。《Understanding the limitations of existing energy-efficient design approaches for deep neural networks》这篇文章中指出尽管SqueezeNet的权重数量比AlexNet少50x,但能耗更高。这些现象表明FLOPs和模型尺寸是衡量实用性的间接度量指标,应该重新考虑基于这些指标设计网络。为了构建更高效的网络结构,专注于更实际和更有效的指标,如energy per image和frame per second(FPS),除了FLOPs和模型参数,考虑其它影响能耗和时间消耗的因素非常重要。

Memory Access Cost

第一个因素是内存访问成本memory access cost(MAC)。CNN的主要能耗来源是内存访问而不是计算。具体来说,从DRAM(Dynamic Random Access Memory)访问数据的能耗比计算本文高几个数量级。此外,内存访问的时间占能耗的一大部分甚至可能成为GPU进程的瓶颈。这意味着,即使在相同的计算量和参数量下,不同模型架构的总内存访问次数不同,能耗也会不同。

导致模型尺寸和内存访问数量之间差异的一个原因是中间激活内存占用intermediate activation memory footprint。《Eyeriss: A spatial architecture for energy-efficient dataflow for convolutional neural networks》中指出,内存占用取决于filter参数和中间特征图。如果中间特征图很大,即使模型参数相同内存访问成本也会增加。所以,作者将MAC作为网络设计的一个重要因素。计算卷积层MAC如下

\(k,h,w,c_i,c_o\) 分别表示卷积核大小、输入和输出的高和宽、输入和输出的通道数。

GPU-Computation Efficiency

通过减少FLOPs来提高速度的网络结构是基于每个浮点操作在设备中以相同的速度处理的思想。但当网络部署在GPU上时这种想法是错误的。这是因为GPU的并行处理机制,由于GPU能够同时处理多个浮点操作进程,因此高效的利用其计算能力是非常重要的。我们使用术语GPU-computation efficiency来描述这个概念。 

计算的张量越大,GPU的并行计算能力就能更好的被利用。将一个大的卷积操作切分成几个较小的碎片操作是的GPU的计算效率低下,因为更少的计算时并行处理的。这意味着在网络设计中如果behavior function相同,最好用较少的层来构建网络。此外,额外的会带来内核启动和同步kernel launching and synchronization从而导致额外的时间开销。

因此,虽然深度卷积和1x1 convolution bottleneck可以减少FLOPs,但因为采用了额外的1x1卷积对GPU的计算效率是有害的。GPU的计算效率随着模型架构的不同而变化,因为为了验证网络架构的计算效率,作者引入了FLOPs per Second(FLOP/s),它是用总的FLOPs除以实际的GPU推理时间。高的FLOP/s意味着可以更高效的利用GPU。

Proposed Method

Rethinking Dense Connection

聚合所有中间层的密集连接不可避免的会导致低效率,这是因为每一层的输入通道大小随着网络层的逐渐变深而线性增加。由于密集聚合,dense block在FLOPs或参数限制下只能生成少量的特征。换句话说,DenseNet通过密集连接,用特征的数量换特征的质量。尽管从表现来看这种交换是有益的,但从能源和时间的角度看还有一些其它缺点。

首先密集连接会导致较高的内存访问成本。一个卷积层内存访问操作数的下限可以表示为 \(MAC\ge 2\sqrt{\frac{hwB}{k^2} }+\frac{B}{hw}  \) 当 \(B=k^2hwc_ic_o\) 是计算量。因为下限基于均值不等式,在固定的计算量或模型参数下,当输入和输出通道相等时MAC最小。密集连接增加了输入通道,而输出通道保持不变,因此每一层的输入和输出通道都不平衡,因此在相同计算量或参数的模型中DenseNet的MAC较高并消耗更多的能源和时间。

其次,密集连接采用了bottleneck结构,降低了GPU并行计算的效率。当模型比较大时,线性增加的输入大小是很严重的问题,因为它使整体的计算量相对深度呈二次方增长的关系。为了抑制这种增长,DenseNet采用了bottleneck结构,增加了一个1x1卷积来保持3x3卷积输入大小不变。尽管这样可以减少FLOPs和参数,但损害了GPU并行计算的效率。Bottleneck结构将一个3x3卷积分解成两个更小的层,带来了更多的sequential计算,降低了推理速度。

由于这些缺点,DenseNet在能源和时间方面变得低效。为了提高效率,作者首先研究了网络训练完后密集连接时如何聚合特征的。具体通过计算每一层输入权重的归一化L1范数来说明密集连接的连通性。这些值表明了前一层对相应层的标准化影响。如图2(top)所示

在Dense block3中,对角线附近的红框说明中间层上的聚合是活跃的。但是在分类层,只使用了一小部分的中间特征。相反在Dense block1中,transition layer很好地聚合了其大部分输入特征,而中间层则不能。

根据观察结果,作者假设中间层的聚合强度与最终层的聚合强度呈负相关,如果中间层的密集连接导致来自每一层的特征之间有相关性这种假设就是正确的。这意味着密集连接使靠后的中间层产生更好的特征,但与来自前面层的特征比较相似。在这种情况下,最后一层不需要学习聚合这两个特性,因为它们表示冗余的信息。因此靠前的中间层对最后一层的影响变小。

由于所有的中间层都被聚合来得到最后一层的特征。因此中间层的特征之间最好是互补的或相关性较小的。因此我们拓展我们的假设,即中间层的密集连接相对成本的影响较小。为了验证这个假设,我们设计了一个新的模块,它只在每个block的最后一层聚合中间特征。

One-Shot Aggregation

OSA模块如图1(b)所示,每个卷积层通过双向连接。一个是连接到后续层来得到更大感受野的特征,另一个是只在最后一层聚合一次。和DenseNet的区别在于每一层的输出没有被concat到后续所有层,从而使中间层的输入大小不变。 

为了验证我们的假设,即中间层的聚集强度与最终层的聚集强度呈负相关,并且密集连接是冗余的,作者在OSA模块上进行了实验。作者设计了和DenseNet-40中密集连接相似参数和计算量的OSA模块。首先研究了OSA module和dense block层数相同的情况(12层)如图2(middle)所示,由于每个卷积层的输入变小了,输出比dense block更大。可以看到,由于中间层上的聚合被去掉,最终层上的聚合的强度更大了。

此外,OSA过渡层的权重和DenseNet的形式不同:浅层特征更多的聚合在过渡层。由于深层特征对过渡层的影响不大,我们可以减少层数又不带来很大的影响。所以作者将OSA重新配置为5层每层43个通道如图2(bottom)所示。令人惊讶的是,使用这个模块我们得到了5.44%的error rate,和DenseNet-40(5.24%)相似。这表明通过密集连接得到的中间特征的效果并没有预期的好。

尽管带有OSA模块的网络在CIFAR-10上的性能略有下降,这并不意味着它在检测任务上的表现就不好。它比dense block的MAC要少的多,根据式(1),用5层43通道的OSA模块替换DenseNet-40中的dense block,MAC将从3.7M减少到2.5M。这是因为OSA中间层具有相同大小的输入和输出,从而使MAC的值到lower boundary。这意味着如果MAC是能源和时间消耗的主要因素,我们可以构建更快更节能的网络。具体来说,由于检测要求比分类更高的分辨率,中间层的内存占用将变得更大,MAC将能更适当的反映能源和时间的消耗。

此外,OSA还提高了GPU的计算效率。OSA模块的中间层的输入大小是常量,因此就不需要额外的1x1卷积来降维。而且由于OSA聚合了浅层特征,需要的层数也更少。

Configuration of VoVNet

由于OSA模块的多样化特征表示和高效,我们可以通过叠加少量模块来构建精度高、速度快的VoVNet。基于图2中浅层特征更多被聚合的事实,我们可以用比DenseNet数量更少通道数更多的卷积来构建OSA module。作者设计了两种VoVNet:轻量的VoVNet-27-slim,以及大尺寸的VoVNet-39/57。VoVNet包含一个stem block其中有3层卷积,以及4个stage的OSA module最终输出stride=32。一个OSA module包含5个卷积层。跨stage时特征图通过stride=2的3x3 max pooling降采样。VoVNet-39/57在第4、5阶段有更多的OSA模块,降采样在最后一个模块中进行。 

由于高层的语义信息在目标检测任务中非常重要,我们逐渐增加高层特征的比例,即逐渐增加特征的通道数。VoVNet的具体结构如表1所示

代码解析

这里以timm中的实现为例,VoVNet有多个stage构成,每个stage又包含多个osa block,一个osa block又包含多个卷积层,vovnet-39a的结构参数如下 

vovnet39a=dict(
        stem_chs=[64, 64, 128],
        stage_conv_chs=[128, 160, 192, 224],
        stage_out_chs=[256, 512, 768, 1024],
        layer_per_block=5,
        block_per_stage=[1, 1, 2, 2],
        residual=False,
        depthwise=False,
        attn='',
    )
ese_vovnet39b=dict(
    stem_chs=[64, 64, 128],
    stage_conv_chs=[128, 160, 192, 224],
    stage_out_chs=[256, 512, 768, 1024],
    layer_per_block=5,
    block_per_stage=[1, 1, 2, 2],
    residual=True,
    depthwise=False,
    attn='ese',
),

'a'和'b'的区别在于每个osa block是否有像ResNet一样的shortcut,即residual=True,以及是否添加注意力模块。

一个完整的osa block如图1(b)所示,代码如下

class OsaBlock(nn.Module):

    def __init__(
            self, in_chs, mid_chs, out_chs, layer_per_block, residual=False,
            depthwise=False, attn='', norm_layer=BatchNormAct2d, act_layer=nn.ReLU, drop_path=None):
        super(OsaBlock, self).__init__()

        self.residual = residual
        self.depthwise = depthwise
        conv_kwargs = dict(norm_layer=norm_layer, act_layer=act_layer)

        next_in_chs = in_chs
        if self.depthwise and next_in_chs != mid_chs:
            assert not residual
            self.conv_reduction = ConvNormAct(next_in_chs, mid_chs, 1, **conv_kwargs)
        else:
            self.conv_reduction = None

        mid_convs = []
        for i in range(layer_per_block):
            if self.depthwise:
                conv = SeparableConvNormAct(mid_chs, mid_chs, **conv_kwargs)
            else:
                conv = ConvNormAct(next_in_chs, mid_chs, 3, **conv_kwargs)
            next_in_chs = mid_chs
            mid_convs.append(conv)
        self.conv_mid = SequentialAppendList(*mid_convs)

        # feature aggregation
        next_in_chs = in_chs + layer_per_block * mid_chs
        self.conv_concat = ConvNormAct(next_in_chs, out_chs, **conv_kwargs)

        self.attn = create_attn(attn, out_chs) if attn else None

        self.drop_path = drop_path

    def forward(self, x):
        output = [x]
        if self.conv_reduction is not None:
            x = self.conv_reduction(x)
        x = self.conv_mid(x, output)
        x = self.conv_concat(x)
        if self.attn is not None:
            x = self.attn(x)
        if self.drop_path is not None:
            x = self.drop_path(x)
        if self.residual:
            x = x + output[0]
        return x

其中主要实现在self.conv_mid,SequentialAppendList实现如下,可以看到将每一层的输出都保存在concat_list里,最后一层将所有层的输出concat起来。在上面的self.conv_concat用1x1卷积进行降维。

class SequentialAppendList(nn.Sequential):
    def __init__(self, *args):
        super(SequentialAppendList, self).__init__(*args)

    def forward(self, x: torch.Tensor, concat_list: List[torch.Tensor]) -> torch.Tensor:
        for i, module in enumerate(self):
            if i == 0:
                concat_list.append(module(x))
            else:
                concat_list.append(module(concat_list[-1]))
        x = torch.cat(concat_list, dim=1)
        return x

实验结果

用VoVNet-27-slim替换检测模型DSOD原本的backbone DenseNet-67,并与其它两个轻量检测模型的对别如下 

计算和能源效率的对比如下

 

可以看到,VoVNet-27-slim的DSOD不仅取得了最高的mAP,同时在计算、能耗、速度方面都是最优的。

作者又比较了大型VoVNet的效果,检测模型用当时SOTA的RefineDet,backbone分别用VoVNet-39和VoVNet-57,在COCO上的精度对比如下

速度、能耗对比如下

 

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

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

相关文章

泰山派学习笔记(二)一步一步编译SDK文件

上一节,我们安装了基于虚拟机的ubuntu系统,并且建立了samba服务打通了win10和ubuntu系统中的文件传输。本节课我们继续对立创官方提供的SDK文件进行编译,学习编译的方法。引用官方的话:如果只想下载别人编译好的固件并且做一些应用…

Linux系统运维:离线安装sar-性能监视和分析工具

目 录 一、前言 二、系统环境 三、安装sar (一)准备工作 1、下载 sar 工具的安装包: 2、将安装包传输到 CentOS 服务器 (二)安装工作 1、解压 2、配置安装 3、编译 4、安装 (三&#xff0…

Ubuntu环境安装MySQL数据库

1.安装过程 打开终端(Terminal)窗口,使用以下命令更新系统软件包: sudo apt update ubuntu环境安装mysql-server和mysql开发包,包括mysql头文件和动态库文件,命令如下: sudo apt-get instal…

15万-20万选纯电车,真劝你不要买合资和新势力

文 | AUTO芯球 作者 | 雷歌 我是怕了, 在后台,不断有朋友要我推荐20万以下/15万以内的纯电车。 比如这位,真心“求”我推荐一下15万以内的车,然后顺带骂我一通“就知道黑”。 好家伙,一边求人办事,一边…

Freertos实时操作系统---基于STM32

一、Freertos简介 1.Freertos介绍 1)RTOS指的是一类的实时操作系统 2)rtos的使用:用户根据对任务来设置其优先级然后来使用调度器来决定哪一个任务来先执行。 3)Freertos的文件数量远低于其他操作系统 4)主要特点&…

力扣经典题目解析--两数之和

两数之和 题目地址: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 简单来说就是在一个数组中找出两个数,这两个数相加要等于给定的target,下面是完整的题目: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中…

按照指定的分隔符对字符串进行分割 numpy.char.partition()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 按照指定的分隔符 对字符串进行分割 numpy.char.partition() [太阳]选择题 请问关于以下代码表述正确的是? import numpy as np a np.array([12_3, 4_5_6]) print(&quo…

一次有趣的nginx Tcp4层代理转发的试验

nginx主配置文件添加配置: stream {log_format proxy $remote_addr [$time_local] $protocol status:$status bytes_sent:$bytes_sent bytes_received:$bytes_received $session_time upstream_addr:"$upstream_addr" "$upstream_bytes_sent" …

Java里常用的集合哪些是线程安全的和不安全的

最近在做一个业务的时候,需要考虑线程的安全性,然后选用集合的时候专门去整理了一下。 线程安全的是: Hashtable,ConcurrentHashMap,Vector ,CopyOnWriteArrayList ,CopyOnWriteArraySet 线程不安全的是: H…

非常实用的利用SAM分割一切大模型,进行抠图。

目录 SAM简介 实现方法 SAM简介 引言: 介绍人工智能(AI)的发展趋势,特别是在图像分割领域。强调基础模型在AI发展中的作用,以及Meta AI开发的SAM模型如何定义这个新的里程碑。 SAM的介绍: 背景&#x…

【论文精读】OS-Copilot: Towards Generalist Computer Agents with Self-Improvement

OS-Copilot: Towards Generalist Computer Agents with Self-Improvement 前言ABSTRACT1 INTRODUCTION2 THE OS-COPILOT FRAMEWORK2.1 PLANNER2.2 CONFIGURATOR2.2.1 DECLARATIVE MEMORY2.2.2 PROCEDURAL MEMORY2.2.3 WORKING MEMORY 2.3 ACTOR 3 THE FRIDAY AGENT3.1 A RUNNIN…

VS中使用xcopy生成后命令报9009错误

错误现象: download下来的代码,在另一台电脑能使用生成后命令xcopy,换一台电脑后该命令不能使用,报如下错误: 2.错误原因: 这是因为xcopy /Y 为Windows程序命令,xcopy其实是Windows下的一个xcopy.exe,如果…

【Spring】声明式事务 spring-tx

文章目录 声明式事务是什么?一、Spring事务管理器二、基于注解的声明式事务1.1 准备工作1.2 基本事务控制1.3 事务属性:只读1.4 事务属性:超时时间1.5 事务属性:事务异常1.6 事务属性:事务隔离级别1.7 事务属性&#x…

redis架构系列——生产常用的部署模式介绍

主从高可用模式 这是最基本的高可用模式,它允许数据从主节点自动复制到一个或多个从节点。这种模式下,从节点可以处理读操作,从而实现负载均衡,并提供故障恢复的基本功能。然而,它的故障恢复不能自动化,写操…

Java核心-核心类与API(2)

话接上回,继续核心类与API的学习,这次介绍StringBuffer/StringBuilder/StringJoiner类。StringBuffer和StringBuilder是我们学习的重点,建议对比学习,做好区分。 一、StringBuffer类 1、概述 1)问题 由于 String 类…

每日OJ题_牛客OR59_字符串中找出连续最长的数字串

目录 牛客OR59 字符串中找出连续最长的数字串 解析代码 牛客OR59 字符串中找出连续最长的数字串 字符串中找出连续最长的数字串_牛客题霸_牛客网 解析代码 #include <iostream> #include <cctype> using namespace std; int main() {string str, tmp "&q…

Stable Diffusion 3 震撼发布,采用Sora同源技术,文字终于不乱码了

Stable Diffusion 3 和 Sora 一样采用了 diffusion transformer 架构。 继 OpenAI 的 Sora 连续一周霸屏后&#xff0c;昨晚&#xff0c;生成式 AI 顶级技术公司 Stability AI 也放了一个大招 ——Stable Diffusion 3。该公司表示&#xff0c;这是他们最强大的文生图模型。 与…

Uniapp-小程序简单的时间选择组件-年月日时分

文章目录 前言一、组件效果二、组件代码使用 总结 前言 uniapp小程序开发系列。本文实现一个简单时间选择控件。uniapp用个心仪时间控件真的麻烦。官方给得要么年月日&#xff0c;要么时分。产品只要年月日时分。这该怎么玩。旧项目没有引入ui框架&#xff0c;我也不想去引入&…

调查居民幸福指数的社会实践报告

引言 在快速发展的现代社会中&#xff0c;居民的幸福感成为了衡量一个社区、一个城市乃至一个国家综合实力的重要指标之一。幸福指数不仅反映了居民的生活质量和满意度&#xff0c;也是政府制定和调整政策&#xff0c;提升民众生活水平的重要依据。因此&#xff0c;本次社会实践…

【Python_Zebra斑马打印机编程学习笔记(二)】基于BarTender将btw文件转换为zpl文件

基于BarTender将btw文件转换为zpl文件 基于BarTender将btw文件转换为zpl文件前言一、BarTender1、BarTender 介绍2、BarTender 安装 二、导出 ZPL 文件1、导出 ZPL 文件步骤2、Zebra 打印机驱动安装 基于BarTender将btw文件转换为zpl文件 前言 本文介绍如何基于 BarTender 软…