乐趣区

关于challenge:写给-mmsegmentation-工具箱新手的避坑指南

前言

我在 Windows 环境应用 MMClassification、MMDetection 都还算轻轻松松,然而走完 MMSegmentation 全流程之后,真的想感叹一句“踩了不少坑啊”,所以想把本人的遇坑教训凝练总结进去,写一个专门给老手无伤通关的避坑教程。

Windows 配置环境的痛:mmcv-full

在 v1.4.0 之前,mmcv-full 的装置没有针对 Windows 的现成预编译包,所以大部分老手会卡在 build MMCV 的过程中 …… 这种状况下有两种解决方案。

计划 1:新版编译版本主动装置

在 1.4.0 之后,MMCV 会跟上 PyTorch 版本更新 Windows 环境下的 mmcv-full 预编译包,然而可用的版本范畴比拟局限,依赖 PyTorch、CUDA、mmcv-full 低版本的炼丹师天然就不适宜这种装置形式了(看计划 2),上面是以 PyTorch1.11.0、CUDA11.3 为例的装置命令。

  • 一句命令装置 mmcv-full,下载速度还是不错的
pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.11/index.html

计划 2:手动操作

如果你不心愿更新到新版 MMSegmentation 或者 MMCV,也能够尝试手动装置,上面以在 GPU+CPU 双环境运行的指标来装置 mmcv-full,参考了官网文档,所有命令行运行在 powershell,应用 cmd 的炼丹师须要留神两个命令行的命令差别。

  • 创立虚拟环境
conda create --name mmcv python=3.7 # 经测试,3.6, 3.7, 3.8 也能通过
conda activate mmcv # 确保做任何操作前先激活环境 
  • 进入一个临时文件门路,克隆 mmcv-full 源码
git clone https://github.com/open-mmlab/mmcv.git
cd mmcv # 进入我的项目文件夹 
  • 装置依赖

所有依赖中,也装置了 ninja 库用于放慢最初编译的速度

pip install -r requirements.txt
# 倡议应用镜像减速 =pip install -r requirements.txt -i https://pypi.douban.com/simple
  • 配置编译环境

装置 Microsoft Visual Studio Community 2017/2019/......,确保环境变量中的 Path 存在编译所需的值。以 VS2019 Community 为例:C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\Hostx86\x64

  • 编译装置 mmcv-full
$env:MMCV_WITH_OPS = 1
$env:MAX_JOBS = 8 # 依据可用的 CPU 和内存量进行设置
python setup.py build_ext # 如果胜利, 将会自动弹进去编译 flow_warp
python setup.py develop # 执行装置 
  • 检测是否装置胜利
pip list # 应用 anaconda 的话,也能够在 openmmlab 依赖的虚拟环境下 =conda list

数据集自定义类别

更改 CLASSES 和 num_classes

不敢调试的老手炼丹师首次面对 mmseg 的我的项目可能莫衷一是,因而也很难养成本人编写数据集加载代码的习惯。其实能搜到很多程度不一的材料教你编辑现有的数据集加载形式(比方常见的 ADEDataset),批改 CLASSES,而后设置 num_classes,可能更改完发现编辑后的代码基本没利用上,网络 decoder 一直吐槽你 num_classes 不对,而后你又去查看手里的数据集 …… 其实是因为意识较浅,上面展现更正当的走通指南:

  • 抉择好模型后,先把相关联配置文件里的全副 num_classes 设置好值,比方经典 ADE 数据集提取并划分了 150 个实例类,num_classes 就是 150,计入 num_classes 的所有类的名称下一步都要写入 CLASSES。(背景类未算入 150,下一节会解说为什么)
  • 上面,进入 mmseg 我的项目下的 mmseg`/`datasets,以遥感语义宰割工作为例新建 py 文件 uavdataset.py,继承自 custom.py 中的 CustomDataset,而后开始实现本人的数据集 …… 在定义 CLASSES 的时候,tuple 初始化为本人类名的汇合即可(比方对于街区 block、农田 field 和其余利用地 notused 的遥感语义宰割工作),用于上色的 PALETTE 也能够用相似的形式配置(配置格局:[R, G, B])。
# mmseg/datasets/uavdataset.py

...
CLASSES = ('block', 'field', 'notused')

PALETTE = [[120, 120, 120], [180, 120, 120], [120, 180, 120]]
...
  • 而后参考 configs/_base_/datasets 的其余配置文件编写 uavdataset.py 作为 UAVDataset 的配置文件。最初,在选用的模型配置文件中更换数据集加载形式为 UAVDataset

对源码的增改没有成果?

  1. OpenMMLab 各种工具箱的官网文档中,都会教你用 pip install -v -e . 装置我的项目,但很多老手对 pip 的这种命令并不理解。其实这个命令是用来开启 mmseg 库编辑模式的,这样批改 mmseg 库内的代码片段能够主动被利用上,无需重新安装(如图截取自 MMSegmentation 官网文档的装置教程,其中正文曾经解释了这种 pip 命令的含意)。
  • 切记!应用 python `setup.py` install 装置的 mmseg 每次编辑源码都须要重新安装,这也是为什么大部分老手更改 CLASSES 却不失效的起因,倡议换用以下装置办法:
cd ~/mmsegmentation-master/ # 进入你的 mmseg 我的项目门路下
pip install -v -e . # 重新安装 英文句点示意装置以后门路下的我的项目 
  • 也有可能会有小伙伴问可不可以用 python setup.py develop,我没做过试验。然而 setup.py 也是门学识,既然官网文档教老手们用 pip 的形式就能成,也就没必要找太多替换计划了,新手上来没必要钻研在这下面。

独特的数据集参数:reduce_zero_label

借助 reduce_zero_label 治理 0 值背景

mmseg 中曾经为各种公共宰割数据集编写了形容文件和加载代码,对于有用过 PyTorch 的小伙伴而言,学习各种数据集的形容文件还是很自若的,只有 reduce_zero_label 对于 mmseg 的老手比拟生疏,所以,在搭建本人的 mmseg 数据集时,老手最纳闷的大略就是 reduce_zero_label 到底应该是 True 还是 False

它有什么用呢?从名字直译过去就是“缩小 0 值标签”。在多类宰割工作中,如果你的数据集中 0 值作为 label 文件中的背景类别,是倡议疏忽的。

关上加载数据的源码片段能够看到一段解决 reduce_zero_label 的代码,意思是:若开启了 reduce_zero_label,本来为 0 的所有标注设置为 255,也就是损失函数中 ignore_index 参数的默认值,该参数默认防止值为 255 的标注参加损失计算。前文按下不表的 150 类的 ADE 数据集,它不蕴含背景的起因就是开了 reduce zero label,本来为 0 值的背景设置为了 ignore_index

# mmseg/datasets/pipelines/loading.py

...
# reduce zero_label
if self.reduce_zero_label:
    # avoid using underflow conversion
    gt_semantic_seg[gt_semantic_seg == 0] = 255
    gt_semantic_seg = gt_semantic_seg - 1
    gt_semantic_seg[gt_semantic_seg == 254] = 255
...

reduce_zero_label 导致的常见问题形容

咱们这里以 ADE 数据集源码为例,reduce_zero_label 默认设置为 True,然而,就算老手把握了上一节的 reduce_zero_label,也可能对 ADE 理解比拟浮浅,会狐疑配置文件中开启的 reduce_zero_label 是不是把 150 个实例类中的第一个给疏忽掉了,毕竟 num_classes 不就是 150 吗,而后想当然把 reduce_zero_label 关掉。

谬误起因剖析

# configs/_base_/datasets/ade20k.py

train_pipeline = [dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', reduce_zero_label=True), # ADE 中 reduce_zero_label 默认设置为 True
    dict(...),
    ...
]

label 中理论加入训练的的确只有 150 类,定义在 CLASSES 中,但 label 文件中理论蕴含了 151 类,而背景类(剩下仍没有标记的,或者被意外疏忽的区域都归为背景,在 label 中值为 0)不蕴含在 150CLASSES 中,须要在训练的时候设置成 ignore_index,所以咱们借助上一大节的 reduce_zero_label 将背景从 151 个类中提出来独自设置为了 ignore_index,咱们假使谬误地将 reduce_zero_label 关掉了,那 num_classes 就是 151 了。

如何加强对数据集更多参数的了解?

理论工程中的数据集往往是咱们本人设计预测类别和标注规定的,如果背景真的很重要,那无论是批改 ADE 的配置文件,还是硬搬 ADE 格局数据集的应用形式,都不如尊重开发者写好的数据集加载代码,改用本人编写的数据集加载形式(只需继承自 CustomDataset 即可)。

在一行行编写的过程中,老手炼丹师能够一直参考钻研现存的其余数据集的解决方案,如果遇到不懂的中央也能有查漏补缺的方向,尤其是 reduce_zero_label 这种参数,须要充沛理解消化能力运用自如。一直尝试尝试尝试的过程中,老手炼丹师也会对各式各样的数据集加载形式产生本人的了解和认识,在迎接特殊任务的时候可能剖析本人的数据集,翻新设计出本人独特的数据集加载形式。

数据集文件后缀的坑:大小写

接着看 mmseg`/`datasetsade.py,这里 ADE20KDataset 类有两个 suffix(文件后缀)相干的参数配置,img_suffix 负责定义图像文件的后缀名,seg_map_suffix 定义标签文件的后缀名。默认配置:

# mmseg/datasets/ade.py

...
def __init__(self, **kwargs):
        super(ADE20KDataset, self).__init__(
            img_suffix='.jpg', # 图像的后缀名
            seg_map_suffix='.png', # 标签的后缀名
            reduce_zero_label=True,
            **kwargs)
        ...

然而有些炼丹师拿到的图像后缀是 .JPG,它和 .jpg 的区别仅仅是大小写不同,然而数据集加载会一直报 FileNotFound 的谬误。所以老手遇到此类报错肯定要留神大小写差别,间接批改配置文件中的 suffix 相干参数即可。

日志可视化

常常能够看到社区的小伙伴在问训练遇到的问题,而且喜爱间接对终端的日志截图,就算是巨佬也不肯定对一长串数字敏感。当我遇到这类状况个别会教他们去官网文档找可视化的章节,学习官网提供的绘制日志曲线图的脚本。然而运行脚本可视化是很麻烦的,应用的教程很少还很容易报错,而 tensorboard 可视化库是各工具箱都通用的,能够一句命令可视化训练过程的各种指标,并展现在对立的本地网页上,也给老手提供了更好展示本人训练问题的伎俩,在 mmseg 应用 tensorboard 的办法也很简略:

  • config/_base_ 中找到 default_runtime.py,第 6 行个别默认是正文起来的,将这行勾销正文也就开启了 tensorboard 记录,当前启动的训练都会在 work_dirs 的对应文件夹中生成 tf_log 文件夹。
# config/_base_/default_runtime.py

# yapf:disable
log_config = dict(
    interval=50,
    hooks=[dict(type='TextLoggerHook', by_epoch=False),
        dict(type='TensorboardLoggerHook') # 启动 tensorboard 记录(该行个别默认被正文起来)])
# yapf:enable
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]
cudnn_benchmark = True
  • 那么这个 tf_log 文件夹怎么应用呢?咱们只须要复制绝对路径,关上终端,切换到 OpenMMLab 所依赖的环境,并装置 tensorboard 的 python 库。
pip install tensorboard
  • 而后将 tensorboard 日志部署到本地 IP 和端口。
tensorboard --logdir {TF_LOG_PATH} # TF_LOG_PATH 替换为本人的 tf_log 文件夹绝对路径即可 
  • 执行胜利之后能够看到终端打印了一个本地 IP 和端口,默认是 http://localhost:6006/,按住 ctrl 键鼠标点击即可进入浏览器关上可视化页面,终端间断屡次按下 ctrl + c 组合键能够进行 tensorboard 服务。

后记

我应用 OpenMMLab 各种工具箱的时候编写的几个辅助脚本在我的 GitHub,涵盖了数据集预处理、保护和质检等性能,大家能够去看看有没有能帮上本人的。MMSegmentation 的大小坑真的让我啼笑皆非哈哈哈,也辛苦 MMSegmentation 开源开发者的付出,祝本人有一天能退出 OpenMMLab 的小家庭一起保护这个开源之星,也祝各位炼丹师试验顺利。

本文参加了 SegmentFault 思否写作挑战赛,欢送正在浏览的你也退出。

退出移动版