- 人工智能
- 计算机视觉
- 预训练
【免费下载链接】PaddleSeg
Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting, 3D Segmentation, etc.
本文围绕 PaddleSeg 仓库configs/maskformer/目录下的模型文档与配套配置展开,系统讲解 MaskFormer 在 PaddlePaddle 上的完整落地形态:如何从 4 份 ADE20k 训练配置出发,理解其数据增广、Swin Transformer 专用 backbone、Pixel Decoder + Transformer Predictor 的解码结构、匈牙利匹配损失,以及预训练权重的性能表现与使用注意事项。读完本文,你可以直接复刻tools/train.py训练流程,并准确解读每个配置项与源码模块之间的对应关系。
1. 模型背景:为什么"逐像素分类"不够
configs/maskformer/README.md引用的原始论文为:
Cheng, Bowen, Alex Schwing, and Alexander Kirillov. "Per-pixel classification is not all you need for semantic segmentation." Advances in Neural Information Processing Systems 34 (2021): 17864-17875.
传统语义分割采用逐像素(dense)分类范式,而 MaskFormer 将分割重构为**集合预测(set prediction)**问题:网络输出一组可学习的 queries,每个 query 预测一个"类别 + 二值 mask"的三元组,通过集合间无重复、无遗漏的预测天然处理多实例重叠区域,从而获得更精确的边界与区域划分。PaddleSeg 对这一范式的实现在 paddleseg/models/maskformer.py,损失函数实现在 paddleseg/models/losses/maskformer_loss.py,两者文件头部均注明参考了原始 MaskFormer 仓库的modeling与criterion.py实现。
2. 配置体系:四档规模的 ADE20k 训练配方
configs/maskformer/目录提供 4 份训练配置,全部面向 ADE20k(150 类)数据集、512×512 训练分辨率、160k 迭代:
| 配置文件 | Backbone | 输入窗口 | 说明 | |:-:|:-:|:-:|:-| | maskformer_swin_tiny_ade20k_512x512_160k.yml | SwinTransformer_tiny_patch4_window7_224_maskformer | 7×7 | 基准配方,其余配置以它为_base_| | maskformer_swin_small_ade20k_512x512_160k.yml | SwinTransformer_small_patch4_window7_224_maskformer | 7×7 | 仅替换 backbone 与预训练权重 | | maskformer_swin_base_ade20k_512x512_160k.yml | SwinTransformer_base_patch4_window7_384_maskformer | 7×7 | 以 large 配置为 base | | maskformer_swin_large_ade20k_512x512_160k.yml | SwinTransformer_large_patch4_window7_384_maskformer | 7×7 | 覆盖训练增广为 640×640 裁剪 |
从配置继承关系看:tiny 是完整的"基准配方";small 与 tiny 仅差异在backbone.type和pretrained两个字段;large 额外覆盖了训练集ResizeByShort的短边采样范围(320~1344,max_size: 2560)和RandomPaddingCrop的裁剪尺寸(640×640),因为更大的 backbone 使用 384 预训练尺寸、更高分辨率的训练输入;base 则直接继承 large 的数据配置,只替换 backbone 为 base 变体。
3. 基准配置逐项解析(tiny 配方)
下面以 maskformer_swin_tiny_ade20k_512x512_160k.yml 为蓝本,逐段说明其参数含义与源码支撑。
3.1 数据集与训练增广
batch_size: 4 iters: 160000 train_dataset: type: ADE20K dataset_root: data/ADEChallengeData2016/ transforms: - type: ResizeByShort short_size: [256, 307, 358, 409, 460, 512, 563, 614, 665, 716, 768, 819, 870, 921, 972, 1024] max_size: 2048 - type: RandomPaddingCrop crop_size: [512, 512] - type: RandomDistort brightness_range: 0.125 brightness_prob: 1.0 contrast_range: 0.5 contrast_prob: 1.0 saturation_range: 0.5 saturation_prob: 1.0 hue_range: 18 hue_prob: 1.0 - type: RandomHorizontalFlip - type: GenerateInstanceTargets num_classes: 150 ignore_index: 255 - type: Normalize mean: [0.485, 0.456, 0.406] std: [0.229, 0.224, 0.225]几个关键点:
- 多尺度随机短边采样:
ResizeByShort的short_size是一个离散列表,训练时逐图随机取一个短边尺寸并等比缩放,max_size: 2048用于限制长边上限。这是 Mask 系列 Transformer 分割模型常用的分辨率增广策略。 - 512×512 随机填充裁剪:
RandomPaddingCrop将缩放后的图裁剪到统一尺寸,保证 batch 内张量形状一致。 GenerateInstanceTargets是 MaskFormer 数据流的关键一环。它把稠密语义标注转换为集合预测所需的实例化目标,实现见 paddleseg/transforms/transforms.py:对当前图像中出现的每个类别,生成一个二值 mask(sem_seg_gt == cid),并输出gt_classes(不足 150 个类别时用ignore_index=255补齐)与gt_masks(形状[num_classes, H, W],未出现的类别对应全 0 mask)。这份data['instances']最终被送入损失函数做匈牙利匹配。- 验证集:
ResizeByShort: short_size: 512短边缩放到 512 后同样做 ImageNet 均值/方差归一化,mode: val表示该数据集用于验证。
3.2 模型定义
model: type: MaskFormer num_classes: 150 backbone: type: SwinTransformer_tiny_patch4_window7_224_maskformer pretrained: https://bj.bcebos.com/paddleseg/paddleseg/dygraph/ade20k/maskformer_ade20k_swin_tiny/pretrain/model.pdparamsmodel.type: MaskFormer对应 paddleseg/models/maskformer.py 中通过@manager.MODELS.add_component注册的MaskFormer类,其构造参数与配置字段一一对应:
num_classes:分类头输出维度,ADE20k 为 150;backbone:以嵌套配置动态构建 backbone;pretrained:若指定,init_weight()会调用utils.load_entire_model加载 ImageNet 预训练权重(见 maskformer.py);sem_seg_postprocess_before_inference(默认False):控制推理阶段后处理发生在 mask 插值之前还是语义 logits 之后。
3.3 优化器与学习率
optimizer: type: AdamW weight_decay: 0.01 custom_cfg: - name: backbone lr_mult: 1.0 - name: norm weight_decay_mult: 0.0 - name: relative_position_bias_table weight_decay_mult: 0.0 grad_clip_cfg: name: ClipGradByNorm clip_norm: 0.01 lr_scheduler: type: PolynomialDecay warmup_iters: 1500 warmup_start_lr: 6.0e-11 learning_rate: 6.0e-05 end_lr: 0 power: 0.9这些取值是 Transformer 分割模型的典型超参组合,源码层面值得注意的有两点:
custom_cfg中对norm与relative_position_bias_table关闭权重衰减(weight_decay_mult: 0.0)。从 maskformer.py 中可以看到 Swin backbone 的相对位置偏置表relative_position_bias_table确实是显式参数,对这类偏置/归一化参数不加衰减是社区通行做法;clip_norm: 0.01的梯度裁剪非常激进(数值很小),配合warmup_start_lr: 6.0e-11的近零起点,用于抑制 Transformer 训练早期的梯度爆炸,这与 Mask 系列 Transformer 分割模型的训练惯例一致。
3.4 损失函数
loss: types: - type: MaskFormerLoss num_classes: 150 eos_coef: 0.1 coef: [1]MaskFormerLoss的完整语义在第 5 节展开。配置中eos_coef: 0.1是"空 query(no-object)"类的交叉熵权重;注意MaskFormer模型的loss_computation会将coef[i]乘到损失上(见 maskformer.py),此处置 1 表示不做额外缩放。
4. 模型结构纵深解析
4.1 专用 Swin backbone:输出多尺度特征字典
配置中的 backbone 类型(如SwinTransformer_tiny_patch4_window7_224_maskformer)在 paddleseg/models/backbones/swin_transformer.py 中定义。与普通 Swin 配置(如SwinTransformer_tiny_patch4_window7_224只输出单个 tensor)不同,*_maskformer版本的forward将四个阶段的输出组织为字典:
self._out_features = ["res2", "res3", "res4", "res5"] self._out_feature_strides = {"res2": 4, "res3": 8, "res4": 16, "res5": 32}并配套output_shape()方法返回{name: {channels, stride}}字典——这正是MaskFormer构造MaskFormerHead时传入backbone.output_shape()的接口。以 tiny 为例,embed_dim=96,通道数依次为 96/192/384/768,window_size=7,且使用patch_norm=True。large 变体(base/large 配置)则使用pretrain_img_size=384的对应实现。
4.2 MaskFormerHead:Pixel Decoder + Transformer Predictor
MaskFormerHead 由两部分组成:
self.pixel_decoder = BasePixelDecoder(input_shape) self.predictor = TransformerPredictor( input_shape[transformer_in_feature]["channels"], # 默认 res5 mask_classification=True, num_classes=num_classes)BasePixelDecoder(maskformer.py)是一个 FPN 风格的像素解码器:
- 输入按 stride 排序后,从深到浅逐层上采样融合;每级先经
lateral_convs(1×1 卷积 + GroupNorm)把通道数压到 256,再与上采样的浅层特征相加,过output_convs(3×3 卷积 + GroupNorm + ReLU); - 最深层(res5)没有 lateral 分支(
lateral_convs置None),直接过 output conv; - 最终经
mask_features(3×3 卷积,256→256)输出mask_features,供后续线性组合生成 mask。
TransformerPredictor(maskformer.py)是集合预测的核心:
PositionEmbeddingSine(num_pos_feats=128,normalize=True)为像素特征生成正弦位置编码;- 内部
Transformer采用d_model=256、nhead=8、enc_layers=0、dec_layers=6、dim_feedforward=2048的默认结构——注意encoder 层数为 0,即 backbone 特征投影后直接进入 6 层 decoder,这是语义分割版 MaskFormer 的典型设定; nn.Embedding(num_queries=100, hidden_dim=256)提供 100 个可学习 query,decoder 开启return_intermediate_dec=True(深度监督),每一层 decoder 的输出都会被收集,用于aux_outputs;- 若
res5通道数与 256 不一致,input_proj(1×1 卷积)负责投影到hidden_dim; - 分类头
class_embed输出num_classes + 1 = 151维(多出的最后一维即 no-object/空 query),mask 头mask_embed是 3 层 MLP(256→256→256),最后用paddle.einsum("lbqc,bchw->lbqhw", mask_embed, mask_features)把 query 与像素特征线性组合成每层 decoder 的预测 mask。
4.3 推理阶段:从 query 到稠密语义图
训练时模型直接返回[{"pred_logits":..., "pred_masks":..., "aux_outputs":...}]交给损失函数;推理路径(maskformer.py)则把集合预测还原为逐像素语义 logits:
def semantic_inference(self, mask_cls, mask_pred): mask_cls = F.softmax(mask_cls)[..., :-1] # 去掉 no-object 类 mask_pred = F.sigmoid(mask_pred) semseg = paddle.einsum("qc,qhw->chw", mask_cls, mask_pred) return semseg即对每个 query 先 softmax 取前 150 类概率、sigmoid 激活 mask,再以类别概率为权重对所有 query 的 mask 加权求和,得到C×H×W的软预测,最后经sem_seg_postprocess双线性插值回原图尺寸(含去除 padding 区域的裁切)。源码注释中标注了典型形状:pred_logits为[B, 100, 151],pred_masks为[B, 100, 512, 512]。
5. 损失函数:匈牙利匹配 + 三项代价
MaskFormerLoss(maskformer_loss.py)的核心流程:
- 目标整理:
forward把data['instances']中的gt_classes/gt_masks按图拆分,过滤掉ignore_index=255的补齐项,得到每张图的{labels, masks}。 - 匈牙利匹配:
HungarianMatcher(maskformer_loss.py)对每个 batch 样本计算num_queries × num_targets的代价矩阵:- 分类代价
cost_class = -paddle.gather(out_prob, index=tgt_ids, axis=1)(目标类别的负似然概率); - 掩码代价为批量的
batch_sigmoid_focal_loss与batch_dice_loss; - 最终代价
C = cost_mask*C + cost_class*C + cost_dice*C,其中权重来自HungarianMatcher(cost_class=1, cost_mask=20, cost_dice=1),再交给scipy.optimize.linear_sum_assignment求解 1-1 指派。
- 分类代价
- 三项损失:
loss_ce:被匹配 query 的交叉熵,未匹配 query 的目标类别置为num_classes(即 no-object 类),且通过empty_weight把最后一类的权重压到eos_coef=0.1,抑制空 query 被过度惩罚/奖励;loss_mask:sigmoid focal loss(alpha=0.25, gamma=2);loss_dice:dice loss;- 权重字典固定为
{"loss_ce": 1, "loss_mask": 20, "loss_dice": 1},且 6 层 decoder 的前 5 层aux_outputs各自做一遍匹配与计算,键名带_i后缀,权重与主损失相同(深度监督)。
- 分布式归一化:
num_masks会all_reduce汇总各卡目标数再除以 world size(下限为 1),保证多卡下损失按真实 mask 数平均。
这套"匹配-计算-深度监督"的实现与 PyTorch 原版criterion.py的结构一致(文件头注释已声明参考来源),差异点在于目标来源是GenerateInstanceTargets从稠密标注派生的伪实例集合,因此无需额外的实例标注。
6. 训练、验证与推理命令
PaddleSeg 的通用入口位于 tools/ 目录。以 tiny 配方为例:
# 单卡训练 python tools/train.py --config configs/maskformer/maskformer_swin_tiny_ade20k_512x512_160k.yml # 验证(指定训练产出的权重目录) python tools/val.py --config configs/maskformer/maskformer_swin_tiny_ade20k_512x512_160k.yml \ --slim_model <output_dir>/model_final.pdparams # 推理并可视化 python tools/predict.py --config configs/maskformer/maskformer_swin_tiny_ade20k_512x512_160k.yml \ --slim_model <output_dir>/model_final.pdparams --save_dir output --visual True注意事项:
dataset_root指向data/ADEChallengeData2016/,训练前需按 PaddleSeg 数据规范组织好 ADE20k 的图片与标注文件;- 多卡训练使用
tools/train.py的--gpus参数(如--gpus 0,1,2,3),损失中的num_masks会跨卡归约,无需手动换算 batch 语义; - 推理输出为
sem_seg软预测 logits,semantic_inference已把 no-object 类去掉,softmax/argmax 即可得到 150 类稠密预测。
7. 预训练权重性能与官方注意事项
configs/maskformer/README.md给出的 ADE20k 验证集结果(512×512,160k 迭代):
| Model | Backbone | Resolution | Training Iters | mIoU | mIoU (flip) | mIoU (ms+flip) |
|---|---|---|---|---|---|---|
| Maskformer-tiny | SwinTransformer | 512x512 | 160000 | 47.93 | - | - |
| Maskformer-small | SwinTransformer | 512x512 | 160000 | 50.4 | - | - |
官方 README 同时给出三条重要说明:
- MaskFormer 支持 tiny/small/base/large 四种规格,仓库提供了全部四份配置与(tiny/small 的)预训练权重及训练日志;base 和 large 的训练结果未提供,官方表述为"应当与论文一致"(should be consistent with the paper),即这两档的数值以原论文为准,仓库内不给出实测 mIoU;
- base 与 large 的评测方式与原始代码库一致,采用多尺度(ms)+ 水平翻转(flip)的组合评测,而 tiny/small 表中给出的是单尺度数字,横向对比时需注意评测协议差异;
- 环境要求:请使用 CUDA 11.2 而非 CUDA 10.2,以避免计算 bug。这是该文档明确的适用前提,复现训练前应确认 PaddlePaddle 对应 CUDA 版本的安装。
预训练权重下载链接以https://bj.bcebos.com/paddleseg/dygraph/ade20k/maskformer_ade20k_swin_{tiny,small}为前缀,分别提供model.pdparams(微调后权重,可直接--slim_model加载)与train.log;backbone 的 ImageNet 预训练权重则内嵌在各 yml 的pretrained字段中,训练时自动拉取。
8. 小结与延伸阅读
PaddleSeg 中 MaskFormer 的完整链路可以概括为:
ADE20k 稠密标注 → GenerateInstanceTargets(派生 gt_classes / gt_masks) → SwinTransformer_xxx_maskformer(res2~res5 多尺度字典特征) → BasePixelDecoder(FPN 融合出 mask_features) → TransformerPredictor(100 queries × 6 层 decoder,深度监督) → MaskFormerLoss(匈牙利匹配 + CE(eos_coef=0.1) + focal×20 + dice×1) → 推理时 semantic_inference 还原为稠密语义 logits若需要进一步深入,建议按以下路径阅读源码:模型主干 paddleseg/models/maskformer.py、匹配与损失 paddleseg/models/losses/maskformer_loss.py、maskformer 变体 backbone paddleseg/models/backbones/swin_transformer.py、实例目标构造 paddleseg/transforms/transforms.py,以及四份 ADE20k 配置 configs/maskformer/ 中 tiny 与 large 在数据增广上的差异。
- 人工智能
- 计算机视觉
- 预训练
【免费下载链接】PaddleSeg
Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting, 3D Segmentation, etc.
相关推荐
RTFormer:基于 Transformer 的实时语义分割网络 —— PaddleSeg 配置、训练与源码解析
RTFormer:基于 Transformer 的实时语义分割网络 —— PaddleSeg 配置、训练与源码解析 RTFormer(Real Time Tra
人工智能计算机视觉预训练PaddleSeg PanopticDeepLab 全景分割实战指南:基于 PaddlePaddle 的 Bottom-Up 全景分割实现与 Cityscapes 训练部署
PaddleSeg PanopticDeepLab 全景分割实战指南:基于 PaddlePaddle 的 Bottom Up 全景分割实现与 Cityscape
人工智能计算机视觉预训练基于UNET的图像语义分割训练实现解析
基于UNET的图像语义分割训练实现解析 项目背景与概述 本文解析的是一个使用PyTorch实现UNET架构进行图像语义分割的训练脚本。UNET是一种经典的编码器
示例工程机器学习深度学习教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考