DeepLabv3+语义分割代码解析
1.Pascal VOC 2012
Pascal VOC (Visual Object Classes) 2012 数据集是计算机视觉领域具有里程碑意义的公开基准数据集,以其全面性、高质量标注和在众多任务上的广泛应用而著称,被广泛用于模型训练、评估与比较研究,尤其作为图像分类、目标检测和语义分割等核心任务的经典基准。
1. 核心特性:多任务基准
Pascal VOC 2012 的核心价值在于其多任务性。它并非针对单一任务设计,而是为多种计算机视觉任务提供了丰富且一致的标注:
- 图像分类 (Image Classification): 判断图像中存在的物体类别(20类)。
- 目标检测 (Object Detection): 定位并识别图像中的目标物体,提供物体的边界框 (Bounding Boxes) 和类别标签。
- 语义分割 (Semantic Segmentation): 为图像中的每一个像素分配类别标签(包含20类物体和背景)。这也是本文聚焦的核心任务。
- 其他任务:如动作识别 (Action Recognition) 等。
丰富的标注(类别标签、边界框、像素级分割掩码)使其成为评估模型在多种视觉理解能力上的通用性强基准。
2. 数据组成与目录结构
数据集解压后几个文件夹分别作用:
- JPEGImages/:存储数据集所有原始
.jpg
格式图像文件,内容涵盖包含20类目标的多样化真实世界场景。 - Annotations/: 存储 XML格式 的目标检测标注文件。每个图像对应一个
.xml
文件,详细记录其包含物体的类别、边界框坐标 (如 xmin, ymin, xmax, ymax) 以及其他属性(如是否截断、是否困难样本等)。 - SegmentationClass/: 存储标准的像素级语义分割标注图(伪彩色图,每个像素值对应预设类别)。
- SegmentationClassAug/ (关键): 存储语义分割任务的增强版标签(由第三方基于原始数据扩展)。本文将使用此目录下的标注进行训练,因为它提供了比原始
SegmentationClass
更多的标注图像。 - ImageSets/: 包含划分不同任务的图像列表:
- ImageSets/Main/:图像分类任务的训练/验证集列表(按类别划分)。
- ImageSets/Segmentation/: (本文使用) 语义分割任务的
train.txt
,val.txt
和trainval.txt
文件,列出用于训练和验证的图像文件名(不含扩展名)。 - 其他任务对应目录:如
Layout/
,Action/
等。
- 其他目录:包含其他任务(非本文重点)的特定数据或标注。
3. 数据集划分与使用**
- 标准划分: 数据集一般会明确划分为训练集 (train)、验证集 (val) 和测试集 (test)。
- 本地训练与验证: 在本地进行模型训练和调优时,仅可使用训练集 (
train
) 和验证集 (val
) 或其合并集 (trainval
) 以及对应标注 (Annotations
,SegmentationClassAug
)。 - 测试集评估 (重要限制): Pascal VOC 2012 官方未公开测试集的真实标签 (Ground Truth)。对最终模型在测试集上的性能评估,必须将模型的预测结果提交至官方评测服务器,由其使用私有的测试标注进行计算并反馈评估指标(如语义分割的 mIoU)。
4.语义分割任务目标与示例
本文的核心任务是语义分割。目标是训练一个模型,使其能为输入图像的每一个像素预测正确的类别标签(如“飞机”、“鸟”、“背景”等)。好的语义分割模型能够精确识别图像中不同物体的轮廓,并将属于同一语义类别的区域(无论实例数量)分割出来。如下图所示,模型输出应清晰划分不同对象区域(如飞机、天空、地面),并生成高质量的分割掩码。
2.参数解析与数据处理
1.参数说明
main.py/get_argparser
中的各个参数主要用于配置 DeepLabV3+ 模型的训练和测试过程,也顺便可以看看整个工程支持哪些功能:
1.数据集相关参数 (Dataset Options)
1 | parser.add_argument("--data_root", type=str, default='./datasets/data', |
2.DeepLab模型相关参数 (Deeplab Options)
1 | parser.add_argument("--model", type=str, default='deeplabv3plus_mobilenet', |
3.训练相关参数 (Train Options)
1 | parser.add_argument("--test_only", action='store_true', default=False, |
4. 检查点相关参数
1 | parser.add_argument("--ckpt", default=None, type=str, |
5.损失函数和优化器参数
1 | parser.add_argument("--loss_type", type=str, default='cross_entropy', |
6. 硬件和随机种子参数
1 | parser.add_argument("--gpu_id", type=str, default='0', |
7. 日志和验证相关参数
1 | parser.add_argument("--print_interval", type=int, default=10, |
8. PASCAL VOC特定参数
1 | parser.add_argument("--year", type=str, default='2012', |
9.可视化相关参数
1 | parser.add_argument("--enable_vis", action='store_true', default=False, |
2.数据处理
以 VOC 数据集为例,我们主要关注以下几个方法:
1.数据读取
1.PASCAL VOC数据集读取
1 | class VOCSegmentation(data.Dataset): |
2.数据读取的核心方法
1 | def __getitem__(self, index): |
2.数据增强和预处理
数据增强通过ExtCompose组合多个转换操作:
1 | train_transform = et.ExtCompose([ |
3.构建 DataLoader
在main.py中,使用DataLoader来批量加载数据:
1 | train_loader = data.DataLoader( |
3.核心架构设计
1.模型构建
1 | # Set up model |
2.模型定义
1.基础模型
1 | class _SimpleSegmentationModel(nn.Module): |
初始化模型的两个核心组件:
backbone
:负责提取图像特征的主干网络(如 ResNet、MobileNet)classifier
:负责将特征图转换为分割结果的分类头(如 DeepLab 的 ASPP 模块)
前向传播 (forward)步骤解析**:
- 保存输入尺寸:
x.shape[-2:]
获取输入张量的最后两个维度(即图像的高度H
和宽度W
)。- 例如,输入
x
的形状为(B, C, H, W)
,则input_shape = (H, W)
。
- 特征提取:
features = self.backbone(x)
:通过主干网络提取多级特征。- 对于 DeepLabv3+,
backbone
可能返回一个字典,包含深层特征(out
)和浅层特征(low_level
)。 - 对于 DeepLabv3,可能直接返回最后一层的特征图。
- 对于 DeepLabv3+,
- 分类头处理:
x = self.classifier(features)
:将特征转换为分割逻辑图(logits)。- 输出形状通常为
(B, num_classes, h, w)
,其中h
和w
是特征图的尺寸(小于输入尺寸)。
- 输出形状通常为
- 上采样恢复分辨率:
F.interpolate
:使用双线性插值将分割图上采样到输入图像尺寸size=input_shape
:目标尺寸(原始图像的 H 和 W)mode='bilinear'
:插值方式(双线性插值适合分割任务)align_corners=False
:保持与其他框架(如 TensorFlow)的兼容性
2.DeepLabV3+模型类
1 | class DeepLabV3(_SimpleSegmentationModel): |
DeepLabV3
类继承自_SimpleSegmentationModel
类,它通过继承获得了所有必要的功能,不需要额外添加新的方法或属性。
3.模型组件
1.骨干网络
支持两种骨干网络:
1.ResNet系列
创建一个基于ResNet的语义分割模型
1 | def _segm_resnet(name, backbone_name, num_classes, output_stride, pretrained_backbone): |
2.MobileNetV2
基于MobileNetV2构建DeepLabv3或DeepLabv3+模型
1 | def _segm_mobilenet(name, backbone_name, num_classes, output_stride, pretrained_backbone): |
2.解码器头(Decoder Head)
DeepLabV3+的解码头模块,包含ASPP模块和多级特征融合
1 | class DeepLabHeadV3Plus(nn.Module): |
3.ASPP模块
ASPP模块通过并行多分支卷积捕获多尺度上下文信息
1 | class ASPP(nn.Module): |
4.训练策略
1.学习率调整策略
在utils.py中实现了两种学习率调整策略:
1.多项式衰减(Poly)
特点:
- 控制平滑,学习率下降自然
- 对于复杂任务(如语义分割)训练更稳定
- 参数少(只需 max_iters 和 power),易于使用
1 | class PolyLR(_LRScheduler): |
2.步进式衰减(Step)
StepLR 是一种“阶梯状”地调整学习率的方法,每隔固定的步数将学习率缩小(乘以 gamma),是一种简洁且有效的学习率下降策略。
1 | class StepLR(_LRScheduler): |
2.优化器配置
在main.py中配置优化器:
1 | # 创建优化器:按模块设置不同学习率(用于迁移学习/微调) |
3.训练循环实现
在main.py中的训练循环:
1 | def main(): |
4. 损失函数选择
支持的损失函数:
1 | # 损失函数选择 |
5.评估与可视化
1.评估函数
评估函数实现:
1 | def val_epoch(model, loader, criterion, device, opts): |
2.评估指标计算
1 | class AverageMeter: |
3.可视化
1 | class Visualizer: |
4.训练过程可视化
1 | def train_epoch(model, loader, criterion, optimizer, device, epoch, opts): |
6.总结
1.Pascal VOC 2012 数据集
- 多任务基准:支持分类、检测、分割(像素级标注)
- 数据组成:JPEGImages(原始图像)、Annotations(边界框)、SegmentationClass(分割标签)
- 评估限制:测试集标签不公开,需提交官方服务器计算指标(如 mIoU)
2.DeepLabV3+ 模型设计
- 骨干网络:支持 ResNet 和 MobileNetV2,适应不同计算需求
- ASPP 模块:多尺度空洞卷积,捕获上下文信息
- 特征融合:结合深层语义特征(高层)与浅层细节(低层)
3.训练与优化
- 学习率策略:多项式衰减(PolyLR)或步进衰减(StepLR)
- 损失函数:交叉熵或 Focal Loss(处理类别不平衡)
- 优化器:SGD,分层设置学习率(骨干网络更低)
4.评估与可视化
- 指标计算:mIoU、像素准确率、混淆矩阵
- 可视化工具:展示输入图像、真实标签、预测结果及训练曲线
7.备注
工程地址:https://github.com/VainF/DeepLabV3Plus-Pytorch
Pascal VOC (Visual Object Classes) 2012数据集:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/