news 2026/9/10 20:06:46

Detectron2 中的 DeepLabV3 / DeepLabV3+ 语义分割实战指南:Cityscapes 训练、评估与源码解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Detectron2 中的 DeepLabV3 / DeepLabV3+ 语义分割实战指南:Cityscapes 训练、评估与源码解析

Detectron2 中的 DeepLabV3 / DeepLabV3+ 语义分割实战指南:Cityscapes 训练、评估与源码解析

【免费下载链接】detectron2Detectron2 is a platform for object detection, segmentation and other visual recognition tasks.项目地址: https://gitcode.com/GitHub_Trending/de/detectron2

本指南围绕 projects/DeepLab/README.md 展开,系统讲解如何在 Detectron2 项目中复现并应用 DeepLabV3 与 DeepLabV3+ 语义分割模型,涵盖环境安装、8 卡分布式训练、模型评估、Cityscapes 官方结果复现,以及从配置到源码的逐层剖析。读完本文,你将掌握基于 ResNet-103-DC5 主干、ASPP 空洞卷积、深度可分离卷积与 poly 学习率调度在 Detectron2 中训练语义分割模型的完整链路,并能独立修改配置迁移到自己的分割数据集。

一、项目定位:Detectron2 中的 DeepLab 实现

Detectron2 官方仓库以projects/目录承载研究级模型实现,DeepLab 正是其中之一。projects/DeepLab在 Detectron2 的建模框架内完整实现了 DeepLabV3 与 DeepLabV3+ 两种语义分割架构,其核心组件分布在:

  • 语义分割头定义:DeepLabV3HeadDeepLabV3PlusHead
  • DeepLab 专用 ResNet 主干:DeepLabStembuild_resnet_deeplab_backbone
  • 损失函数:DeepLabCE(hard pixel mining 交叉熵)
  • 学习率调度 与 求解器构建:WarmupPolyLR
  • 配置扩展:add_deeplab_config
  • 训练/评估入口:Trainer

从入口模块 deeplab/init.py 可以看到,该包对外暴露的接口即为上述add_deeplab_configbuild_lr_schedulerbuild_resnet_deeplab_backboneDeepLabV3HeadDeepLabV3PlusHead,是接入 Detectron2 训练管线的最小组合。

二、环境安装

DeepLab 项目运行在 Detectron2 之上,因此首先需要安装 Detectron2 本体(官方安装说明见 INSTALL.md,Linux 下编译 C++/CUDA 扩展的细节可参考 detectron2/layers/csrc/README.md)。

# 安装 detectron2(以源码方式编译,DeepLab 依赖其 CUDA 扩展如 SyncBN) python -m pip install -e .

安装完成后,无需额外安装独立包——projects/DeepLab下的 Python 代码通过detectron2.projects.deeplab命名空间被导入(见 train_net.py 中的from detectron2.projects.deeplab import add_deeplab_config, build_lr_scheduler),因此工作区根目录必须保持为 detectron2 仓库根目录,以保证包路径可解析。

三、模型训练:8 卡分布式启动命令

README 给出的训练命令如下,进入项目目录后直接以配置文件启动:

cd /path/to/detectron2/projects/DeepLab python train_net.py --config-file configs/Cityscapes-SemanticSegmentation/deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml --num-gpus 8

对该命令逐段拆解:

  • --config-file:指定完整配置文件,此处为 deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml。文件名各段含义:R_103(R-103 主干,即改进型 ResNet-101)、os16(encoder 输出 stride 为 16)、mg124(res5 multi-grid 为 [1, 2, 4])、poly(poly 学习率)、90k(90,000 次迭代)、bs16(batch size 16)。
  • --num-gpus 8:使用 8 块 GPU 做分布式数据并行训练,配合--num-machines--machine-rank--dist-url可扩展到多机。

3.1 训练入口的内部逻辑

train_net.py 的setup()函数展示了配置装配顺序,这对自定义配置至关重要:

cfg = get_cfg() add_deeplab_config(cfg) # 注入 DeepLab 专用配置项(ASPP、stem、poly 等) cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) # 支持命令行覆盖 cfg.freeze() default_setup(cfg, args)

即:先调用add_deeplab_config注册 DeepLab 新增的配置字段(否则cfg不认识ASPP_DILATIONS等键),再合并 YAML 文件与命令行覆盖项。main()在非 eval 模式下创建Trainer并调用trainer.train()launch()负责根据num_gpus自动拉起多进程训练。

3.2 训练数据增强管线

与 Detectron2 通用检测/分割任务不同,语义分割训练需要"裁剪 + 类别面积约束"的增强组合。Trainer.build_train_loader针对SemanticSegmentor架构调用了自定义的build_sem_seg_train_aug(train_net.py):

  1. T.ResizeShortestEdge:按INPUT.MIN_SIZE_TRAIN((512, 768, 1024, 1280, 1536, 1792, 2048) 中随机 choice)缩放到边,限制最大边MAX_SIZE_TRAIN=4096
  2. T.RandomCrop_CategoryAreaConstraint:若INPUT.CROP.ENABLED=True,执行absolute模式的 (512, 1024) 随机裁剪,并约束裁剪区域内单一类别占比不超过SINGLE_CATEGORY_MAX_AREA=1.0(见 deeplab/config.py 的注释:反复重试裁剪,直到没有任何一个 GT 类别在裁剪区域中占比超过该阈值,避免大类别主导训练);
  3. T.RandomFlip:随机水平翻转。

四、模型评估

评估与训练共用同一入口,只需追加--eval-only并指定权重路径:

cd /path/to/detectron2/projects/DeepLab python train_net.py --config-file configs/Cityscapes-SemanticSegmentation/deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml --eval-only MODEL.WEIGHTS /path/to/model_checkpoint

--eval-only使main()走评估分支:构建模型 → 通过DetectionCheckpointer加载MODEL.WEIGHTS→ 调用Trainer.test(cfg, model)(train_net.py)。

评估器由Trainer.build_evaluator按数据集的evaluator_type元数据自动选择(train_net.py):

  • sem_segSemSegEvaluator(通用语义分割评估,输出到OUTPUT_DIR/inference);
  • cityscapes_sem_segCityscapesSemSegEvaluator(Cityscapes 官方评估脚本,对 19 类细粒度标注计算 mIoU,忽略 ignore 区域)。

推理时,分割头输出的 logits 通过双线性插值上采样common_stride倍回到原图分辨率(见下文forward分析),因此--eval-only命令中的MODEL.WEIGHTS指向任何通过DetectionCheckpointer序列化的 checkpoint 即可。

五、Cityscapes 语义分割结果复现表

README 中给出了使用 ImageNet 预训练初始化的 Cityscapes 模型基准结果,全部以 1024×2048 输出分辨率在 Cityscapes val 集上评估:

方法主干输出分辨率mIoUmodel id下载
DeepLabV3R101-DC51024×204876.7--
DeepLabV3R103-DC51024×204878.528041665model / metrics
DeepLabV3+R101-DC51024×204878.1--
DeepLabV3+R103-DC51024×204880.028054032model / metrics

其中 model id 对应训练实验目录名,下载链接指向dl.fbaipublicfiles.com的模型权重与metrics.json训练日志(weights 与 metrics 文件在运行时可通过DetectionCheckpointer加载或直接查看评估曲线)。需要说明:

  • R103:并非标准的 ResNet-103,而是将 ResNet-101 的第一个 7×7 卷积替换为 3 个 3×3 卷积(感受野不变、参数量略增、非线性增强)的变体,该修改在多数语义分割论文中被采用,并在 ImageNet 上使用 PyTorch examples 的默认配方预训练;
  • DC5:表示在res5阶段使用空洞(dilated)卷积,使特征图 stride 由 32 降为 16(os16),从而保留更高分辨率的空间信息;
  • 上述 mIoU 数据直接取自 README 表格,属于官方发布结果,在实际复现时受随机种子、GPU 型号与数值精度影响可能产生小幅浮动。

六、配置深度解析:从 Base 到模型专属配置

6.1 基础配置 Base-DeepLabV3-OS16-Semantic.yaml

该文件继承自仓库级基础配置 configs/Base-RCNN-DilatedC5.yaml(提供 PIXEL_MEAN/STD、SyncBN 等通用项),并声明了语义分割的默认骨架:

MODEL: META_ARCHITECTURE: "SemanticSegmentor" BACKBONE: FREEZE_AT: 0 SEM_SEG_HEAD: NAME: "DeepLabV3Head" IN_FEATURES: ["res5"] ASPP_CHANNELS: 256 ASPP_DILATIONS: [6, 12, 18] ASPP_DROPOUT: 0.1 CONVS_DIM: 256 COMMON_STRIDE: 16 NUM_CLASSES: 19 LOSS_TYPE: "hard_pixel_mining" DATASETS: TRAIN: ("cityscapes_fine_sem_seg_train",) TEST: ("cityscapes_fine_sem_seg_val",) SOLVER: BASE_LR: 0.01 MAX_ITER: 90000 LR_SCHEDULER_NAME: "WarmupPolyLR" IMS_PER_BATCH: 16 INPUT: MIN_SIZE_TRAIN: (512, 768, 1024, 1280, 1536, 1792, 2048) MIN_SIZE_TRAIN_SAMPLING: "choice" MIN_SIZE_TEST: 1024 MAX_SIZE_TRAIN: 4096 MAX_SIZE_TEST: 2048 CROP: ENABLED: True TYPE: "absolute" SIZE: (512, 1024) SINGLE_CATEGORY_MAX_AREA: 1.0 DATALOADER: NUM_WORKERS: 10

关键参数说明:

配置项默认值作用
MODEL.SEM_SEG_HEAD.ASPP_CHANNELS256ASPP 各分支输出通道数
MODEL.SEM_SEG_HEAD.ASPP_DILATIONS[6, 12, 18]ASPP 中三个空洞卷积的 dilation 系数
MODEL.SEM_SEG_HEAD.ASPP_DROPOUT0.1ASPP 输出上的 dropout 比例
MODEL.SEM_SEG_HEAD.COMMON_STRIDE16输出相对于输入的下采样倍数(os16)
MODEL.SEM_SEG_HEAD.NUM_CLASSES19Cityscapes 细粒度类别数
MODEL.SEM_SEG_HEAD.LOSS_TYPEhard_pixel_mining损失类型,可选cross_entropyhard_pixel_mining
SOLVER.LR_SCHEDULER_NAMEWarmupPolyLRpoly 学习率调度器(DeepLab 特有)
INPUT.CROP.SINGLE_CATEGORY_MAX_AREA1.0单类别在裁剪区域的最大面积占比约束

6.2 DeepLabV3+ 专属配置 deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml

_BASE_: Base-DeepLabV3-OS16-Semantic.yaml MODEL: WEIGHTS: "detectron2://DeepLab/R-103.pkl" PIXEL_MEAN: [123.675, 116.280, 103.530] PIXEL_STD: [58.395, 57.120, 57.375] BACKBONE: NAME: "build_resnet_deeplab_backbone" RESNETS: DEPTH: 101 NORM: "SyncBN" OUT_FEATURES: ["res2", "res5"] RES5_MULTI_GRID: [1, 2, 4] STEM_TYPE: "deeplab" STEM_OUT_CHANNELS: 128 STRIDE_IN_1X1: False SEM_SEG_HEAD: NAME: "DeepLabV3PlusHead" IN_FEATURES: ["res2", "res5"] PROJECT_FEATURES: ["res2"] PROJECT_CHANNELS: [48] NORM: "SyncBN" COMMON_STRIDE: 4 INPUT: FORMAT: "RGB"

与 DeepLabV3 配置(deeplab_v3_R_103_os16_mg124_poly_90k_bs16.yaml)相比,V3+ 的关键差异:

  • 多级特征输入OUT_FEATURES: ["res2", "res5"],低层res2(stride 4)提供高分辨率细节,高层res5输入 ASPP 提供语义信息;
  • Decoder 通道投影PROJECT_FEATURES: ["res2"]PROJECT_CHANNELS: [48],将 res2 通过 1×1 卷积压缩到 48 通道,再与上采样后的 ASPP 输出拼接;
  • COMMON_STRIDE 降为 4:DeepLabV3+ 的 encoder-decoder 结构输出 stride 从 16 降到 4,直接输出 4 倍下采样的 logits,在推理时仅需上采样 4 倍即可回到原图;
  • DeepLab StemSTEM_TYPE: "deeplab"STEM_OUT_CHANNELS: 128,将标准 7×7 stride 2 卷积替换为 3 个 3×3 卷积(stride 2/1/1),输出通道扩展到 128;
  • STRIDE_IN_1X1: False:在 res5 空洞阶段,下采样发生在 3×3 卷积而非 1×1 卷积,这是空洞分割标准的stride_in_1x1=False设定。

6.3 add_deeplab_config:新配置项从哪来

DeepLab 使用的许多配置项(ASPP_*POLY_LR_*PROJECT_*STEM_TYPERES5_MULTI_GRID等)并非 Detectron2 内置,而是由 deeplab/config.py 中的add_deeplab_config动态注入:

cfg.SOLVER.POLY_LR_POWER = 0.9 # poly 学习率指数 cfg.SOLVER.POLY_LR_CONSTANT_ENDING = 0.0 # 尾部恒定学习率(0 表示关闭) cfg.MODEL.SEM_SEG_HEAD.LOSS_TYPE = "hard_pixel_mining" cfg.MODEL.SEM_SEG_HEAD.PROJECT_FEATURES = ["res2"] cfg.MODEL.SEM_SEG_HEAD.PROJECT_CHANNELS = [48] cfg.MODEL.SEM_SEG_HEAD.ASPP_CHANNELS = 256 cfg.MODEL.SEM_SEG_HEAD.ASPP_DILATIONS = [6, 12, 18] cfg.MODEL.SEM_SEG_HEAD.ASPP_DROPOUT = 0.1 cfg.MODEL.SEM_SEG_HEAD.USE_DEPTHWISE_SEPARABLE_CONV = False cfg.MODEL.RESNETS.RES4_DILATION = 1 cfg.MODEL.RESNETS.RES5_MULTI_GRID = [1, 2, 4] cfg.MODEL.RESNETS.STEM_TYPE = "deeplab"

这是接入任何 Detectron2 训练脚本(如tools/plain_train_net.py)前必须调用的注册步骤——漏掉它会导致cfg.merge_from_file因未知字段而报错。

七、源码级原理剖析

7.1 DeepLabV3+ 分割头:decoder 逐级融合

DeepLabV3PlusHead 注册于SEM_SEG_HEADS_REGISTRY,其核心layers()方法自高到低分辨率反向遍历in_features(代码注释为 "Reverse feature maps into top-down order"):

  1. 对每个特征f先做project_conv(res2 为 1×1 投影到 48 通道;res5 为 ASPP 模块);
  2. 将上一级(低分辨率)输出y双线性上采样到当前特征分辨率,与投影特征拼接;
  3. 拼接结果经fuse_conv融合——默认是两层 3×3 卷积(semantic_seg.py),若开启USE_DEPTHWISE_SEPARABLE_CONV,则按 Panoptic-DeepLab 的建议用单个 5×5 深度可分离卷积替代两层 3×3 卷积(两者感受野相同,见代码注释);
  4. 最后predictor(1×1 卷积)输出num_classes通道的 logits。

forward()中训练与推理行为分离(semantic_seg.py):训练时返回(None, {"loss_sem_seg": ...}),推理时对 logits 做scale_factor=common_stride的双线性上采样后返回(C×H×W logits, {})

from_config中还隐藏一个细节:当开启裁剪训练(INPUT.CROP.ENABLED)时,若裁剪尺寸不能被 encoder stride 整除会直接抛出ValueError;同时 ASPP 的 image pooling 分支会使用train_h // encoder_stride作为全局平均池化的 kernel size,这解释了为何 Cityscapes 配置固定裁剪为 (512, 1024) 且 stride 为 16/4。

7.2 DeepLabV3 分割头:单特征 + ASPP

DeepLabV3Head 结构更简洁,断言len(in_features) == 1:取单一高层特征(默认res5)→ ASPP → 1×1 predictor → 上采样common_stride(16)倍。它没有 decoder 与低层特征融合,因此CONVS_DIM=256直接作为 ASPP 输出通道并被 predictor 消费。

7.3 DeepLabCE:hard pixel mining 损失

LOSS_TYPE: "hard_pixel_mining"对应 loss.py 中的DeepLabCE,其实现逻辑为:

  1. 先用reduction="none"的交叉熵计算每个像素的损失;
  2. 取前top_k_percent_pixels(默认 0.2,即最难的 20%)像素的损失做torch.topk
  3. 对这批最难像素的损失求均值作为最终 loss。

该策略来自 TensorFlow DeepLab 框架与 DeeperLab 论文,作用是让训练聚焦于难分类像素(如物体边缘、小目标),两个分割头在构造损失时均调用DeepLabCE(ignore_label=self.ignore_value, top_k_percent_pixels=0.2)。若希望使用标准交叉熵,只需将LOSS_TYPE改为cross_entropy

7.4 DeepLabStem:改进的 ResNet 主干

resnet.py 中的DeepLabStem将标准BasicStem的 7×7 stride 2 卷积替换为3×3(stride 2) → 3×3 → 3×3三段结构,每段后接 ReLU,最后接 3×3 stride 2 max-pool,输出 128 通道。build_resnet_deeplab_backbone通过STEM_TYPEbasic/deeplab间切换,并支持RES5_MULTI_GRID:在 res5 阶段以dilation_per_block = [dilation * mg for mg in res5_multi_grid]逐 block 设置空洞率(即 [1, 2, 4] × 2 = 2/4/8),实现 multi-grid 空洞卷积。res4_dilation=1res5_dilation=2的组合配合OUT_FEATURES: ["res2", "res5"],正是os16(res5 输出 stride 16)的由来。

7.5 WarmupPolyLR:poly 学习率调度

DeepLab 训练不使用 Detectron2 默认的多步衰减,而是 lr_scheduler.py 中的WarmupPolyLR,其学习率公式为:

lr = base_lr × warmup_factor × (1 - iter / max_iters)^power
  • power = 0.9POLY_LR_POWER),学习率随迭代平滑衰减到 0;
  • warmup_iters轮执行线性 warmup(默认因子 0.001);
  • 若设置POLY_LR_CONSTANT_ENDING > 0,当衰减值低于该阈值时学习率恒定保持为base_lr × constant_ending,避免尾部衰减过慢。

调度器由 build_solver.py 的build_lr_scheduler根据SOLVER.LR_SCHEDULER_NAME == "WarmupPolyLR"路由创建,并被Trainer.build_lr_scheduler接入 Detectron2 训练循环。

八、扩展到自定义数据集

若要在自己的分割数据集上使用本实现,需调整以下配置(均可用--opts命令行覆盖,无需改代码):

  1. 数据集注册:参考 detectron2/data/datasets/builtin.py 与 cityscapes.py 注册"xxx_sem_seg_train"/"xxx_sem_seg_val",并在 DATASETS 中替换TRAIN/TEST
  2. 类别数MODEL.SEM_SEG_HEAD.NUM_CLASSES改为实际类别数(背景计入则 +1);
  3. 忽略值MODEL.SEM_SEG_HEAD.IGNORE_VALUE默认 -1,数据集中若有 ignore 区域需对应设置;
  4. 裁剪与增强INPUT.CROP.SIZE必须能被COMMON_STRIDE整除(DeepLabV3 为 16、DeepLabV3+ 为 4),否则from_config会抛ValueError
  5. 预训练MODEL.WEIGHTS可替换为 detectron2:// 的 ImageNet 权重或其他 checkpoint,DetectionCheckpointer会自动做兼容加载。

九、引用 DeepLab

若在研究中使用了本实现,请按如下 BibTeX 引用原始论文:

DeepLabv3+(Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation,ECCV 2018):

@inproceedings{deeplabv3plus2018, title={Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation}, author={Liang-Chieh Chen and Yukun Zhu and George Papandreou and Florian Schroff and Hartwig Adam}, booktitle={ECCV}, year={2018} }

DeepLabv3(Rethinking atrous convolution for semantic image segmentation):

@article{deeplabv32018, title={Rethinking atrous convolution for semantic image segmentation}, author={Chen, Liang-Chieh and Papandreou, George and Schroff, Florian and Adam, Hartwig}, journal={arXiv:1706.05587}, year={2017} }

十、小结

projects/DeepLab在 Detectron2 框架内提供了开箱即用的 DeepLabV3/V3+ 语义分割方案:通过add_deeplab_config注入 ASPP、DeepLabStem、multi-grid、poly 学习率等专属配置,通过train_net.py一键完成分布式训练与 Cityscapes 评估,并在 Cityscapes val 上以 R103-DC5 主干取得 DeepLabV3 78.5 mIoU、DeepLabV3+ 80.0 mIoU 的官方结果。结合本文的配置拆解与源码剖析,你可以快速复现官方实验,或将这套 encoder-decoder + 空洞卷积 + hard pixel mining 的组合迁移到自定义语义分割任务中。

【免费下载链接】detectron2Detectron2 is a platform for object detection, segmentation and other visual recognition tasks.项目地址: https://gitcode.com/GitHub_Trending/de/detectron2

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 20:04:44

动态状态估计中的EKF与UKF对比:从原理到Matlab仿真

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:01:39

AI驱动的元数据补全:让数据自动填空与自我表达

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 19:59:12

现在口碑好的AI论文写作工具有哪些品牌?学生党亲测反馈

每到期末、毕业答辩、课题申报阶段,很多学生都会陷入论文写作的困境:选题毫无头绪、大纲搭建逻辑混乱、正文撰写耗时长、参考文献格式出错、查重重复率偏高、AIGC检测告警、本校论文排版标准复杂。依靠纯人工从零开始撰写,反复修改格式和降重…

作者头像 李华