GCNet

GCNet 论文详解

GCNet:Non-local Networks Meet Squeeze-Excitation Networks and Beyond,cvpr,2019.

链接:paper

代码:github

摘要

背景:Non-local Network 提供了一种捕获远程依赖关系的开创性方法,通过将特定于查询的全局上下文聚合得到每个查询位置。但是,本文发现,对于图中不同的查询位置,non-local network 网络建模的上下文信息几乎是相同的。

贡献:基于上述问题,文中建立了一个简化的基于查询无关的网络(snl),保持了NLNet的精度,大大减少了计算量。设计了一个轻量级GC block模块,和snet 都属于一种“三步骤”通用框架:1、全局上下文建模;2、channel-wise 依赖关系转换;3、特征融合。可以有效的建模全局上下文。可以将其应用于主干网络的多层中。

引言

​ 无论是non-local还是本文所提出的gcnet都属于"long-range dependency “。它们的目的都是尽可能从"global"的角度来理解图像。使用传统的卷积效率低,且很难达到这一点,因为一个卷积操作是对一个“local neighborhood "的pixel 关系进行建模。虽然可以通过不断的加深网络,来达到网络后半部分的神经元的感受野变大,达到一种不太”local“的效果,但这种粗暴的加深网络的做法:有三个缺点:(1)不够精巧,参数量计、算量大;(2)网络越深,优化难度越大;(3)不太”local"并不代表全局,有最大距离的限制。

对上面第三点的理解可以为:在网络的后半部分,feature map右下角的cell,感受野可能扩大了,但可能还是始终无法获得原图片上左上角的信息(因为卷积操作最大距离的限制)。与之对应的,一个理想的神经网络应该是:不要那么深,让用户优化的太困难;网络涉及的精巧一点,最好较少的参数量达到原始网络结构的性能;真正的做到全局,没有最大距离的限制。

为了解决这个问题,我们提出了non-local network,通过自我注意机制来建模远程依赖关系。对于每一个query position,计算该query position与图中其他点之间的关系来提取该点的特征。

然而,作者对non-local 的attention map进行可视化后发现不同的query point 对应的attention map 几乎是一样的。如下图所示:

img

基于此,文中提出了简化版的NL(SNL)。该简化模块的计算量明显少于NL。其准确率几乎没有下降。此外,我们发现这个简化块与SENet 网络具有相似的结构。它们都是通过从各个位置聚合的相同特征来强化原有特征,但在聚合策略、转化和强化功能上的选择又相互区别。通过对这些函数的抽象,我们得到了统一简化的NL块和SE块的三步通用框架:(a)上下文建模模块,它将所有位置的特征聚合在一起,形成全局上下文特征;(b)特征转换模块,以捕获渠道间的相互依赖;和©融合模块,将全局上下文特征合并为所有位置特征。简化的NL块和SE块是这个通用框架的两个实例。文中还提出了GC 模块,在上下文建模(使用全局注意力池)和融合(使用添加)步骤上,GC 模块与简化的NL块共享相同的实现,而与SE块共享相同的转换步骤(使用两层瓶颈)。GC块在多个视觉识别任务中的表现优于简化的NL块和SE块。

Method

1、Simplifying the Non-local Block

​ 既然attention map 与具体的点的位置无关,那就不要每一个点单独算一个attention map.用另外一种能过获取全局信息,但一个feature map 上的点可以共用attention 。基于此,我们简化了NL模块,提出了SNL模块,结构如下图(b):

img

Non-local 定义公式:

img

SNL定义公式:

img

一个直观的感觉是block结构确实简化了。在实际运算的变化中,可以看公式,公式中关键部分在于+号后面的变化。Non-local+号后面的内容与xi有关,因此每一个点i,需要计算一次。而snl的表达公式+号后面的内容已与xi无关,也即计算一次,然后大家公用,也映证了上文所讲的query-independent。

2、global context block

GCNet在上下文信息建模这个地方使用了Simplified NL block中的机制,可以充分利用全局上下文信息,同时在Transform阶段借鉴了SE block。

img

实验

Ablation

  • a. 看出Simplified NL与NL几乎一直,但是参数量要小一些。且每个阶段都使用GC block性能更好。
  • b. 在residual block中GC添加在add操作之后效果最好。
  • c. 添加在residual 的所有阶段效果最优,能比baseline高1-3%。
  • d. 使用简化版的NLNet并使用1×1卷积作为transform的时候效果最好,但是其计算量太大。
  • e. ratio=1/4的时候效果最好。
  • f. attention pooling+add的的组合用作池化和特征融合设计方法效果最好。

img

pytorch 代码

import torch
import torch.nn as nn
import torchvision
classs GlobalContextBlock(nn.Module):
    def __init__(slef,inplanes,ratio,pooling_type='att',fusion_types=('channel_add',)):
        super(GlobalContextBlock,self).__init__()
        assert pooling_type in ['avg', 'att']
        assert isinstance(fusion_types, (list, tuple))
        valid_fusion_types = ['channel_add', 'channel_mul']
        assert all([f in valid_fusion_types for f in fusion_types])
        assert len(fusion_types) > 0, 'at least one fusion should be used'
        self.inplanes = inplanes
        self.ratio = ratio
        self.planes = int(inplanes * ratio)
        self.pooling_type = pooling_type
        self.fusion_types = fusion_types
        if pooling_type == 'att':
            slef.conv_mask = nn.Conv2d(inplanes,1,kernel_size = 1)
            slef.softmax = nn.Softmax(dim=2)
         else:
            slef.avg_pool = self.avg_pool = nn.AdaptiveAvgPool2d(1)
          if 'channel_add' in fusion_types:
            self.channel_add_conv = nn.Sequential(
                nn.Conv2d(self.inplanes, self.planes, kernel_size=1),
                nn.LayerNorm([self.planes, 1, 1]),
                nn.ReLU(inplace=True),  # yapf: disable
                nn.Conv2d(self.planes, self.inplanes, kernel_size=1))
         else:
            self.channel_add_conv = None
         if 'channel_mul' in fusion_types:
            self.channel_mul_conv = nn.Sequential(
                nn.Conv2d(self.inplanes, self.planes, kernel_size=1),
                nn.LayerNorm([self.planes, 1, 1]),
                nn.ReLU(inplace=True),  # yapf: disable
                nn.Conv2d(self.planes, self.inplanes, kernel_size=1))
        else:
            self.channel_mul_conv = None
            
    def spatial_pool(self, x):
        batch, channel, height, width = x.size()
        if self.pooling_type == 'att':
            input_x = x
            # [N, C, H * W]
            input_x = input_x.view(batch, channel, height * width)
            # [N, 1, C, H * W]
            input_x = input_x.unsqueeze(1)
            # [N, 1, H, W]
            context_mask = self.conv_mask(x)
            # [N, 1, H * W]
            context_mask = context_mask.view(batch, 1, height * width)
            # [N, 1, H * W]
            context_mask = self.softmax(context_mask)
            # [N, 1, H * W, 1]
            context_mask = context_mask.unsqueeze(-1)
            # [N, 1, C, 1]
            context = torch.matmul(input_x, context_mask)
            # [N, C, 1, 1]
            context = context.view(batch, channel, 1, 1)
        else:
            # [N, C, 1, 1]
            context = self.avg_pool(x)

        return context

    def forward(self, x):
        # [N, C, 1, 1]
        context = self.spatial_pool(x)

        out = x
        if self.channel_mul_conv is not None:
            # [N, C, 1, 1]
            channel_mul_term = torch.sigmoid(self.channel_mul_conv(context))
            out = out * channel_mul_term
        if self.channel_add_conv is not None:
            # [N, C, 1, 1]
            channel_add_term = self.channel_add_conv(context)
            out = out + channel_add_term

        return out

### GCNet架构与实现 GCNet(Global Context Network)是一种改进的非局部网络结构,旨在更高效地捕获图像中的长距离依赖关系。通过引入全局上下文模块(Global Context Block),该模型能够在保持较低计算开销的同时显著提升性能。 #### Global Context Block的工作原理 全局上下文块的核心在于其简化了传统非局部神经网络(NLNet)的设计思路,在保留有效特征提取能力的基础上大幅降低了运算复杂度。具体来说: - **输入处理**:接收来自前一层卷积操作后的特征图作为输入。 - **降维变换**:利用1×1卷积核减少通道数至原尺寸的一半,从而降低后续计算负担[^4]。 - **空间池化**:执行全局平均池化操作以获取整个感受野内的统计信息,形成紧凑的空间描述子向量。 - **权重生成器**:基于上述得到的信息构建自适应权值矩阵W,用于调整各位置的重要性程度;此过程借鉴了SENet的思想,但作用范围扩展到了全部像素点而非仅仅限于单个channel维度上。 - **加权求和**:将原始特征映射F与由W指导下的重构版本相乘累加以获得最终输出G(F),并将其反馈给下一轮迭代使用。 这种设计使得GCBlock可以在不明显增加额外参数数量的前提下增强模型对于场景整体布局的理解力,进而改善识别效果[^3]。 ```python import torch.nn as nn class ContextBlock(nn.Module): def __init__(self, inplanes, ratio=0.25, pooling_type='att', fusion_types=('channel_add', )): super(ContextBlock, self).__init__() ... def forward(self, x): batch_size = x.size(0) pooled featrues processing... return output_feature_map ``` 以上代码片段展示了如何定义一个基本版的ContextBlock类来实现GCNet的关键组件之一——全局上下文模块[^2]。 ### SCP协议详解 SCP(Secure Copy Protocol) 是一种用于在网络环境中安全传输文件的安全复制命令行工具。它建立在SSH之上提供加密通信信道保障数据交换过程中不会被窃听篡改等问题发生。主要特点如下: - 支持远程主机间直接进行文件拷贝; - 可指定源路径及目标地址完成双向迁移任务; - 自动验证服务器身份防止中间人攻击风险; - 继承了OpenSSH项目带来的强大密钥管理功能支持多种认证方式如密码、公私钥对等。 典型应用场景包括但不限于自动化部署脚本编写、跨平台同步配置文件或是备份重要资料库等等实用场合之中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值