mmsegmentation训练自定义数据集(语义分割,Upernet,Swin-T)
1. 论文复现
1.1. 原文结果
1.2. 复现结果
- 实验结果:在ADE20k数据集上,复现结果的mIOU略微超过原文结果
1.3. Test阶段速度:
2. Mmsegmentation Trick
- mmsegmentation整体的构架流程:
以backbone为swin-t的Upernet为例:
configs/swin/upernet_swin_tiny_patch4_window7_512x512_160k_ade20k_pretrain_224x224_1K.py
2.1. Pipeline(加载数据、数据增强)
-
路径:/home/wenjie.yuan/park/mmsegmentation/configs/base/datasets/ade20k.py
-
pipeline中包括:
LoadImageFromFile
:加载图像的API,当需要修改数据读取方式,加载bucket
中数据,或者需要修改图片数据,可以对此API进行修改LoadAnnotations
:加载mask的APIResize
:保持原图像的比例不变,效果会更佳RandomCrop
:cat_max_ratio=0.75
,代表最多类别的像素值占整个图片的比例大于-cat_max_ratio
,就进行裁剪,防止背景占比太大RandomFlip
:随机反转PhotoMetricDistortion
:光度失真:调整图像的亮度,色度,对比度,饱和度,以及加入噪点实现DefaultFormatBundle
:各个 Dataset 类的 get_item 函数最后返回的是一个 dict。调用DataContainer
类,对原本数据的一层简单包装 /wrapper,得到一个list(dict)。在此之前,经过的数据增强部分都是单张图片(一个dict)Collect
:当cpu_only = False, stack = True
时,将DefaultFormatBundle
的list的图像部分N个[C,H,W]打包成为[N,C,H,W]
2.2. 损失函数选择
- 路径:
configs/_base_/models/upernet_swin.py
- 主要包括
FocalLoss
、LovaszLoss
、CrossEntropyLoss
、DiceLoss
2.3. 学习率策略
-
configs/swin/upernet_swin_tiny_patch4_window7_512x512_160k_ade20k_pretrain_224x224_1K.py
-
使用了
AdamW
,需要修改学习率,只需要修改lr即可 -
采用多项式衰减策略:
min_lr
:最后几个epoch的学习率by_epoch
:是否选择在下降到最低的时候会上升,防止后期学习率很低陷于局部最优解
2.4. 其他trick
- 在线难样本挖掘 (Online Hard Example Mining, OHEM)
- 在
configs/_base_/models/upernet_swin.py
中添加
- 在
model=dict(
decode_head=dict(
sampler=dict(type='OHEMPixelSampler', thresh=0.7, min_kept=100000)) )
3. 训练FRFL相机数据集
- 数据集:
- 包含五类:bump (减速带)、stopper (限位器)、open_lock:打开地锁、close_lock:关闭地锁、crosswalk(人行道)
- 环境:参考github
3.1. 修改配置文件:
-
在
tools/data
文件夹下按照格式准备数据集: -
tools/mydata/park
- annotations
- training
- validation
- images
- training
- validation
- annotations
-
或者在
mmseg/datasets/pipelines
文件夹下的loading.py
中修改LoadImageFromFile
类去读json文件 -
修改
configs/_base_/datasets/ade20k.py
的data_root
(如果第1步准备好的就不需要) -
修改
tools/train
的--config
(选择配置文件)和--work-dir
(权重保存在哪)和--load-from
(预训练权重) -
修改
mmseg/datasets/ade.py
的CLASSES
和PALETTE
(调色板) -
修改
configs/_base_/models
文件夹下的upernet_swin.py
中的num_classes
为自己的类别数 -
修改
configs/swin
文件夹下的upernet_swin_tiny_patch4_window7_512x512_160k_ade20k_pretrain_224x224_1K.py
的num_classes
、samples_per_gpu
3.2. 实验参数修改
修改了的参数:
Resize
:img_scale=(1600, 640),ratio_range=(0.75, 1.25)RandomCrop
:crop_size=(512, 512),cat_max_ratio=1batch
=32lr
=0.00012Loss
:
decode_head=dict(
loss_decode=[dict(type='LovaszLoss', per_image=False,reduction='none',loss_weight=1.0),
dict(type='FocalLoss', loss_weight=1.0)]))
auxiliary_head=dict(
loss_decode=[dict(type='LovaszLoss', per_image=False,reduction='none',loss_weight=0.4),
dict(type='FocalLoss', loss_weight=0.4)]))
samples_per_gpu
:每个GPU每次处理的图片,batch = samples_per_gpu * GPUS
,samples_per_gpu=4
时候,显存没满,但是GPU利用率已经接近满了,再提高samples_per_gpu
,降低iteration
速度提高并不多- 将输入
mask
中背景当成一个类别训练:
gt_semantic_seg[gt_semantic_seg == 0] = 6
gt_semantic_seg[gt_semantic_seg == 255] = 6
demo/image_demo.py
中将图片打印出:
show_result_pyplot(out_file=output_dir) # output_dir是输出图片路径,不然不会在终端显示和保存
3.3. 消融实验
3.3.1 参数作用
参数(数据增强) | 参数说明 | 实验(mIOU) |
---|---|---|
img_scale/ratio_range | 输入图像=img_scale*ratio_range | (0.75 , 1.25)> (0.5 , 2.0)原配置 > (0.25,2.5) > (1.0, 2.0) |
crop_size | 裁剪的尺寸 | (512,512)预训练模型输入大小>(416,416) |
cat_max_ratio | 一张图像最多的类别小于cat_max_ratio,就需要裁剪 | 1 (不经过)> 0.75 |
batch、lr | 2lr< lr , (batch=64&2lr) <(batch=32&lr) | |
samples_per_gpu | 每个GPU每次处理的图片 | 32 |
loss | (FocalLoss和LovaszLoss 10:1 ) > (FocalLoss和LovaszLoss 1:1 ) > (FocalLoss) > (CrossEntropyLoss(class_weight=(1,1,1,1,1,0.9))) > (CrossEntropyLoss) =(CrossEntropyLoss预训练,然后CrossEntropyLoss和LovaszLoss 1:1 finetune的方案) |
3.3.2. 消融实验
3.3.3. 实验精度
-
- Basline + Focal&Lovasz + cat_max_ratio = 1
- Basline + Focal&Lovasz + cat_max_ratio = 1
3.4.分割效果(白色或紫色为标注区域)
3.4.1. 限车位和开锁
-
真实标签:
-
实际分割效果:
3.4.2. 闭锁、限车位
-
真实标签:
-
实际分割效果:
3.4.3. 开锁、限车位、减速带
- 真实标签:
- 实际分割效果:
3.4.4. 人行道
-
真实标签:
-
实际分割效果:
4. 常见BUG
TypeError: __init__() got an unexpected keyword argument 'embed_dim'
- 解决办法:把代码路径加入python环境
- export PYTHONPATH=/home/mmsegmentation