论文介绍
题目:Vision Permutator: A Permutable MLP-Like Architecture for Visual Recognition
论文地址:https://arxiv.org/pdf/2106.12368
QQ深度学习交流群:994264161
扫描下方二维码,加入深度学习论文指南星球!
加入即可获得,模块缝合、制作、写作技巧,学会“结构”创新、“创新点”创新,从三区到顶会,小论文大论文,毕业一站式服务
创新点
独特的结构设计:提出了一种名为 Vision Permutator (ViP) 的新型多层感知机 (MLP) 架构,与传统的 CNN 和 Vision Transformer (ViT) 不同,该架构通过分别在高度和宽度维度上编码特征来保留位置信息。这种方法可以捕获长距离的依赖关系,同时保留精确的位置信息,从而实现更具表现力的特征表示。
独立的维度处理:与其他将空间维度展平处理的 MLP 架构(如 Mixer 和 ResMLP)不同,ViP 在不丢失二维特征表示的情况下分别对高度和宽度维度进行处理。通过这种方法,ViP 能够生成对视觉识别至关重要的方向敏感输出。
高效的性能表现:在无需依赖卷积或自注意力机制的情况下,ViP 在 ImageNet 数据集上达到了 81.5% 的 Top-1 准确率,仅使用 25M 参数。这一表现超过了大多数相同规模的 CNN 和 Transformer 模型。
灵活的模型扩展:论文设计了三种不同规模的 ViP 模型(Small, Medium, Large),通过扩展模型的层数和隐藏维度,进一步提升性能。例如,88M 参数的 ViP-Large 模型实现了 83.2% 的 Top-1 准确率。
实验证明的有效性:通过实验,论文展示了单独编码高度和宽度维度信息的优势,尤其是在精细级别的特征表示上表现突出。同时,提出的 Weighted Permute-MLP 方法也进一步提高了模型的表现。
简单的数据依赖:与其他需要大规模数据集(如 ImageNet-22K)的 MLP 模型不同,ViP 在仅使用 ImageNet-1K 数据集的情况下就能实现优异的性能,这表明该架构在数据效率方面具有显著优势。
方法
整体架构
论文提出的 Vision Permutator (ViP) 模型通过将输入图像划分为小块(patches),使用线性投影生成特征嵌入,再经过多个 Permutator 块 处理特征,每个块包含 Permute-MLP 和 Channel-MLP,分别编码空间(高度和宽度)和通道信息,保留二维空间特性。最终通过全局平均池化和全连接层完成分类。ViP 创新地保留空间维度,捕捉位置敏感信息,在效率和性能上优于传统 MLP、CNN 和 Transformer 模型。
输入图像分块:
输入图像首先被均匀划分为小块(patches),每个小块的尺寸如
、16 × 16 16 \times 16 、14 × 14 14 \times 14 。7 × 7 7 \times 7 每个小块通过线性投影映射为嵌入表示(tokens)。这样,图像被转化为形状为
的特征表示,其中H × W × C H \times W \times C 和H H 是图像的高度和宽度,W W 是通道数。C C Permutator 块的堆叠:
使用三个分支分别处理高度、宽度和通道信息。
高度维度的处理通过高度-通道的维度置换(Permutation)实现;宽度维度类似。
每个分支输出后通过逐元素相加(element-wise addition)融合,并通过一个全连接层完成特征融合。
Permute-MLP:负责分别在高度(H)和宽度(W)维度上编码空间信息,同时还处理通道(C)维度信息。
Channel-MLP:负责对通道信息进行混合。
特征嵌入经过一系列的 Permutator 块 用于编码特征信息。
每个 Permutator 块包含以下两个主要模块:
Permute-MLP 的处理方法:
全局平均池化和分类:
经过 Permutator 块的特征最终通过全局平均池化 (Global Average Pooling),生成固定大小的特征向量。
这一特征向量输入一个全连接层,用于进行分类任务。
模型的不同配置:
ViP-Small: 较少的参数和层数,适用于资源受限的场景。
ViP-Medium: 参数和层数适中。
ViP-Large: 参数和层数最多,性能最强。
论文提出了三种不同规模的模型配置:
即插即用模块作用
VIP 作为一个即插即用模块:
计算资源有限但对性能有较高要求的场景:
ViP 的架构轻量高效,不依赖卷积和自注意力机制,适合在嵌入式设备、移动设备或低功耗场景中应用,例如边缘计算设备上的图像分类任务。
需要保留空间位置信息的任务:
图像分类:提高对不同类别图像特征的精确区分能力。
目标检测:对目标在图像中的位置敏感,便于精确定位。
语义分割:对像素级别的分类需要精准的空间位置信息。
ViP 特别适合需要处理二维空间特征并对位置信息敏感的任务,例如:
需要高效特征融合的多模态任务:
在多模态场景(例如结合图像和文本信息的任务)中,ViP 可作为特征提取模块,帮助高效融合来自不同维度的特征信息。
大模型精简和高效推理场景:
ViP 模块可以作为大型模型的替代组件,用于降低模型的参数量和计算复杂度,同时保持良好的性能,例如在 Transformer 模型中的部分替代应用。
消融实验结果
说明了数据增强方法对模型性能的影响。
实验对比了未使用数据增强和使用四种常见数据增强方法(Random Augmentation、CutOut、MixUp 和 CutMix)的表现。结果表明,数据增强显著提升了模型性能,其中 MixUp 和 CutMix 的效果尤为明显,将 Top-1 准确率从 75.3% 提升至 80.6%。
说明了模型规模(层数、隐藏维度)对性能的影响。
随着模型规模的增加(从 ViP-Small 到 ViP-Medium 再到 ViP-Large),Top-1 准确率分别提升到 81.5%、82.7% 和 83.2%,验证了扩大模型规模在性能提升上的有效性。
说明了对更精细级别的 token 表示进行编码的重要性。
比较不同初始 patch 大小(如
、16 × 16 16 \times 16 、14 × 14 14 \times 14 )的表现,发现较小的 patch 尺寸(如7 × 7 7 \times 7 )能够捕获更细粒度的特征,显著提升性能(Top-1 准确率从 79.8% 提升至 81.5%)。7 × 7 7 \times 7
说明了在 Permutator 模块中分别编码高度和宽度信息的重要性。
实验表明,若仅移除高度或宽度信息的编码,Top-1 准确率分别下降至 72.8% 和 72.7%,表明单独编码空间信息对性能的显著影响。此外,引入 Weighted Permute-MLP(加权的 Permute-MLP)进一步将性能提升到 80.6%,高于原始 Permute-MLP 的 80.2%。
即插即用模块
import torch
from torch import nn
# 论文地址:https://arxiv.org/pdf/2106.12368
# 论文:Vision Permutator: A Permutable MLP-Like Architecture for Visual Recognition
class MLP(nn.Module):
def __init__(self,in_features,hidden_features,out_features,act_layer=nn.GELU,drop=0.1):
super().__init__()
self.fc1=nn.Linear(in_features,hidden_features)
self.act=act_layer()
self.fc2=nn.Linear(hidden_features,out_features)
self.drop=nn.Dropout(drop)
def forward(self, x) :
return self.drop(self.fc2(self.drop(self.act(self.fc1(x)))))
class WeightedPermuteMLP(nn.Module):
def __init__(self,dim,seg_dim=8, qkv_bias=False, proj_drop=0.):
super().__init__()
self.seg_dim=seg_dim
self.mlp_c=nn.Linear(dim,dim,bias=qkv_bias)
self.mlp_h=nn.Linear(dim,dim,bias=qkv_bias)
self.mlp_w=nn.Linear(dim,dim,bias=qkv_bias)
self.reweighting=MLP(dim,dim//4,dim*3)
self.proj=nn.Linear(dim,dim)
self.proj_drop=nn.Dropout(proj_drop)
def forward(self,x) :
B,H,W,C=x.shape
c_embed=self.mlp_c(x)
S=C//self.seg_dim
h_embed=x.reshape(B,H,W,self.seg_dim,S).permute(0,3,2,1,4).reshape(B,self.seg_dim,W,H*S)
h_embed=self.mlp_h(h_embed).reshape(B,self.seg_dim,W,H,S).permute(0,3,2,1,4).reshape(B,H,W,C)
w_embed=x.reshape(B,H,W,self.seg_dim,S).permute(0,3,1,2,4).reshape(B,self.seg_dim,H,W*S)
w_embed=self.mlp_w(w_embed).reshape(B,self.seg_dim,H,W,S).permute(0,2,3,1,4).reshape(B,H,W,C)
weight=(c_embed+h_embed+w_embed).permute(0,3,1,2).flatten(2).mean(2)
weight=self.reweighting(weight).reshape(B,C,3).permute(2,0,1).softmax(0).unsqueeze(2).unsqueeze(2)
x=c_embed*weight[0]+w_embed*weight[1]+h_embed*weight[2]
x=self.proj_drop(self.proj(x))
return x
if __name__ == '__main__':
input=torch.randn(64,8,8,512)
seg_dim=8
block=WeightedPermuteMLP(512,seg_dim)
out=block(input) print(out.shape)
便捷下载方式
浏览打开网址:https://github.com/ai-dawang/PlugNPlay-Modules
更多分析可见原文