深度学习模块26-SKAttention模块

25、SKAttention模块

论文《Selective Kernel Networks》

1、作用

该论文介绍了选择性核网络(SKNets),这是一种在卷积神经网络(CNN)中的动态选择机制,允许每个神经元根据输入自适应地调整其感受野大小。这种方法受到视觉皮层神经元对不同刺激响应时感受野大小变化的启发,在CNN设计中不常利用此特性。

2、机制

SKNets利用了一个称为选择性核(SK)单元的构建模块,该模块包含具有不同核大小的多个分支。这些分支通过一个softmax注意力机制融合,由这些分支中的信息引导。这个融合过程使得神经元能够根据输入自适应地调整其有效感受野大小。

3、独特优势

1、自适应感受野

SKNets中的神经元可以基于输入动态调整其感受野大小,模仿生物神经元的适应能力。这允许在不同尺度上更有效地处理视觉信息。

2、计算效率

尽管为了适应性而纳入了多种核大小,SKNets仍然保持了较低的模型复杂度,与现有最先进的架构相比。通过仔细的设计选择,如使用高效的分组/深度卷积和注意力机制中的缩减比率来控制参数数量,实现了这种效率。

3、性能提升

在ImageNet和CIFAR等基准测试上的实验结果显示,SKNets在具有相似或更低模型复杂度的情况下,超过了其他最先进的架构。适应性调整感受野的能力可能有助于更有效地捕捉不同尺度的目标对象,提高识别性能。

4、代码

import numpy as np
import torch
from torch import nn
from torch.nn import init
from collections import OrderedDict

class SKAttention(nn.Module):
    def __init__(self, channel=512, kernels=[1, 3, 5, 7], reduction=16, group=1, L=32):
        super().__init__()
        # 计算维度压缩后的向量长度
        self.d = max(L, channel // reduction)
        # 不同尺寸的卷积核组成的卷积层列表
        self.convs = nn.ModuleList([])
        for k in kernels:
            self.convs.append(
                nn.Sequential(OrderedDict([
                    ('conv', nn.Conv2d(channel, channel, kernel_size=k, padding=k // 2, groups=group)),
                    ('bn', nn.BatchNorm2d(channel)),
                    ('relu', nn.ReLU())
                ]))
            )
        # 通道数压缩的全连接层
        self.fc = nn.Linear(channel, self.d)
        # 为每个卷积核尺寸对应的特征图计算注意力权重的全连接层列表
        self.fcs = nn.ModuleList([])
        for i in range(len(kernels)):
            self.fcs.append(nn.Linear(self.d, channel))
        # 注意力权重的Softmax层
        self.softmax = nn.Softmax(dim=0)

    def forward(self, x):
        bs, c, _, _ = x.size()
        conv_outs = []
        # 通过不同尺寸的卷积核处理输入
        for conv in self.convs:
            conv_outs.append(conv(x))
        feats = torch.stack(conv_outs, 0)  # k,bs,channel,h,w

        # 将所有卷积核的输出求和得到融合特征图U
        U = sum(conv_outs)  # bs,c,h,w

        # 对融合特征图U进行全局平均池化,并通过全连接层降维得到Z
        S = U.mean(-1).mean(-1)  # bs,c
        Z = self.fc(S)  # bs,d

        # 计算每个卷积核对应的注意力权重
        weights = []
        for fc in self.fcs:
            weight = fc(Z)
            weights.append(weight.view(bs, c, 1, 1))  # bs,channel
        attention_weights = torch.stack(weights, 0)  # k,bs,channel,1,1
        attention_weights = self.softmax(attention_weights)  # k,bs,channel,1,1

        # 将注意力权重应用到对应的特征图上,并对所有特征图进行加权求和得到最终的输出V
        V = (attention_weights * feats).sum(0)
        return V

# 示例用法
if __name__ == '__main__':
    input = torch.randn(50, 512, 7, 7)
    sk = SKAttention(channel=512, reduction=8)
    output = sk(input)
    print(output.shape)  # 输出经过SK注意力处理后的特征图形状

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容