MMSegmentation 中的 ERFNet:高效残差分解卷积实时语义分割实现与配置指南
【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
导读
本文以 MMSegmentation 仓库中 configs/erfnet/README.md 为主线,系统讲解 ERFNet(Efficient Residual Factorized ConvNet)这一面向实时语义分割的高效架构:包括其论文核心思想、在 MMSegmentation 中的源码实现、完整的 Cityscapes 训练配置、实验结果复现要点,以及基于仓库测试用例的验证方法。读完本文,你将掌握如何在 MMSegmentation 中读懂、配置、训练与测试 ERFNet,并理解其"残差连接 + 分解卷积"背后的效率来源。
1. 模型背景:面向智能驾驶的实时语义分割
ERFNet 由 Romera 等人提出,发表于 IEEE Transactions on Intelligent Transportation Systems(2017),核心目标是在嵌入式设备上以实时速度完成高精度像素级语义分割,为智能车辆(Intelligent Vehicles, IVs)的场景理解提供统一方案。
论文摘要指出,当时的 SOTA 分割方法在精度与计算资源之间缺乏良好平衡,难以部署到真实车辆。ERFNet 的核心创新在于提出了一种新型网络层——使用残差连接(residual connections)与分解卷积(factorized convolutions),在保持精度接近 SOTA 的同时将计算量降低数个量级。论文报告在单张 Titan X 上可运行超过 83 FPS,在 Jetson TX1 嵌入式设备上可达 7 FPS。这一效率与精度的权衡使其成为 IV 场景理解的理想方案。
MMSegmentation 将该算法完整实现,包括 backbone(mmseg/models/backbones/erfnet.py)与配套的 Cityscapes 训练配置,模型元数据记录于 configs/erfnet/metafile.yaml。
2. 架构剖析:三大基本模块的源码实现
从 mmseg/models/backbones/erfnet.py 的源码结构看,ERFNet backbone 由三种基本模块组成,对应论文中"分解卷积 + 残差 + 高效下采样/上采样"的设计:
2.1 DownsamplerBlock:下采样块
DownsamplerBlock(erfnet.py#L11-L65)与常规 ConvModule 不同:它将一个 stride=2 的 3×3 卷积与一个 stride=2 的 MaxPool 的输出拼接(concatenate)后再过 BatchNorm 与 ReLU。
关键实现点:
- 卷积输出通道为
out_channels - in_channels,池化保留in_channels通道,拼接后恰好为out_channels; - 池化结果通过
resize(..., mode='bilinear')与卷积输出对齐尺寸。
测试用例 tests/test_models/test_backbones/test_erfnet.py#L120-L127 验证了DownsamplerBlock(16, 64)的 conv 输出为 48 通道(64-16)、BN 参数长度为 64、池化核与步长为 2。
2.2 NonBottleneck1d:非瓶颈一维分解卷积块
NonBottleneck1d(erfnet.py#L68-L145)是 ERFNet 效率的核心:它将标准 3×3 卷积分解为3×1 与 1×3 两个一维卷积,显著减少参数量与计算量,并通过残差连接output = self.act(output + input)保持梯度流通。
实现细节:
- 每个 block 默认包含
num_conv_layer=2组(3×1 → 1×3)卷积对; - 第二组卷积可设置空洞率
dilation(默认 1),用于在不增加参数的情况下扩大感受野; - 第一组后接激活,第二组后接
nn.Dropout(p=drop_rate)(drop_rate默认 0),实现随机深度式的正则化效果。
2.3 UpsamplerBlock:上采样块
UpsamplerBlock(erfnet.py#L148-L191)使用nn.ConvTranspose2d(转置卷积,kernel=3, stride=2, output_padding=1)将特征图尺寸翻倍,随后接 BN 与 ReLU,测试用例验证了其通道变化(如 64→16)。
2.4 ERFNet 主网络:编码器-解码器组装逻辑
ERFNet类(erfnet.py#L194-L329)通过nn.ModuleList组装编码器与解码器:
- 编码器:1 个 DownsamplerBlock(3→16 通道)+ 5 个 NonBottleneck1d(64 通道)+ 1 个 DownsamplerBlock(64→128 通道)+ 8 个**带不同空洞率(2, 4, 8, 16,循环两组)**的 NonBottleneck1d(128 通道);
- 解码器:2 个 UpsamplerBlock(128→64→16 通道),每个上采样后接 2 个 NonBottleneck1d;
- 输出:forward 返回
[x],最终特征图为 16 通道,供后续解码头使用。
构造时有多条assert一致性校验(erfnet.py#L246-L269),例如编码器下采样块数量必须等于解码器上采样块数量 +1、编码器 Non-bottleneck 块数量必须能被空洞率个数整除等。测试用例 tests/test_models/test_backbones/test_erfnet.py#L38-L117 专门构造了 6 种非法参数组合验证这些断言会被触发,保障了配置的正确性。
3. 官方配置全解:erfnet_fcn_4xb4-160k_cityscapes-512x1024
3.1 实验配置总览
仓库提供的唯一官方模型配置为 configs/erfnet/erfnet_fcn_4xb4-160k_cityscapes-512x1024.py,其内容精简,通过继承_base_组装而成:
_base_ = [ '../_base_/models/erfnet_fcn.py', '../_base_/datasets/cityscapes.py', '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' ] crop_size = (512, 1024) data_preprocessor = dict(size=crop_size) model = dict(data_preprocessor=data_preprocessor) train_dataloader = dict(batch_size=4, num_workers=4) val_dataloader = dict(batch_size=1, num_workers=4) test_dataloader = val_dataloader四个基础文件分别定义了模型结构、数据集、运行时与训练计划:
| 基础配置 | 作用 |
|---|---|
| configs/base/models/erfnet_fcn.py | 定义 backbone(ERFNet)与解码头(FCNHead) |
| configs/base/datasets/cityscapes.py | Cityscapes 数据集路径、pipeline 与评估指标 |
| configs/base/default_runtime.py | 日志、可视化、checkpoint 钩子等运行时设置 |
| configs/base/schedules/schedule_160k.py | SGD 优化器与 Poly 学习率策略 |
3.2 模型结构配置详解
configs/base/models/erfnet_fcn.py 中 backbone 各参数与源码构造一一对应:
backbone=dict( type='ERFNet', in_channels=3, # 输入图像通道数(RGB) enc_downsample_channels=(16, 64, 128),# 编码器各级下采样输出通道 enc_stage_non_bottlenecks=(5, 8), # 编码器各级 NonBottleneck1d 数量 enc_non_bottleneck_dilations=(2, 4, 8, 16), # 末级空洞率序列 enc_non_bottleneck_channels=(64, 128),# 编码器各级 NonBottleneck1d 通道数 dec_upsample_channels=(64, 16), # 解码器各级上采样输出通道 dec_stages_non_bottleneck=(2, 2), # 解码器各级 NonBottleneck1d 数量 dec_non_bottleneck_channels=(64, 16), # 解码器各级 NonBottleneck1d 通道数 dropout_ratio=0.1, # NonBottleneck1d 中 Dropout 概率 init_cfg=None)解码头(Decoder Head)的重要设计:README 明确指出,原论文中的最后一个反卷积层被替换为朴素的FCNHead解码头 + 双线性上采样层,实验发现该替换更有效且更高效。对应的 FCNHead 配置为:
decode_head=dict( type='FCNHead', in_channels=16, # 与 backbone 输出的 16 通道特征图匹配 channels=128, num_convs=1, concat_input=False, dropout_ratio=0.1, num_classes=19, # Cityscapes 的 19 类语义类别 norm_cfg=norm_cfg, # SyncBN align_corners=False, loss_decode=dict( type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0))整体模型类型为EncoderDecoder,数据预处理器使用SegDataPreProcessor(ImageNet 均值/方差、BGR→RGB),train_cfg=dict()、test_cfg=dict(mode='whole')表示整图推理模式。
3.3 训练计划与数据增强配置
configs/base/schedules/schedule_160k.py 定义了 160k 迭代训练计划:
optimizer = dict(type='SGD', lr=0.01, momentum=0.9, weight_decay=0.0005) optim_wrapper = dict(type='OptimWrapper', optimizer=optimizer, clip_grad=None) param_scheduler = [ dict(type='PolyLR', eta_min=1e-4, power=0.9, begin=0, end=160000, by_epoch=False) ] train_cfg = dict(type='IterBasedTrainLoop', max_iters=160000, val_interval=16000)- 优化器:SGD(lr=0.01,momentum=0.9,weight_decay=0.0005);
- 学习率:PolyLR 多项式衰减(power=0.9,最低 1e-4),按迭代而非 epoch 调度;
- 每 16000 次迭代验证一次,每 16000 次迭代保存 checkpoint。
数据集侧(configs/base/datasets/cityscapes.py):训练 pipeline 包含RandomResize(scale=(2048,1024),ratio_range=(0.5,2.0))、RandomCrop(crop_size=(512,1024),cat_max_ratio=0.75)、RandomFlip(prob=0.5)与PhotoMetricDistortion;评估使用IoUMetric的mIoU指标。最终配置将训练 batch_size 设为 4(4 卡 × 4 = 16,与 metafile 中 Batch Size: 16 一致),验证/测试 batch_size 为 1。
4. 实验结果与复现要点
4.1 Cityscapes 官方结果
README 的 Results 表格记录了在 Cityscapes 上的完整结果:
| Method | Backbone | Crop Size | Lr schd | Mem (GB) | Inf time (fps) | Device | mIoU | mIoU(ms+flip) |
|---|---|---|---|---|---|---|---|---|
| ERFNet | ERFNet | 512x1024 | 160000 | 6.04 | 15.26 | V100 | 72.5 | 74.75 |
- 训练资源:4× V100 GPU(见 configs/erfnet/metafile.yaml);
- 模型权重与训练日志可从 metafile 中的 Weights / Training log 字段获取;
- 测试时多尺度 + 水平翻转(ms+flip)可将 mIoU 从 72.5 提升至 74.75。
4.2 三条复现注意点(README 原文要点)
- 模型从零训练(trained from scratch):
pretrained=None、init_cfg=None,不使用任何 ImageNet 预训练权重; - 解码器替换:原论文最后一个反卷积层被
FCNHead+ 双线性上采样替代(原因见 3.2 节); - 对随机种子敏感:README 特别强调,模型性能对 seed 值敏感,如需精确复现表格结果,请参考官方日志文件中记录的 seed 设置;更换 seed 可能导致结果与表格不一致。
5. 训练、测试与推理实践
5.1 单机多卡训练
使用仓库提供的 tools/dist_train.sh 启动 4 卡训练:
bash tools/dist_train.sh configs/erfnet/erfnet_fcn_4xb4-160k_cityscapes-512x1024.py 4单卡训练可使用 tools/train.py:
python tools/train.py configs/erfnet/erfnet_fcn_4xb4-160k_cityscapes-512x1024.py训练前需按 Cityscapes 数据集约定将数据放置于data/cityscapes/下(leftImg8bit/与gtFine/目录结构见 configs/base/datasets/cityscapes.py 的data_prefix设置)。
5.2 测试与指标复现
# 多卡测试 bash tools/dist_test.sh configs/erfnet/erfnet_fcn_4xb4-160k_cityscapes-512x1024.py \ /path/to/erfnet_fcn_4x4_512x1024_160k_cityscapes_20220704_162145-dc90157a.pth 4 # 单卡测试 python tools/test.py configs/erfnet/erfnet_fcn_4xb4-160k_cityscapes-512x1024.py \ /path/to/checkpoint.pth测试 pipeline 对图片 Resize 到 (2048, 1024) 后整图推理(test_cfg.mode='whole')。
5.3 单图推理
仓库提供 demo/image_demo.py 进行可视化推理:
python demo/image_demo.py demo/demo.png \ configs/erfnet/erfnet_fcn_4xb4-160k_cityscapes-512x1024.py \ /path/to/checkpoint.pth --out-file result.png6. 源码验证:单元测试如何保障实现正确性
仓库通过 tests/test_models/test_backbones/test_erfnet.py 对 ERFNet 实现进行了系统性验证:
- 标准前向测试:以
(2, 3, 256, 512)输入,断言 backbone 输出形状为(2, 16, 128, 256)——即 16 通道、空间尺寸缩小 4 倍,与解码头in_channels=16严格匹配;同时测试非规整输入尺寸(2, 3, 527, 279)也能正常前向; - 模块级测试:逐一验证 DownsamplerBlock 的卷积/池化通道数、NonBottleneck1d 的四组分解卷积通道与 dropout 概率、UpsamplerBlock 的转置卷积通道;
- 非法参数断言测试:覆盖编码器/解码器通道数、block 数量、空洞率整除性等 6 类不一致配置,确保构造期即能发现配置错误。
这些测试共同构成了"配置参数 → 网络结构 → 输出形状"的闭环证据链:任何对通道元组或 block 数量的误配,要么在构造阶段被 assert 拦截,要么在前向阶段输出形状与解码头失配而报错。
7. 结语
ERFNet 展示了"残差连接 + 分解卷积 + 高效上采样"这一组合在实时语义分割上的巨大潜力。在 MMSegmentation 中,其实现被组织为可插拔的 backbone(mmseg/models/backbones/erfnet.py)与模块化配置(configs/erfnet/),配合完整的测试用例与 Cityscapes 基准结果,既便于研究者复现论文结论,也便于在自定义数据集上调整通道数、空洞率、Dropout 等超参快速验证想法。对于嵌入式与自动驾驶场景的落地需求,ERFNet 是一个兼具精度与速度的可靠基线。
参考文献
@article{romera2017erfnet, title={Erfnet: Efficient residual factorized convnet for real-time semantic segmentation}, author={Romera, Eduardo and Alvarez, Jos{\'e} M and Bergasa, Luis M and Arroyo, Roberto}, journal={IEEE Transactions on Intelligent Transportation Systems}, volume={19}, number={1}, pages={263--272}, year={2017}, publisher={IEEE} }【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考