Cityscapes数据集上的SOTA模型实战:从数据预处理到模型调优全流程解析

1次阅读
没有评论

共计 2436 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

背景介绍

Cityscapes 是自动驾驶领域广泛使用的语义分割数据集,包含 5000 张精细标注的城市街景图像(2975 训练,500 验证,1525 测试),覆盖 19 类常见物体如道路、车辆、行人等。其特点包括:

Cityscapes 数据集上的 SOTA 模型实战:从数据预处理到模型调优全流程解析

  • 高分辨率(2048×1024)带来细节保留优势,但显存消耗大
  • 标注包含group(如交通标志)和instance(如车辆)两个层级
  • 使用 mIoU(平均交并比)作为核心指标,计算各类预测区域与真实标注的重合度均值

数据预处理

标注文件解析

Cityscapes 使用 JSON 格式存储多边形标注,推荐使用官方 cityscapesscripts 工具包处理:

from cityscapesscripts.helpers.labels import trainId2label

# 转换原始标签 ID 为训练用的 19 类 ID(0-18)def convert_label(label_map):
    for label in trainId2label.values():
        label_map[label_map == label.id] = label.trainId
    return label_map

数据增强策略

高分辨率图像需谨慎选择增强方式,典型组合:

  1. 随机水平翻转(p=0.5)
  2. 随机缩放(0.5-2.0 范围)
  3. 颜色抖动(亮度 0.1, 对比度 0.1, 饱和度 0.1)
  4. 标准化参数:mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]

模型架构选型

DeepLabv3+ 优势

  • 空洞卷积保持感受野同时减少下采样
  • ASPP 模块多尺度特征融合
  • 适合显存有限的设备(约 8GB 可训练 1024×512 尺寸)

HRNet 特点

  • 并行多分辨率子网络
  • 始终保持高分辨率特征
  • 需要更大显存(16GB+ 推荐)

新手建议:显存 <12GB 选 DeepLabv3+,否则优先 HRNet-W48

代码实战

数据加载器实现

关键点:处理类别不平衡(道路像素占比约 30%)

class CityscapesDataset(Dataset):
    def __init__(self, root, split='train'):
        self.class_weights = torch.tensor([
            0.8373, 0.918, 0.866, 1.0345, 1.0166, 0.9969, 0.9754,
            1.0489, 0.8786, 1.0023, 0.9539, 0.9843, 1.1116, 0.9037,
            1.0865, 1.0955, 1.0865, 1.1529, 1.0507  # 逆频率加权
        ])

    def __getitem__(self, idx):
        image = Image.open(img_path).convert('RGB')
        label = convert_label(np.array(Image.open(label_path)))

        if self.transform:
            image, label = self.transform(image, label)

        return image, label, self.class_weights[label]

损失函数设计

推荐组合:

criterion = nn.CrossEntropyLoss(weight=class_weights, ignore_index=255)
aux_criterion = nn.CrossEntropyLoss(weight=class_weights)  # 用于 DeepLab 辅助头

训练技巧

学习率调度

三阶段策略:

  1. Warmup(前 500 迭代):lr = base_lr * (iter/500)
  2. 余弦衰减:lr = base_lr * 0.5(1 + cos(iter/max_iterπ))
  3. 最终微调:最后 1 /10 训练时冻结 BN 层

OHEM 实现

在线难例挖掘示例:

class OhemCELoss(nn.Module):
    def __init__(self, thresh=0.7):
        super().__init__()
        self.thresh = -torch.log(torch.tensor(thresh))

    def forward(self, pred, target):
        n_min = target.numel() // 16  # 取损失值前 6.25% 的样本
        loss = F.cross_entropy(pred, target, reduction='none')
        loss = loss[loss > self.thresh]
        return loss[:n_min].mean()

避坑指南

标签映射

常见错误:

  • 未处理 ignore_index=255 导致梯度异常
  • 混淆 idtrainId(如交通灯 id=19 应映射到 trainId=6)

解决方案:

# 官方提供的标签对照表
{0: ('road', 7, 0, 255),
    1: ('sidewalk', 8, 1, 255),
    # ... 其他类别
    18: ('motorcycle', 17, 18, 255)
}

验证集数据泄露

严禁在验证集上:

  • 执行任何数据增强(除标准化)
  • 使用验证集统计结果调整超参数
  • 多次重复验证影响早停判断

性能优化

显存管理技巧

  1. 梯度累积:batch_size= 4 时,每 2 次迭代更新一次(等效 bs=8)
  2. 混合精度训练:
scaler = torch.cuda.amp.GradScaler()

with torch.cuda.amp.autocast():
    output = model(inputs)
    loss = criterion(output, labels)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
  1. 使用 torch.backends.cudnn.benchmark = True 加速卷积

总结

通过合理的数据预处理、模型选择以及训练技巧,在 Cityscapes 上达到 75+ mIoU 是完全可行的。建议初学者先用 DeepLabv3+ 在缩小尺寸(1024×512)上实验,待流程跑通后再尝试更大模型。关键是要理解每个技术选择背后的动机,而不是盲目套用参数。

正文完
 0
评论(没有评论)