SEnet、CBAM、ECA注意力三大机制

编程入门 行业动态 更新时间:2024-10-23 18:28:37

SEnet、CBAM、ECA注意力<a href=https://www.elefans.com/category/jswz/34/1767861.html style=三大机制"/>

SEnet、CBAM、ECA注意力三大机制

# 下面是通道注意力机制即SEnet的代码,个人理解SEnet是在对每个channel进行加权操作,看那个channel重要,就给他权重大一点。
# 每个channel由于每个特征向量不一样因此提取的特征也就不一样即通道注意力机制注重的是特征的重要性(图片的点、线、明暗)
# 因此通道注意力机制是对每个通道的长宽进行卷积,一开始对通道不进行改变
import torch
import torch.nn as nn
import mathclass se_block(nn.Module):def __init__(self, channel, ratio=16):super(se_block, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.fc = nn.Sequential(nn.Linear(channel, channel // ratio, bias=False),nn.ReLU(inplace=True),nn.Linear(channel // ratio, channel, bias=False),nn.Sigmoid())def forward(self, x):b, c, _, _ = x.size()y = self.avg_pool(x).view(b, c)y = self.fc(y).view(b, c, 1, 1)return x * y# 下面是通道注意力机制和空间注意力机制的结合(CBAM),空间注意力机制是每个通道内的看哪个比较重要
# 空间注意力机制他对应的将通道这个维度进行卷积或者池化,对通道进行压缩操作使其变成两个通道,对图片的长宽不进行改变
class ChannelAttention(nn.Module):def __init__(self, in_planes, ratio=8):super(ChannelAttention, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.max_pool = nn.AdaptiveMaxPool2d(1)# 利用1x1卷积代替全连接self.fc1   = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)self.relu1 = nn.ReLU()self.fc2   = nn.Conv2d(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))))max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))out = avg_out + max_outreturn self.sigmoid(out)class SpatialAttention(nn.Module):def __init__(self, kernel_size=7):super(SpatialAttention, self).__init__()assert kernel_size in (3, 7), 'kernel size must be 3 or 7'padding = 3 if kernel_size == 7 else 1self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)self.sigmoid = nn.Sigmoid()def forward(self, x):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)class cbam_block(nn.Module):def __init__(self, channel, ratio=8, kernel_size=7):super(cbam_block, self).__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# 下面是ECA,其就是将通道注意力机制中的两个全连接操纵变成了一个一维卷积
class eca_block(nn.Module):def __init__(self, channel, b=1, gamma=2):super(eca_block, self).__init__()kernel_size = int(abs((math.log(channel, 2) + b) / gamma))kernel_size = kernel_size if kernel_size % 2 else kernel_size + 1# 上面相当于对每个不同的图片,卷积核去自适应的进行改变self.avg_pool = nn.AdaptiveAvgPool2d(1)self.conv = nn.Conv1d(1, 1, kernel_size=kernel_size, padding=(kernel_size - 1) // 2, bias=False)# padding=(kernel_size - 1) // 2 相当于paddin=same,即保持输出图片大小不变的操作# 为啥这里进入的通道数是1呢,是因为前面有个自适应层,将图片变成了1*1*channel这个样子,在下面经过维度变换,此时将维度变成了b*1*c,然后conv1d是对最后一维进行卷积的(同理conv2d是对最后两维进行卷积的)因此就是对channel这个维度进行了一个卷积,此时就可以相当于把一个长方体横过来看(或者说换成了channel和长这个面)此时相当于宽为以前的通道数即1.self.sigmoid = nn.Sigmoid()def forward(self, x):y = self.avg_pool(x)y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)# y.squeeze(-1)是将最后一个维度删掉即宽这个维度就没有了,transpose(-1, -2)是将最后一个和倒数第二个维度进行互换,即现在的维度变成了b,1,c这三个维度,1是由于前面的自适应平均层变成了1*1的图像,所以长在这里就是1。unsqueeze(-1)是增加最后一个维度y = self.sigmoid(y)return x * y.expand_as(x)# y.expand_as(x)是将y的size于x的size进行一个统一,可以看成将y像x一样扩展

更多推荐

SEnet、CBAM、ECA注意力三大机制

本文发布于:2024-03-11 21:39:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1729959.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:三大   注意力   机制   SEnet   CBAM

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!