论文介绍
题目:ULSAM: Ultra-Lightweight Subspace Attention Module for Compact Convolutional Neural Networks
论文地址:https://arxiv.org/pdf/2006.15102
QQ深度学习交流群:719278780
扫描下方二维码,加入深度学习论文指南星球!
加入即可获得,模块缝合、制作、写作技巧,学会“结构”创新、“创新点”创新,从三区到顶会,小论文大论文,毕业一站式服务
创新点
提出了一种新的轻量级注意力模块:论文提出了“超轻量级子空间注意力模块”(ULSAM),专为紧凑型卷积神经网络(如MobileNet)设计。这是首次在紧凑型CNN中引入子空间注意力机制,能够以更低的计算和参数开销高效学习特征图中跨通道的信息。
子空间注意力的概念:论文主张通过为每个特征子空间学习单独的注意力图,可以实现多尺度和多频率特征表示。这样的设计更适合细粒度图像分类任务,能够更好地捕捉局部细节和全局信息。
计算和参数效率的改进:与现有的注意力机制(如SE-Net、CBAM)相比,ULSAM显著降低了计算开销(FLOPs)和参数数量。例如,在MobileNet-V2上,FLOPs和参数分别减少了约13%和25%,同时提升了ImageNet-1K和细粒度数据集上的分类精度。
实验验证与性能提升:在多个基准数据集(如ImageNet-1K、Caltech-UCSD Birds-200、Stanford Dogs等)上的实验表明,ULSAM能够在减少计算资源的同时提升分类精度。这验证了其在细粒度分类和资源受限环境中的实用性。
方法
整体架构
ULSAM(超轻量级子空间注意力模块)是一种高效的注意力机制模块,专为紧凑型卷积神经网络(如MobileNet)设计。其核心是将特征图划分为多个子空间,为每个子空间生成独立的注意力权重,通过轻量级的深度卷积和点卷积实现特征增强和跨通道信息交互。ULSAM可以作为插件插入或替代网络中的部分层,显著降低计算和参数开销,同时提升分类性能,尤其在细粒度图像分类任务中展现了卓越表现。
ULSAM 的核心设计如下:
特征划分:
输入特征图
F ∈ R m × h × w,其中 是通道数,m m 和h h 是空间尺寸。w w 将特征图划分为
个互斥子空间,每个子空间包含g g 个特征图。G = m g G = \frac{m}{g}
子空间注意力计算:
MaxPool: 提取局部信息。
Depthwise Convolution (DW): 高效提取跨通道信息。
Pointwise Convolution (PW): 使用单个卷积核进一步融合通道间信息。
Softmax: 生成注意力权重,确保权重和为 1。
对每个子空间
,计算一个对应的注意力图F n F_{n} :A n A_{n} A n = Softmax ( PW 1 ( MaxPool 3 × 3 , 1 ( DW 1 × 1 ( F n ) ) ) )
特征重分布:
:逐元素乘法。⊙ \odot :逐元素加法。⊕ \oplus
使用注意力图
对原始特征进行重新分配:A n A_{n} F ^ n = ( A n ⊙ F n ) ⊕ F n
特征合并:
将所有子空间的重新分配特征图
级联形成输出特征图F ^ n \hat{F}_{n} :F ^ \hat{F} F ^ = Concat ( F ^ 1 , F ^ 2 , … , F ^ g )
即插即用模块作用
ULSAM 作为一个即插即用模块:
提升紧凑型 CNN 的性能:
在 MobileNet-V1 和 MobileNet-V2 等紧凑型网络中,ULSAM 有效增强了特征图的表示能力,同时减少了冗余计算,提升了分类精度。
多尺度和多频率特征提取:
通过将特征图划分为多个子空间,并为每个子空间生成独立的注意力图,ULSAM 提供了更丰富的多尺度和多频率特征表示,适应复杂场景中的细节建模需求。
高效捕捉跨通道依赖:
传统卷积操作对通道间依赖的建模能力有限,ULSAM 通过轻量化设计高效捕获特征图中通道间的复杂关系,提升模型对特征的重要性判断能力。
减少计算和参数开销:
ULSAM 的设计避免了使用参数密集型模块(如 MLP),仅通过轻量卷积实现跨通道信息交互,适合资源受限设备,同时保持性能优越。
消融实验结果
表6:ULSAM 在不同位置和子空间数
结果:
在 MobileNet-V1 和 MobileNet-V2 的不同层插入 ULSAM 时,随着子空间数
的增加,性能先提升后略微下降。g g MobileNet-V1 在
和g = 4 g=4 时,Top-1 准确率最高,表明适当的子空间划分能够更好捕获跨通道信息。g = 8 g=8 说明:
子空间划分的数量
是关键超参数,过多子空间可能导致信息不足,过少则无法充分捕获特征间的复杂关系。g g
表7:在减少参数和 FLOPs 的情况下插入 ULSAM 的效果(ImageNet-1K)
ULSAM 可以在大幅减少计算和存储成本的情况下,维持甚至提升网络的分类性能。
在 MobileNet-V1 中替代或插入部分层后,FLOPs 和参数均显著减少,同时在
时保持了较高的准确率。g = 4 g=4 表8:MobileNet-V2 减少参数和 FLOPs 的实验结果(ImageNet-1K)
表明 ULSAM 在更加紧凑的网络中能够高效捕获重要特征,进一步验证了其轻量级设计的优势。
在 MobileNet-V2 的不同残差块中插入或替代为 ULSAM,随着 FLOPs 和参数减少,Top-1 准确率在合理范围内变化(有些情况甚至提升)。
表9-12:在细粒度数据集上的实验结果(Food-101、Birds 和 Dogs 数据集)
结果:
在不同子空间数
下,ULSAM 显著提升了细粒度分类的准确率,尤其在细节丰富的 Birds 和 Dogs 数据集中,性能提升尤为明显。g g 说明:
ULSAM 对高内类差异和复杂局部信息的任务(如细粒度分类)尤其有效,验证了其多尺度和多频率特征捕获能力。
即插即用模块
import torch
import torch.nn as nn
torch.set_default_tensor_type(torch.cuda.FloatTensor)
#ULSAM: Ultra-Lightweight Subspace Attention Module for Compact Convolutional Neural Networks(WACV20)
class SubSpace(nn.Module):
def __init__(self, nin: int) -> None:
super(SubSpace, self).__init__()
self.conv_dws = nn.Conv2d(
nin, nin, kernel_size=1, stride=1, padding=0, groups=nin
)
self.bn_dws = nn.BatchNorm2d(nin, momentum=0.9)
self.relu_dws = nn.ReLU(inplace=False)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
self.conv_point = nn.Conv2d(
nin, 1, kernel_size=1, stride=1, padding=0, groups=1
)
self.bn_point = nn.BatchNorm2d(1, momentum=0.9)
self.relu_point = nn.ReLU(inplace=False)
self.softmax = nn.Softmax(dim=2)
def forward(self, x: torch.Tensor) -> torch.Tensor:
out = self.conv_dws(x)
out = self.bn_dws(out)
out = self.relu_dws(out)
out = self.maxpool(out)
out = self.conv_point(out)
out = self.bn_point(out)
out = self.relu_point(out)
m, n, p, q = out.shape
out = self.softmax(out.view(m, n, -1))
out = out.view(m, n, p, q)
out = out.expand(x.shape[0], x.shape[1], x.shape[2], x.shape[3])
out = torch.mul(out, x)
out = out + x
return out
class ULSAM(nn.Module):
def __init__(self, nin: int, nout: int, h: int, w: int, num_splits: int) -> None:
super(ULSAM, self).__init__()
assert nin % num_splits == 0
self.nin = nin
self.nout = nout
self.h = h
self.w = w
self.num_splits = num_splits
self.subspaces = nn.ModuleList(
[SubSpace(int(self.nin / self.num_splits)) for i in range(self.num_splits)]
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
group_size = int(self.nin / self.num_splits)
# split at batch dimension
sub_feat = torch.chunk(x, self.num_splits, dim=1)
out = []
for idx, l in enumerate(self.subspaces):
out.append(self.subspaces[idx](sub_feat[idx]))
out = torch.cat(out, dim=1)
return out
if __name__ == '__main__':
input = torch.randn(1, 32, 112, 112)
block = ULSAM(32, 64, 112, 112, 4)
print(input.size())
output = block(input)
print(output.size())
便捷下载方式
浏览打开网址:https://github.com/ai-dawang/PlugNPlay-Modules
更多分析可见原文