CV常用注意力机制总结

本文总结了近几年CV领域常用的注意力机制,包括:SE(Squeeze and Excitation)、ECA(Efficient Channel Attention)、CBAM(Convolutional Block Attention Module)、CA(Coordinate attention for efficient mobile network design)

一、SE

目的是给特征图中不同的通道赋予不同的权重,步骤如下:

  1. 对特征图进行Squeeze,该步骤是通过全局平均池化把特征图从大小为(N,C,H,W)转换为(N,C,1,1),这样就达到了全局上下文信息的融合
  2. Excitation操作,该步骤使用两个全连接层,其中第一个全连接层使用ReLU激活函数,第二个全连接层采用Sigmoid激活函数,目的是将权重中映射到(0,1)之间。值得注意的是,为了减少计算量进行降维处理,将第一个全连接的输出采用输入的1/4或者1/16
  3. 通过广播机制将权重与输入特征图相乘,得到不同权重下的特征图

代码实现如下, 

import torch
import torch.nn as nnclass Se(nn.Module):def __init__(self, in_channel, reduction=16):super(Se, self).__init__()self.pool = nn.AdaptiveAvgPool2d(output_size=1)self.fc = nn.Sequential(nn.Linear(in_features=in_channel, out_features=in_channel//reduction, bias=False),nn.ReLU(),nn.Linear(in_features=in_channel//reduction, out_features=in_channel, bias=False),nn.Sigmoid())def forward(self,x):out = self.pool(x)out = self.fc(out.view(out.size(0),-1))out = out.view(x.size(0),x.size(1),1,1)return out*x

二、ECA

可参考《注意力机制 ECA-Net 学习记录_eca注意力机制_chen_zn95的博客-CSDN博客》

ECA也是一个通道注意力机制,该算法是在SE的基础上做出了一定的改进,首先ECA作者认为SE中的全连接降维可以降低模型的复杂度,但这也破坏了通道与其权重之间的直接对应关系,先降维后升维,这样权重和通道的对应关系是间接的。为了解决以上问题,作者提出一维卷积的方法,避免了降维对数据的影响,步骤如下:

  1. 对特征图进行Squeeze,该步骤是通过全局平均池化把特征图从大小为(N,C,H,W)转换为(N,C,1,1),这样就达到了全局上下文信息的融合(与SE的步骤1相同)
  2. 计算自适应卷积核的大小,k=\left | \frac{log_{2}^{C}}{\gamma }+\frac{b}{\gamma } \right |,其中,C:输入通道数,b=1,γ=2;对经过步骤一处理的特征进行一维卷积操作(获得局部跨通道信息),再采用Sigmoid激活函数将权重映射在0到1之间
  3. 通过广播机制将权重与输入特征图相乘,得到不同权重下的特征图

代码实现如下,

import torch
import torch.nn as nn
import mathclass ECA(nn.Module):def __init__(self, in_channel, gamma=2, b=1):super(ECA, self).__init__()k = int(abs((math.log(in_channel,2)+b)/gamma))kernel_size = k if k % 2 else k+1padding = kernel_size//2self.pool = nn.AdaptiveAvgPool2d(output_size=1)self.conv = nn.Sequential(nn.Conv1d(in_channels=1, out_channels=1, kernel_size=kernel_size, padding=padding, bias=False),nn.Sigmoid())def forward(self,x):out=self.pool(x)out=out.view(x.size(0), 1, x.size(1))out=self.conv(out)out=out.view(x.size(0), x.size(1), 1, 1)return out*x

三、CBAM

CBAM是一种将通道与空间注意力机制相结合的算法,输入特征图先进行通道注意力机制再进行空间注意力机制操作,这样从通道和空间两个方面达到了强化感兴趣区域的目的

通道注意力机制的实现步骤如下:

  1. 对特征图进行Squeeze,该步骤分别采用全局平均池化和全局最大池化把特征图从大小为(N,C,H,W)转换为(N,C,1,1),这样就达到了全局上下文信息的融合
  2. 分别将全局最大池化和全局平均池化结果进行MLP操作,MLP在这里定义与SE的全连接层操作一样,为两层全连接层,中间采用ReLU激活,最后将两者相加后利用Sigmoid函数激活
  3. 通过广播机制将权重与输入特征图相乘,得到不同权重下的特征图

空间注意力机制的实现步骤如下:

  1. 将上述通道注意力操作的结果,分别在通道维度上进行最大池化和平均池化,即将经过通道注意力机制的特征图从(N,C,H,W)转换为(N,1,H,W),融合不同通道的信息,然后在通道维度上将最大池化与平均池化的结果concat起来
  2. 将叠加后2个通道的结果做卷积运算,输出通道为1,卷积核大小为7,最后将输出结果进行Sigmoid处理
  3. 通过广播机制将权重与输入特征图相乘,得到不同权重下的特征图

代码实现如下,

import torch
import torch.nn as nn
import mathclass CBAM(nn.Module):def __init__(self, in_channel, reduction=16, kernel_size=7):super(CBAM, self).__init__()# 通道注意力机制self.max_pool = nn.AdaptiveMaxPool2d(output_size=1)self.avg_pool = nn.AdaptiveAvgPool2d(output_size=1)self.mlp = nn.Sequential(nn.Linear(in_features=in_channel, out_features=in_channel//reduction, bias=False),nn.ReLU(),nn.Linear(in_features=in_channel//reduction, out_features=in_channel,bias=False))self.sigmoid = nn.Sigmoid()# 空间注意力机制self.conv = nn.Conv2d(in_channels=2, out_channels=1, kernel_size=kernel_size , stride=1, padding=kernel_size//2, bias=False)def forward(self,x):# 通道注意力机制max_out = self.max_pool(x)max_out = self.mlp(max_out.view(maxout.size(0), -1))avg_out = self.avg_pool(x)avg_out = self.mlp(avg_out.view(avgout.size(0), -1))channel_out = self.sigmoid(max_out+avg_out)channel_out = channel_out.view(x.size(0), x.size(1),1,1)channel_out = channel_out*x# 空间注意力机制max_out, _ = torch.max(channel_out, dim=1, keepdim=True)mean_out = torch.mean(channel_out, dim=1, keepdim=True)out = torch.cat((max_out, mean_out), dim=1)out = self.sigmoid(self.conv(out))out = out*channel_outreturn out

四、CA

SE对提升模型性能具有显著的有效性,但它们通常忽略了位置信息。CA利用x、y两个方向的全局池化,分别将垂直和水平方向上的输入特征聚合为两个独立的方向感知特征映射,将输入Feature Map的位置信息嵌入到通道注意力的聚合特征向量。这两个嵌入方向特定信息的特征图被分别编码到两个注意图中,然后通过乘法将这两种注意图应用于输入特征图,加强感兴趣区域的表示。实现步骤如下:

  1. 沿着x、y方向对输入特征图分别进行自适应池化操作,将特征图大小从(N,C,H,W)变为(N,C,H,1)、(N,C,1,W),对大小为(N,C,1,W)的特征进行permute操作,使得该特征大小变为(N,C,W,1),再沿着(dim=2)对这两个特征进行concat,得到大小为(N,C,H+W,1)的特征图
  2. 对步骤一处理后的特征进行1*1卷积操作(目的是降维),随后再经过BN和h_swish激活函数
  3. 沿着dim=2对步骤二处理后的特征进行分割操作(torch.split),将特征分为(N,C/r,H,1)、(N,C/r,W,1),其中r为通道降维因子。随后对大小为(N,C/r,W,1)的特征进行permute操作,变为(N,C/r,1,W)。最后对以上两个特征进行1*1卷积操作(目的是改变特征图的通道数)并经Sigmoid处理
  4. 通过广播机制将步骤三的两个特征先后与输入特征图相乘(out = identity * a_w * a_h),得到不同权重下的特征图

【下图有点小问题,应该是对1D Global Avg Pool(W)特征进行permute操作】

代码实现如下,

import torch
import torch.nn as nn
import math
import torch.nn.functional as Fclass h_sigmoid(nn.Module):def __init__(self, inplace=True):super(h_sigmoid, self).__init__()self.relu = nn.ReLU6(inplace=inplace)def forward(self, x):return self.relu(x + 3) / 6class h_swish(nn.Module):def __init__(self, inplace=True):super(h_swish, self).__init__()self.sigmoid = h_sigmoid(inplace=inplace)def forward(self, x):return x * self.sigmoid(x)class CoordAtt(nn.Module):def __init__(self, inp, oup, reduction=32):super(CoordAtt, self).__init__()self.pool_h = nn.AdaptiveAvgPool2d((None, 1))self.pool_w = nn.AdaptiveAvgPool2d((1, None))mip = max(8, inp // reduction)self.conv1 = nn.Conv2d(inp, mip, kernel_size=1, stride=1, padding=0)self.bn1 = nn.BatchNorm2d(mip)self.act = h_swish()self.conv_h = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)self.conv_w = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)def forward(self, x):identity = xn,c,h,w = x.size()x_h = self.pool_h(x)x_w = self.pool_w(x).permute(0, 1, 3, 2)y = torch.cat([x_h, x_w], dim=2)y = self.conv1(y)y = self.bn1(y)y = self.act(y) x_h, x_w = torch.split(y, [h, w], dim=2)x_w = x_w.permute(0, 1, 3, 2)a_h = self.conv_h(x_h).sigmoid()a_w = self.conv_w(x_w).sigmoid()out = identity * a_w * a_hreturn out

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS五大内存分区

我们知道任何一个程序在运行的时候实际是运行在内存中的,这个内存也就是我们通常所说的主存,也叫运行内存,也叫RAM(Random Access Memory),是可以直接与CPU进行交换数据的内部存储器。内存读取速度很快&…

天池大赛中药说明书实体识别挑战冠军方案开源(二)部署运行实战 附详细操作说明

目录 Introduction 导言环境搭建环境 Github地址项目目录说明使用步骤下载预训练模型更改部分代码模型训练参数设置BERT-CRF模型训练BERT-SPAN模型训练BERT-MRC模型训练 运行训练预测复赛 test 文件 (上述模型训练完成后) 参考资料其它资料下载 Introduc…

2023最新 Navicat 16.2.3 安装和学习试用连接Redis教程详解

🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~&#x1f33…

react-flow基础使用及dagre库的使用

前言 最近项目中需要用到拓扑图的展示,最开始选用的是antv的拓扑图组件。antv组件虽然此很方便,但是在布局的时候总是会有莫名其妙的bug,然后自己也想法去解决(看前辈经验、官方issue),最后还是不能解决。…

【RuoYi-Cloud-Plus】学习笔记 09 - Sentinel(四)熔断降级知识整理

文章目录 前言参考目录版本说明学习笔记1、包结构2、DegradeSlot3、DegradeRule4、DegradeRuleManager5、CircuitBreaker5.1 CircuitBreaker.State6、AbstractCircuitBreaker6.1、AbstractCircuitBreaker#fromCloseToOpen6.2、AbstractCircuitBreaker#fromHalfOpenToOpen6.3、A…

Edge浏览器无法展示Stable Diffusion Control Net插件

Edge浏览器无法展示Stable Diffusion Control Net插件 最近在学习Stable Diffusion,需要使用到Control Net插件,结果通过各种方式安装成功插件后,浏览器页面没有展示ControlNet相关页面,最终换到Chorme浏览器后正常,猜…

安全测试方法介绍(上)静态源代码审查

软件开发完成之后,我们需要进行安全验证,验证我们的软件是不是符合安全要求。软件安全测试主要有以下几个方面:确定软件的安全特性实现是否与预期设计一致的过程;有关验证软件安全等级和识别潜在安全缺陷的过程;查找软…

云服务器下WordPress发送邮件的设置

WordPress的邮件功能很强大,可以实现用户密码以往后自助恢复等问题。 WordPress默认是使用php发邮件的,php需要配置好smtp(端口25)服务器及密码。这种方式不直观,因此一般都用smtp插件,常用的插件是WP Mai…

6.2.6 网络基本服务----电子邮件系统(E-mail)

6.2.6 网络基本服务----电子邮件系统(E-mail) 电子邮件系统是因特网上使用的最多且最受用户欢迎的一种应用 电子邮件系统包括用户代理和邮件服务器,提供收发邮件、邮件传送服务,邮件被传送到收信人邮件服务器的收信人信箱中&…

使用STM32实现 蓝牙插座

硬件介绍 蓝牙模块HC-01,其实之前就用过,使用起来非常简单 继电器模块, (VCC 3.3V)当左侧IN输入低电平时,右侧的ON 和 COM会导通,左上的绿灯会亮,此处充当插座的角色 项目需求 通过蓝牙的串口发送open打开…

8086变址寄存器和字符串拷贝程序学习

在此文用到了si和di寄存器; 8086汇编语言显示带颜色的字符串程序学习 - 使用emu8086_bcbobo21cn的博客-CSDN博客 下面单独来学习si和di寄存器; SI和DI是8086CPU中和BX功能相近的寄存器; 区别:SI和DI不能够分成两个8位寄存器来使用&#xff…