一张手绘图带你搞懂空间注意力、通道注意力、local注意力及生成过程(附代码注释)

soft attention(包括空间注意力、通道注意力)软注意学习的目的是选择细粒度的重要像素点,它们是pixel级。
hard attention( local 注意力) 硬注意学习则致力于搜索粗糙的潜在判别区域,它们是region级。
他们在功能上有很大的互补性。他们的结合使用可以提高模型的性能

下面讲解空间注意力、通道注意力、local 注意力的生成

在这里插入图片描述

空间注意力、通道注意力可行性解释

64个通道的采样图(如可生成见我博客)
在这里插入图片描述
通道注意力:
就是对于每个channel赋予不同的权重,比如1,2处马的形状比较明显,所以理所当然,对1,2通道的权重比较大,3,4处权重小。

空间注意力:
空间注意力是对64个通道进行mean的一个操作,得到一个(w x h)的权重,mean的操作就学到了所有通道的整体分布,而抛弃了奇异的通道。比如说1,2的图可以很好的描绘出马的形状,而3,4就不行(但本质上它也是要显示出马的形状),但是通过mean后,得到的w x h权值共享后,给了3,4一定的权值描述,相当于给3,4一定的注意力,这样它们也可以描绘出马的形状。

代码(展示的是Harmonious Attention Network for Person Re-Identification中SoftAttn生成的过程,与真实的通道注意力和空间注意力是有点差距的,忘知晓)

class SpatialAttn(nn.Module):  # 输入x.shape=(32,3,256,128),对第三维度通道求mean=(32,1,256,128),一个卷积照片缩小一半,upsample恢复,再经过1x1 conv

    def __init__(self):
        super(SpatialAttn, self).__init__()
        self.conv1 = ConvBlock(1, 1, 3, s=2, p=1)
        self.conv2 = ConvBlock(1, 1, 1)

    def forward(self, x):
        # global cross-channel averaging
        x = x.mean(1, keepdim=True)  # x.shape=(32,3,256,128)  x.mean.shape按照通道求均值=(32,1,256,128)
        # 3-by-3 conv
        x = self.conv1(x)  # x.shape=(32,1,128,64)
        # bilinear resizing
        x = F.upsample(x, (x.size(2) * 2, x.size(3) * 2), mode='bilinear', align_corners=True)  # x.shape=(32,1,256,128)
        # scaling conv
        x = self.conv2(x)  # x.shape=(32,1,256,128)
        return x

class ChannelAttn(nn.Module):

    def __init__(self, in_channels, reduction_rate=16):
        super(ChannelAttn, self).__init__()
        assert in_channels % reduction_rate == 0
        self.conv1 = ConvBlock(in_channels, in_channels // reduction_rate, 1)
        self.conv2 = ConvBlock(in_channels // reduction_rate, in_channels, 1)

    def forward(self, x):
        # squeeze operation (global average pooling)
        # x.shape=(32, 16, 256, 128)
        x = F.avg_pool2d(x, x.size()[2:])#torch.size([32,16,1,1])
        # excitation operation (2 conv layers)
        x = self.conv1(x)#torch.size([32,1,1,1])
        x = self.conv2(x)#torch.size([32,16,1,1])
        return x

class SoftAttn(nn.Module):#软注意力(32,16,256,128)=空间注意力的输出(32,1,256,128)乘上通道注意力(32,16,1,1)

    def __init__(self, in_channels):
        super(SoftAttn, self).__init__()
        self.spatial_attn = SpatialAttn()
        self.channel_attn = ChannelAttn(in_channels)
        self.conv = ConvBlock(in_channels, in_channels, 1)

    def forward(self, x):#x.shape(32,16,256,128)
        y_spatial = self.spatial_attn(x)#32,1,256,128
        y_channel = self.channel_attn(x)#32,16,1,1
        y = y_spatial * y_channel#32,16,256,128
        y = F.sigmoid(self.conv(y))
        return y#torch.Size([32, 16, 256, 128])

本人知识水平有限,要是错误的话,欢迎指正,感谢!

碰巧,如果你看到了这篇文章,并且觉得有用的话 那就给个三连吧!

一张手绘图带你搞懂空间注意力、通道注意力、local注意力及生成过程(附代码注释)_第1张图片

你可能感兴趣的:(深度学习)