PoolFormer 语义分割实战:MetaFormer 骨干网络在 MMSegmentation 中的配置、训练与评测指南
【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
导读
本文以 MMSegmentation 仓库中 configs/poolformer 的官方配置与 README 为主体,系统讲解如何将 PoolFormer 这一 MetaFormer 代表性骨干网络接入语义分割任务。文章覆盖 PoolFormer 的核心思想(用简单池化替换注意力)、mmpretrain 环境依赖、FPN 全金字塔解码结构、ADE20K 上的完整实验结果表,以及从配置继承、模型变体替换到训练评测的全链路实操,帮助读者直接复现 PoolFormer + FPN 的分割方案,并理解其底层实现原理。
PoolFormer 与 MetaFormer:为什么"池化"也能媲美注意力
PoolFormer 出自论文MetaFormer is Actually What You Need for Vision(CVPR 2022),其核心观点是:Transformer 真正起作用的是"通用架构"(MetaFormer),而不是其中的注意力 token mixer 模块。
论文的验证思路非常直接:既然已有工作证明注意力可以被空间 MLP 替换且效果仍然不错,那么进一步把注意力模块替换为一个"极其简单的空间池化算子"(仅做最基本的 token mixing),得到的模型——即 PoolFormer——是否依然具备竞争力?实验结果表明答案是肯定的:
- 在 ImageNet-1K 上,PoolFormer 达到 82.1% top-1 精度,超过调参充分的视觉 Transformer/MLP 类基线 DeiT-B 0.3%、ResMLP-B24 1.1%;
- 同时参数量分别减少 35% / 52%,MACs 减少 48% / 60%。
该结论推动提出了MetaFormer这一从 Transformer 中抽象出的通用架构概念——即不指定 token mixer 的通用框架。论文进一步论证:近期在视觉任务上表现优异的 Transformer 与 MLP 类模型,其关键贡献者正是 MetaFormer 通用架构本身,因此未来研究应更多聚焦于改进 MetaFormer,而非仅仅设计 token mixer 模块。PoolFormer 也因此可以充当未来 MetaFormer 架构设计的起点基线。
在 MMSegmentation 中,PoolFormer 以**骨干网络(Backbone)**身份出现,配以 FPN 颈部与 FPN 解码头构成完整的分割模型,官方配置与权重索引见 configs/poolformer 与 configs/poolformer/metafile.yaml。
使用前提:先安装 mmpretrain 获取 PoolFormer 骨干
PoolFormer 骨干网络本身托管在 MMClassification(现为 mmpretrain)中,MMSegmentation 通过注册机制直接复用。官方 README 明确指出:
- PoolFormer backbone 需要先安装 MMClassification,其中包含丰富的下游任务骨干网络;
- 预训练权重也可以从 MMClassification 的 PoolFormer 配置中获取。
安装命令(MMSegmentation v1.x 配套版本要求):
pip install "mmpretrain>=1.0.0rc7"安装完成后,还需要在配置中显式导入 mmpretrain 的模型注册。以 configs/base/models/fpn_poolformer_s12.py 为例:
# TODO: delete custom_imports after mmpretrain supports auto import # please install mmpretrain >= 1.0.0rc7 # import mmpretrain.models to trigger register_module in mmpretrain custom_imports = dict( imports=['mmpretrain.models'], allow_failed_imports=False)这段custom_imports的作用是在加载配置时先导入mmpretrain.models,从而触发 mmpretrain 内部模块的register_module注册,使配置中的type='mmpretrain.PoolFormer'能够被正确解析。若 mmpretrain 已支持自动导入,这一行可以删除(源码注释中已注明该 TODO)。
配置文件全解析:骨干、FPN 颈部与解码头
PoolFormer 在 MMSegmentation 中的最小可运行配置为 configs/poolformer/fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py,其通过_base_机制继承三份基础配置:
_base_ = [ '../_base_/models/fpn_poolformer_s12.py', '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' ]骨干网络(Backbone)
骨干部分定义在 configs/base/models/fpn_poolformer_s12.py:
model = dict( type='EncoderDecoder', data_preprocessor=data_preprocessor, backbone=dict( type='mmpretrain.PoolFormer', arch='s12', init_cfg=dict( type='Pretrained', checkpoint=checkpoint_file, prefix='backbone.'), in_patch_size=7, in_stride=4, in_pad=2, down_patch_size=3, down_stride=2, down_pad=1, drop_rate=0., drop_path_rate=0., out_indices=(0, 2, 4, 6), frozen_stages=0, ), ... )关键参数说明:
| 参数 | 默认值 | 作用 |
|---|---|---|
type | mmpretrain.PoolFormer | 直接复用 mmpretrain 注册的 PoolFormer 骨干 |
arch | 's12' | 模型变体,可选 s12 / s24 / s36 / m36 / m48 |
init_cfg | Pretrained | 从 ImageNet-1K 预训练权重初始化,prefix='backbone.'对应权重字典前缀 |
in_patch_size / in_stride / in_pad | 7 / 4 / 2 | 输入 Patch Embedding 的卷积核尺寸、步长与 padding |
down_patch_size / down_stride / down_pad | 3 / 2 / 1 | 各阶段间下采样卷积参数 |
out_indices | (0, 2, 4, 6) | 输出第 0/2/4/6 四个阶段的特征图,供 FPN 使用 |
frozen_stages | 0 | 冻结前若干 stage 的骨干参数,0 表示全部参与训练 |
预训练权重 URL 直接写在基础配置中(S12 为poolformer-s12_3rdparty_32xb128_in1k,m48 为poolformer-m48_3rdparty_32xb128_in1k),各变体权重可在 mmpretrain 的 PoolFormer 配置页获取后,通过checkpoint_file覆盖。
数据预处理器
data_preprocessor = dict( type='SegDataPreProcessor', mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], bgr_to_rgb=True, pad_val=0, seg_pad_val=255)这是 MMSegmentation v1.x 引入的SegDataPreProcessor,统一完成归一化、BGR→RGB 通道转换、padding 等操作,其中seg_pad_val=255表示标签 padding 值 255(该值在计算损失时默认被忽略)。
特征金字塔颈部(FPN Neck)
FPN 颈部定义如下:
neck=dict( type='FPN', in_channels=[256, 512, 1024, 2048], out_channels=256, num_outs=4),注意:S12 骨干四个阶段的实际输出通道为[64, 128, 320, 512],因此 fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py 中会覆盖:
model = dict( data_preprocessor=data_preprocessor, neck=dict(in_channels=[64, 128, 320, 512]), decode_head=dict(num_classes=150))FPN 颈部的底层实现在 mmseg/models/necks/fpn.py:对每个输入层级先做1x1lateral 卷积统一通道到out_channels,再从最深层开始自顶向下逐级最近邻上采样相加(top-down path),最后对每个层级做3x3卷积输出,得到 4 个尺度、每尺度 256 通道的特征金字塔。
解码头(FPNHead)
解码头采用 Semantic FPN 风格的FPNHead(实现见 mmseg/models/decode_heads/fpn_head.py):
decode_head=dict( type='FPNHead', in_channels=[256, 256, 256, 256], in_index=[0, 1, 2, 3], feature_strides=[4, 8, 16, 32], channels=128, dropout_ratio=0.1, num_classes=19, norm_cfg=norm_cfg, align_corners=False, loss_decode=dict( type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)),从源码看,FPNHead为每个feature_strides构造一个scale_head:各尺度先经 3x3 卷积(必要时级联双线性上采样),再逐级相加融合为单张高分辨率特征图,最后经cls_seg卷积输出num_classes通道的分割 logits。ADE20K 配置将num_classes覆盖为 150。
训练调度与优化器
基础调度来自 configs/base/schedules/schedule_40k.py(默认 SGD + 40k 迭代)。PoolFormer 配置将其整体替换为 AdamW + AMP 混合精度:
optim_wrapper = dict( _delete_=True, type='AmpOptimWrapper', optimizer=dict(type='AdamW', lr=0.0002, weight_decay=0.0001)) param_scheduler = [ dict( type='PolyLR', power=0.9, begin=0, end=40000, eta_min=0.0, by_epoch=False, ) ]_delete_=True:删除继承的 SGD 优化器配置,防止与 AdamW 冲突;AmpOptimWrapper:启用自动混合精度(对应显存占用较低,可参考结果表中各变体 4.17–10.48 GB 的显存数据);PolyLR:多项式学习率衰减,power=0.9、eta_min=0.0、按迭代(by_epoch=False)衰减,40k 迭代到 0。
数据流水线方面,训练采用RandomResize + RandomCrop(512×512) + RandomFlip + PhotoMetricDistortion,其中cat_max_ratio=0.75限制裁剪窗口内单类别占比过高;测试采用Resize + ResizeToMultiple(32)保证尺寸可被 32 整除(见下文实现细节说明)。
模型变体与快速替换
PoolFormer 提供 5 种规模变体,全部在 configs/poolformer 目录下,每个变体对应一份独立配置:
| 配置 | 变体 | 骨干通道 |
|---|---|---|
| fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py | S12 | [64, 128, 320, 512] |
| fpn_poolformer_s24_8xb4-40k_ade20k-512x512.py | S24 | 同上(仅 arch 与权重不同) |
| fpn_poolformer_s36_8x4_512x512_40k_ade20k.py | S36 | 同上(仅 arch 与权重不同) |
| fpn_poolformer_m36_8xb4-40k_ade20k-512x512.py | M36 | 同上 |
| fpn_poolformer_m48_8xb4-40k_ade20k-512x512.py | M48 | [96, 192, 384, 768] |
小/中规模(S/M)变体以继承 S12 配置为基础,仅需覆盖arch、预训练权重与 FPN 输入通道。以 M48 为例,fpn_poolformer_m48_8xb4-40k_ade20k-512x512.py 完整内容为:
_base_ = './fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py' checkpoint_file = 'https://download.openmmlab.com/mmclassification/v0/poolformer/poolformer-m48_3rdparty_32xb128_in1k_20220414-9378f3eb.pth' # noqa # model settings model = dict( backbone=dict( arch='m48', init_cfg=dict( type='Pretrained', checkpoint=checkpoint_file, prefix='backbone.')), neck=dict(in_channels=[96, 192, 384, 768]))这种"继承 + 覆盖"的写法使得新增变体成本极低:换arch、换权重、改neck.in_channels三步即可。
ADE20K 实验结果一览
官方 README 提供了 5 个变体在 ADE20K(512×512 裁剪,ImageNet-1K 预训练)上的完整评测结果。下表完整继承该结果(mIoU*表示采用Resize + ResizeToMultiple测试流水线时的指标;ms+flip为多尺度 + 翻转测试增强,MMSegmentation v1.x 中仍在完善中):
| Method | Backbone | Crop Size | pretrain | Batch Size | Lr schd | Mem (GB) | Inf time (fps) | Device | mIoU | mIoU* |
|---|---|---|---|---|---|---|---|---|---|---|
| FPN | PoolFormer-S12 | 512x512 | ImageNet-1K | 32 | 40000 | 4.17 | 23.48 | V100 | 36.68 | 37.07 |
| FPN | PoolFormer-S24 | 512x512 | ImageNet-1K | 32 | 40000 | 5.47 | 15.74 | V100 | 40.12 | 40.36 |
| FPN | PoolFormer-S36 | 512x512 | ImageNet-1K | 32 | 40000 | 6.77 | 11.34 | V100 | 41.61 | 41.81 |
| FPN | PoolFormer-M36 | 512x512 | ImageNet-1K | 32 | 40000 | 8.59 | 8.97 | V100 | 41.95 | 42.35 |
| FPN | PoolFormer-M48 | 512x512 | ImageNet-1K | 32 | 40000 | 10.48 | 6.69 | V100 | 42.43 | 42.76 |
各模型的权重与训练日志索引统一记录在 configs/poolformer/metafile.yaml 中(Weights与Training log字段),训练资源为 8×V100 GPU、总 batch size 32(单卡 4)。从表中可以清晰看到一条规律:骨干规模从 S12 增大到 M48,mIoU 从 36.68 提升至 42.43,代价是显存从 4.17 GB 增至 10.48 GB、推理速度从 23.48 fps 降至 6.69 fps——这为不同硬件条件下的骨干选型提供了直接参考。
关键实现细节说明
官方 README 在表格下方给出三条重要说明,直接关系到评测口径的一致性:
AlignedResize被替换为Resize + ResizeToMultiple:原版 PoolFormer 实现使用AlignedResize保证 resize 后尺寸对齐,MMSegmentation 中改用标准Resize后接ResizeToMultiple(size_divisor=32),效果等价且与框架现有流水线兼容,见 fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py 中test_pipeline的第 2、3 行。mIoU*的口径:带*的 mIoU 是在test_pipeline采用Resize + ResizeToMultiple时采集的,日志(log)中的 mIoU 同样基于该口径,因此上表中普通 mIoU 与mIoU*存在约 0.2–0.4 的差异属于预期现象,对比结果时须注意口径一致。测试时增强(TTA)状态:MMSegmentation v1.x 中
ms+flip(多尺度 + 翻转)测试增强仍在开发完善中,当前表格中该项为空,读者使用时需留意版本更新。
训练与测试命令
在完成数据准备(ADE20K 数据集按 MMSegmentation 约定放置于data/ade/ADEChallengeData2016,配置中data_root指向该目录)与 mmpretrain 安装后,即可基于任意变体配置启动训练:
# 单卡训练 python tools/train.py configs/poolformer/fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py # 多卡分布式训练(例如 8 卡) bash tools/dist_train.sh configs/poolformer/fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py 8训练完成后,使用tools/test.py配合从 configs/poolformer/metafile.yaml 获取的官方权重进行评测:
# 单卡测试 python tools/test.py configs/poolformer/fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py ${CHECKPOINT_FILE} # 多卡测试 bash tools/dist_test.sh configs/poolformer/fpn_poolformer_s12_8xb4-40k_ade20k-512x512.py ${CHECKPOINT_FILE} 8评测默认使用配置中的test_evaluator = dict(type='IoUMetric', iou_metrics=['mIoU']),输出 mIoU 等标准语义分割指标。
引用与延伸阅读
若在研究中使用了 PoolFormer 或 MetaFormer 思想,请引用原论文:
@inproceedings{yu2022metaformer, title={Metaformer is actually what you need for vision}, author={Yu, Weihao and Luo, Mi and Zhou, Pan and Si, Chenyang and Zhou, Yichen and Wang, Xinchao and Feng, Jiashi and Yan, Shuicheng}, booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition}, pages={10819--10829}, year={2022} }进一步深入阅读时,建议按以下路径在仓库内展开:
- 骨干定义与 mmpretrain 注册机制:configs/base/models/fpn_poolformer_s12.py;
- FPN 颈部逐层实现:mmseg/models/necks/fpn.py;
- Semantic FPN 解码头实现:mmseg/models/decode_heads/fpn_head.py;
- 全部 5 个变体的配置与权重索引:configs/poolformer 与 configs/poolformer/metafile.yaml。
PoolFormer 的价值在于用最简算子验证了"通用架构优于特定模块"这一命题——理解了它,也就理解了 MetaFormer 系列后续骨干(如 ConvNeXt 等)的设计逻辑,是学习现代视觉骨干演进脉络的理想起点。
【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考