注意力机制:通道注意力机制、空间注意力机制、CBAM(附有完整代码)

目录

注意力机制

什么是注意力机制?

注意力机制的作用

通道注意力机制

原理

代码

结果

空间注意力机制

原理

代码

结果

CBAM注意力机制

原理

代码

结果


 

注意力机制

什么是注意力机制?

注意力机制(Attention Mechanism)是一种模仿人类注意力机制的计算机科学原理,主要用于提高神经网络在处理序列数据时的性能。在深度学习中,注意力机制被广泛应用于各种任务,如自然语言处理、计算机视觉和强化学习等领域。

注意力机制的核心思想是让模型能够在处理输入数据时,动态地关注输入的不同部分,而不是一概而论地平均对待所有输入。通过引入注意力机制,模型可以根据输入数据的重要性分配不同的权重,从而使模型能够更加集中精力处理与当前任务相关的信息,提高模型的表现和泛化能力

通俗地讲,注意力机制就好比是人类的注意力一样。当我们面对复杂的信息时,我们会集中精力关注其中的某些部分,而忽略其他不重要的部分。注意力机制在神经网络中的作用类似于这个过程,它让模型能够有选择地关注输入数据的特定部分,从而更好地处理和理解信息。

举个例子,假设你在观看一张照片并描述其中的内容。如果照片上有一只猫和一只狗,注意力机制就像是告诉你:“现在把注意力放在猫的部分”,这样你就能更专注地描述照片中的猫,而忽略掉其他不相关的内容。


注意力机制的作用

1.提高模型性能:通过引入注意力机制,模型可以更加聚焦地处理输入数据,从而提高模型在各种任务中的性能,包括图像分类、目标检测、语言建模等。

2.解决长距离依赖问题:在处理序列数据时,注意力机制可以帮助模型更好地捕捉序列中不同位置之间的相关性,从而缓解长距离依赖问题,提高模型在翻译、文本生成等任务中的表现。

3.抑制无关信息:通过注意力机制,模型可以动态地抑制输入数据中的无关信息,集中精力处理重要的部分,提高模型的鲁棒性和泛化能力。

4.可解释性:注意力机制可以帮助理解模型的预测过程,例如在图像分类任务中,可以观察模型对于输入图像的不同区域给予了怎样的关注,从而解释模型的预测依据。

增强模型对抗性:在对抗性攻击方面,注意力机制可以帮助模型更好地捕捉输入数据的特征,从而增强模型对抗性,提高模型的安全性。

总的来说,注意力机制的作用是让模型能够更加智能地处理输入数据,从而提高模型的性能、可解释性和鲁棒性。因此,注意力机制在深度学习中扮演着至关重要的角色。
 

通道注意力机制

原理

通道注意力机制(Channel Attention Module)的目的是通过动态调整每个通道的重要性,使模型能够更有效地利用输入数据的信息。

通道注意力机制的核心思想是让模型自动学习每个通道的重要性,并根据通道的贡献调整输入数据的表示。通过引入通道注意力机制,模型可以更加有效地利用每个通道的信息,提高模型对输入数据的表征能力,从而改善模型在各种任务中的性能。

如下图:先将输入特征图分别进行全局最大池化和全局平均池化(是在特征层的高和宽上进行池化),得到两张不同维度的特征描述。然后池化后的特征图共用一个多层感知器网络,先通过一个全连接层进行特征降维,再通过全连接层进行特征升维。将两张特征图在通道维度堆叠,经过 sigmoid 激活函数将特征图的每个通道的权重归一化到0-1之间。最后,将归一化后的权重和输入特征图相乘,得到处理好的特征图。

c5eebac5b8e94cddab1951f42f121345.png

详细操作:

141ff9f58c4c4c1d9767fde4697881e1.png

代码

注:代码使用的三维卷积

import torch.nn as nn
import torch
import torch.nn.functional as f

print("************************通道注意力机制*********************")


# 通道注意力机制
class ChannelAttention(nn.Module):
    # 初始化,in_planes参数指定了输入特征图的通道数,ratio参数用于控制通道注意力机制中特征降维和升维过程中的压缩比率。默认值为8
    def __init__(self, in_planes, ratio=8):
        # 继承父类初始化方法
        super().__init__()
        # 全局最大池化 [b,c,h,w]==>[b,c,1,1]
        self.avg_pool = nn.AdaptiveAvgPool3d((4, 1, 1)) # C*H*W
        # 全局平均池化 [b,c,h,w]==>[b,c,1,1]
        self.max_pool = nn.AdaptiveMaxPool3d((4, 1, 1)) # C*H*W

        # 使用1x1x1卷积核代替全连接层进行特征降维
        self.fc1 = nn.Conv3d(in_planes, in_planes // ratio, 1, bias=False)
        # 激活函数
        self.relu1 = nn.ReLU()
        # 使用1x1x1卷积核进行特征升维
        self.fc2 = nn.Conv3d(in_planes // ratio, in_planes, 1, bias=False)

        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # 通过平均池化和最大池化后的特征进行卷积、激活、再卷积操作
        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x)))) # 平均池化-->卷积-->RELu激活-->卷积
        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x)))) # 最大池化-->卷积-->RELu激活-->卷积
        # 将两个输出相加
        out = avg_out + max_out
        # 应用Sigmoid函数
        return self.sigmoid(out)

# 创建ChannelAttention模型的实例,输入通道数为256
model = ChannelAttention(256)
# 打印模型结构
print(model)
# 创建一个形状为[2, 256, 4, 8, 8]的输入张量,所有元素初始化为1
inputs = torch.ones([2, 256, 4, 8, 8]) # 2是批次大小(batch size),256是通道数,4、8、8分别是深度、高度和宽度的维度
# 将输入张量传递给模型,并获取输出
outputs = model(inputs)
# 打印输入张量的形状
print(inputs.shape) # [2, 256, 4, 8, 8]
# 打印输出张量的形状
print(outputs.shape) # [2, 256, 4, 1, 1]

结果

620866857eca474eb65c085297ac6c0e.png

空间注意力机制

原理

空间注意力机制(Spatial Attention Module)是一种用于处理空间信息的注意力机制,主要用于在深度学习模型中动态地调整输入数据的不同空间位置的重要性,以增强有用信息并抑制无用信息。在图像处理等领域,空间注意力机制可以帮助模型更好地关注图像中不同区域的特征,从而提高模型的表征能力和性能。

空间注意力模型就是寻找网络中最重要的部位进行处理。旨在提升关键区域的特征表达,本质上是将原始图片中的空间信息通过空间转换模块,变换到另一个空间中并保留关键信息,为每个位置生成权重掩膜(mask)并加权输出,从而增强感兴趣的特定目标区域同时弱化不相关的背景区域

如下图:首先,对输入进来的特征层,在每一个特征点的通道上取最大值和平均值,特征图的高和宽不变相当与对输入进来的特征图压扁了,通道数变为1。之后将这两个结果进行一个堆叠。然后,使用 7*7 (或3*3)大小的卷积核融合通道信息,特征图从 [B,2,H,W] 变成 [B,1,H,W]。然后,使用Sigmoid函数,获得了输入特征层每一个特征点的权值(0-1之间)。最后,将这个权值乘上原输入特征层即可。

6fb56a562e5b403f9c2de607cc906304.png

详细操作:

74e685dce2514b2582aa87aec222d1d2.png

代码

注:代码使用的三维卷积

import torch.nn as nn
import torch
import torch.nn.functional as f

print("************************空间注意力机制*********************")


# 空间注意力机制
class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=3):
        super().__init__()

        # 断言法:kernel_size必须为3或7
        assert kernel_size in (3, 7),'kernel size must be 3 or 7'
        # 三元操作:如果kernel_size的值等于7,则padding被设置为3;否则(即kernel_size的值为3),padding被设置为1。
        padding = 3 if kernel_size == 7 else 1
        # 定义一个卷积层,输入通道数为2,输出通道数为1
        self.conv1 = nn.Conv3d(2, 1, kernel_size, padding=padding, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # (N, C, H, W),dim=1沿着通道维度C,计算张量的平均值和最大值
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        # 将平均值和最大值在通道维度上拼接
        x = torch.cat([avg_out, max_out], dim=1)
        x = self.conv1(x)
        return self.sigmoid(x)

model = SpatialAttention(kernel_size=7)
print(model)
inputs = torch.ones([2, 256, 4, 8, 8])
outputs = model(inputs)
print(inputs.shape)
print(outputs.shape)

结果

4d35ee4000f548cf84591c5c70a5d3c0.png

CBAM注意力机制

原理

CBAM(Convolutional Block Attention Module)模块是一种结合了通道注意力和空间注意力机制的注意力模块,旨在提高卷积神经网络(CNN)对图像特征的表征能力。CBAM模块通过同时关注通道维度和空间维度的特征信息,实现了对图像特征的全局感知和重要性调整。

CBAM模块通常由两个子模块组成:通道注意力模块(Channel Attention Module)和空间注意力模块(Spatial Attention Module)。这两个子模块分别用于对通道维度和空间维度的特征进行加权调整,从而提高特征表示的表征能力。(两个Attention进行串联,Channel 在前,Spatial在后)如下图:

aef0c95e908346ba85ffb29729eb4e44.png

模块会沿着两个独立的维度(通道和空间)依次推断注意力图,然后将注意力图乘以输入特征图以进行自适应特征修饰。 由于CBAM是轻量级的通用模块,因此可以以可忽略的开销将其无缝集成到任何CNN架构中,并且可以与基础CNN一起进行端到端训练。

代码

注:代码使用的三维卷积

import torch.nn as nn
import torch
import torch.nn.functional as f

print("************************通道注意力机制*********************")


# 通道注意力机制
class ChannelAttention(nn.Module):
    # 初始化,in_planes参数指定了输入特征图的通道数,ratio参数用于控制通道注意力机制中特征降维和升维过程中的压缩比率。默认值为8
    def __init__(self, in_planes, ratio=8):
        # 继承父类初始化方法
        super().__init__()
        # 全局最大池化 [b,c,h,w]==>[b,c,1,1]
        self.avg_pool = nn.AdaptiveAvgPool3d((4, 1, 1)) # C*H*W
        # 全局平均池化 [b,c,h,w]==>[b,c,1,1]
        self.max_pool = nn.AdaptiveMaxPool3d((4, 1, 1)) # C*H*W

        # 使用1x1x1卷积核代替全连接层进行特征降维
        self.fc1 = nn.Conv3d(in_planes, in_planes // ratio, 1, bias=False)
        # 激活函数
        self.relu1 = nn.ReLU()
        # 使用1x1x1卷积核进行特征升维
        self.fc2 = nn.Conv3d(in_planes // ratio, in_planes, 1, bias=False)

        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # 通过平均池化和最大池化后的特征进行卷积、激活、再卷积操作
        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x)))) # 平均池化-->卷积-->RELu激活-->卷积
        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x)))) # 最大池化-->卷积-->RELu激活-->卷积
        # 将两个输出相加
        out = avg_out + max_out
        # 应用Sigmoid函数
        return self.sigmoid(out)

# 创建ChannelAttention模型的实例,输入通道数为256
model = ChannelAttention(256)
# 打印模型结构
print(model)
# 创建一个形状为[2, 256, 4, 8, 8]的输入张量,所有元素初始化为1
inputs = torch.ones([2, 256, 4, 8, 8]) # 2是批次大小(batch size),256是通道数,4、8、8分别是深度、高度和宽度的维度
# 将输入张量传递给模型,并获取输出
outputs = model(inputs)
# 打印输入张量的形状
print(inputs.shape) # [2, 256, 4, 8, 8]
# 打印输出张量的形状
print(outputs.shape) # [2, 256, 4, 1, 1]

print("************************空间注意力机制*********************")


# 空间注意力机制
class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=3):
        super().__init__()

        # 断言法:kernel_size必须为3或7
        assert kernel_size in (3, 7),'kernel size must be 3 or 7'
        # 三元操作:如果kernel_size的值等于7,则padding被设置为3;否则(即kernel_size的值为3),padding被设置为1。
        padding = 3 if kernel_size == 7 else 1
        # 定义一个卷积层,输入通道数为2,输出通道数为1
        self.conv1 = nn.Conv3d(2, 1, kernel_size, padding=padding, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # (N, C, H, W),dim=1沿着通道维度C,计算张量的平均值和最大值
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        # 将平均值和最大值在通道维度上拼接
        x = torch.cat([avg_out, max_out], dim=1)
        x = self.conv1(x)
        return self.sigmoid(x)

model = SpatialAttention(kernel_size=7)
print(model)
inputs = torch.ones([2, 256, 4, 8, 8])
outputs = model(inputs)
print(inputs.shape)
print(outputs.shape)


print("************************CBAM模块*********************")
class CBAM_Block(nn.Module):
    def __init__(self, channel, ratio=8, kernel_size=3):
        super().__init__()
        # 初始化通道注意力模块
        self.channelAttention = ChannelAttention(channel, ratio=ratio)
        # 初始化空间注意力模块
        self.SpatialAttention = SpatialAttention(kernel_size=kernel_size)

    def forward(self, x):
        # 应用通道注意力和空间注意力
        x = x * self.channelAttention(x)
        x = x * self.SpatialAttention(x)
        return x

model = CBAM_Block(256)
print(model)
inputs = torch.ones([2, 256, 4, 8, 8])
outputs = model(inputs)
print(inputs.shape)
print(outputs.shape)

结果

07a8ec92c59e47a29283c5b717e932ba.png

 

  • 42
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值