拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLOV5医学影像数据集实操:宫颈癌检测目录校验与训练避坑指南

YOLOV5医学影像数据集实操:宫颈癌检测目录校验与训练避坑指南

简介:面向医学影像与目标检测研究者的宫颈癌检测数据集,采用YOLOV5标准目录格式整理,仅含cancer一个类别,已分为训练集与验证集。训练集包含816张图片及对应txt标注,验证集216张图片及标注,总计1032张图片,均为1000-4000像素大分辨率RGB图像,病灶目标小,边界框标注清晰,贴近小目标检测场景。压缩包约615MB,内含2000个文件,主要由916个jpeg原图、1083个txt边界框标签和1个可直接运行的Python可视化脚本组成,下载后无需额外转换即可用于YOLO系列模型训练,特别适合验证大分辨率小目标检测算法。已有738人学习下载,适合需要大分辨率小目标医学检测数据集的算法工程师与科研人员。附带的可视化脚本能随机抽取图片并绘制边界框保存结果,方便快速预览标注质量与数据分布,辅助评估数据集效果。

1. 拿到的医学数据集是 YOLOV5 目录格式:宫颈癌检测单类别任务先想清楚这三件事

一个解压后就是标准 YOLOV5 目录格式的宫颈癌检测数据集,1 个类别,训练集和验证集已经分好,看起来是“开箱即训”的省心项目。但医学影像目标检测和通用检测有个本质差别:单类别、小样本、图像特征高度依赖染色和切片条件,这三件事叠加,让“格式正确”只解决了 10% 的问题,剩下 90% 是目录校验、划分逻辑和验证方法。这个数据集适合跑通从 YOLOV5 目录格式校验、data.yaml 配置到模型训练的完整链路,也适合做病理辅助检测的从业者拿来做基线实验。别急着跑训练命令,先花半小时把目录拆开看一遍,省下后面一整天的排查时间。

2. 拆解 YOLOV5 目录格式:宫颈癌训练集/验证集的目录结构与标签约定

在把训练命令敲下去之前,先把目录结构看明白。标准 YOLOV5 目录格式的常见做法是:数据集根目录下放 images 和 labels 两个一级目录,各自内部按 train、val 划分,训练集和验证集互不混淆。

cervical-cancer/ ├── images/ │ ├── train/ │ │ ├── img_0001.jpg │ │ ├── img_0002.jpg │ │ └── ... │ └── val/ │ ├── img_0100.jpg │ └── ... └── labels/ ├── train/ │ ├── img_0001.txt │ ├── img_0002.txt │ └── ... └── val/ ├── img_0100.txt └── ...

这段目录结构里有一个硬约束:images/train 里的每一张图,必须在 labels/train 里有一个同名 .txt 文件,扩展名不同、文件名前缀必须完全一致。比如 img_0001.jpg 对应 img_0001.txt,img_0100.png 对应 img_0100.txt。如果文件名对不齐,YOLOV5 在加载数据时不会报错,而是打一行 warning 然后跳过这张图,这种“静默跳过”是后面所有奇怪现象的源头。

标签文件内容也要符合约定。每行表示一个目标框,格式是 YOLO 归一化坐标:class x_center y_center width height,所有的坐标值都在 0 到 1 之间。这个宫颈癌检测项目只有 1 个类别,所以 class 这一列恒为 0。特别提醒:不要因为只有 1 个类别就把 class 列省掉,五列格式是 YOLOV5 解析器的硬性要求;标签文件里也不能存在空行,行尾不能有多余空格,否则加载时轻则跳过、重则直接抛异常。

2.1 YOLOV5 的加载机制:images 与 labels 同名匹配的隐性问题

YOLOV5 源码里负责读取数据的是 utils/datasets.py 中的 LoadImagesAndLabels 类。它遍历 images 目录下的所有图片,然后根据后缀替换规则去 labels 目录寻找同名 txt。如果某个图片没有对应 txt,默认行为是跳过它并打印一条 warning;如果某个 txt 没有对应的图片,则会被当成孤立标签直接忽略。这两个行为都不致命,但叠加起来就很坑:比如一个数据集有 1200 张图、1000 个标签,训练时那 200 张没有标签的图会被当作纯背景样本参与计算。当背景样本占比过高时,loss 会明显下降,但 mAP 始终在 0 附近,因为模型几乎没有学到任何正样本特征。

命名规则上,图片名和标签名的前缀必须完全一致。从 VOC、COCO 或医学标注平台转换数据集时,最容易翻车的是:标签文件叫img_0001.txt,图片却叫0001.jpg,前缀对不上,全部被跳过。另一个隐蔽问题是 UTF-8 BOM 头,Windows 下用记事本编辑过的 txt 会在开头多一个不可见字符,Python 按行解析时第一行 class 字段变成\ufeff0,导致 int() 转换失败。遇到这种情况,打开文件看一眼前几个字节就能定位。建议拿到任何数据集,先不要训练,跑一遍目录体检脚本,半小时的检查时间能省下至少一整天的排查时间。

提示:YOLOV5 的数据校验非常宽松,它默认“信任”你的目录是对的。目录格式错误不会直接让你训练失败,而是让模型学习到错误的数据分布。

2.2 单类别也要写 data.yaml:类别配置文件的最小写法

YOLOV5 训练时必须指定一个 data.yaml,它告诉训练器三件事:数据集根目录在哪、训练集和验证集图片路径、类别数量和类别名。单类别宫颈癌检测任务同样要写,不能因为“只有一个类”就省略。

# cervical_data.yaml path: /data/cervical-cancer # 数据集根目录,建议写绝对路径 train: images/train # 训练集图片目录,相对 path 解析 val: images/val # 验证集图片目录,相对 path 解析 nc: 1 # 类别数:宫颈癌检测只有 1 个类别 names: 0: cervical_cancer # 类别名,自己定,不要和别的任务混用

参数说明:path 字段是 YOLOV5 v5.0 之后新增的写法,如果你的环境是 v3/v4 老版本,需要把 train 和 val 改成相对于运行目录的完整路径,比如/data/cervical-cancer/images/train。nc 必须和标签文件里的 class 最大值匹配,标签里 class 最大是 0,nc 就是 1。names 的索引从 0 开始,单类别任务只有 0 这个索引。

有个非常容易被坑的点:data.yaml 里的 path 如果用了相对路径,YOLOV5 会相对于当前工作目录解析,而不是相对于 yaml 文件所在目录。很多人在服务器上用 nohup 启动训练时工作目录不对,就会出现 Dataset not found 错误。我一般会在 yaml 里写死绝对路径,避免这种和环境相关的玄学问题。另外,这个 yaml 文件放在哪个目录都不影响,训练时通过 --data 参数指定完整路径即可。

2.3 训练集与验证集的划分逻辑:医学影像为什么不能随机乱分

自然图像数据集可以随机划分训练集和验证集,因为每张图是独立的样本。医学影像不行,尤其宫颈癌病理图像:同一个患者的多个切片、多个视野之间存在高度相关性。如果随机划分,同一个患者的图像可能同时出现在训练集和验证集里,模型等于提前见过这位患者的纹理特征,验证精度虚高,泛化能力被严重高估。

在之前处理一个宫颈癌检测数据集时,我做过对比实验:按图片随机划分时验证集 mAP 能到 0.8 以上,改成按患者 ID 整组划分后,mAP 直接掉到 0.7 以下。这个差距不是模型好坏,而是数据划分泄漏。拿到这个已经分好训练集和验证集的数据集,第一件事就是检查两个集合里有没有同一个患者 ID 的图像。检查方法通常是从文件名提取 ID 前缀,比如patient001_slide01.jpg的 patient001,然后用集合运算对比 train 和 val 的 ID 是否有交集。

如果发现存在患者重叠,有两个处理方案。方案一是直接重新按患者 ID 划分,把验证集重新割出来;方案二是保留原有划分,但在报告实验结果时明确标注“验证集与训练集存在患者重叠,mAP 可能偏高”,至少不要让结论误导后续判断。还要检查一个常见问题:训练集和验证集的图像来源是否一致。之前碰到过某个数据集验证集是精挑细选的清晰切片,训练集是包含大量模糊切片的原始扫描,模型在验证集上表现很好,但实际手头数据一测就翻车。

注意:医学数据集标注质量参差不齐,“验证集是整理过的、训练集是原始的”这种情况相当常见。训练前抽 20 到 30 张验证集图像人工看一下标签框位置,确认框是否贴合病灶边界,比单纯看统计数值可靠得多。

3. 把宫颈癌检测数据集跑通 YOLOV5:目录体检、训练命令与参数调优

确认目录格式无误后,下一步就是真正跑训练。这一章给出目录体检脚本、最小训练命令,以及针对医学单类别检测场景的参数调整方案。

3.1 先做目录体检:检查图片与标签对不齐的排查脚本

写一个 Python 脚本,在训练前把目录里所有图片和标签文件都过一遍,输出对不齐的文件列表。

import os from pathlib import Path dataset_root = Path('/data/cervical-cancer') for split in ['train', 'val']: img_dir = dataset_root / f'images/{split}' lbl_dir = dataset_root / f'labels/{split}' # 收集图片和标签的文件名前缀(去掉扩展名) img_stems = {p.stem for p in img_dir.glob('*.jpg')} img_stems |= {p.stem for p in img_dir.glob('*.png')} img_stems |= {p.stem for p in img_dir.glob('*.jpeg')} lbl_stems = {p.stem for p in lbl_dir.glob('*.txt')} missing_lbl = img_stems - lbl_stems orphan_lbl = lbl_stems - img_stems print(f'[{split}] images={len(img_stems)}, labels={len(lbl_stems)}') print(f' missing label: {len(missing_lbl)}, 示例: {list(missing_lbl)[:5]}') print(f' orphan label : {len(orphan_lbl)}, 示例: {list(orphan_lbl)[:5]}') # 抽查前几个标签文件的内容格式 for txt in sorted(lbl_dir.glob('*.txt'))[:5]: with open(txt, encoding='utf-8-sig') as f: # 忽略 BOM 头 first_line = f.readline().strip() cols = first_line.split() if len(cols) != 5: ok = False else: try: ok = all(0 <= float(v) <= 1 for v in cols[1:]) except ValueError: ok = False print(f' {txt.name}: {cols}, {"OK" if ok else "BAD"}')

逻辑说明:这段脚本做了两层检查。第一层对比 images 和 labels 的文件名前缀集合,找出“有图无标签”和“有标签无图”的文件,前者会静默跳过、后者会浪费标注工作量。第二层抽查每个 split 前五个标签文件,确认每行 5 列、class 值合法、坐标在 0 到 1 之间,如果坐标大于 1 说明标签没归一化,class 值大于 0 说明类别编号和 nc=1 不匹配。

参数说明:glob 匹配了 jpg、png、jpeg 三种常见格式,因为医学图像里还常出现 .tif 和 .bmp,如果数据集里有这两种格式,记得在集合运算里加上;open 时用了 encoding='utf-8-sig',会自动剔除 BOM 头,这比先报错再修文件要省时间。脚本输出的 BAD 信息是关键排查入口,尤其注意坐标值是否为 0 到 1 之间的浮点数,YOLO 标签格式不认像素坐标。

如果脚本发现大量缺标签,不要尝试手工补,先问数据来源是转换环节丢文件,还是原始标注就不完整。一次在我自己处理过的宫颈癌数据集里,缺标签的图片全部来自同一批切片扫描仪,原因是这批图单独跑过一个预处理流程,标签文件被脚本误删了。

3.2 跑通最小训练:data.yaml 与训练命令落地

目录校验通过后,用最小命令把训练跑起来。以 YOLOV5 v6/v7 版本为例:

python train.py \ --data /data/cervical-cancer/cervical_data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --project runs/cervical \ --name exp1

参数说明:--weights 用 COCO 预训练的 yolov5s.pt。医学图像和自然图像差异很大,但骨干网络低层学习的边缘、纹理和颜色特征仍然可以复用,尤其在小样本条件下,预训练权重能明显加速收敛。如果你想从零开始训练,改成 --weights '' 即可,但医学小数据集上从零训练效果通常不如迁移学习。--img 640 是训练分辨率,宫颈癌病灶通常是小区域,后面可以尝试提高到 1024,代价是显存占用大幅上升。--batch 16 取决于 GPU 显存,如果只有 8GB 显存,建议降到 8。--epochs 100 是针对小数据集的折中值,医学数据量一般在几百到几千张,100 轮足够判断模型是否收敛。

跑第一个 epoch 时,建议盯着终端输出的两类信息:第一类是Dataset not found或Assertion报错,说明 data.yaml 路径或标签格式有问题;第二类是train: images=xxx, labels=yyy的统计,images 数量和 labels 数量可以粗略验证目录是否正确加载。如果 labels 数量远小于 images 数量,说明大量图片被当作背景跳过了,这种情况在目录体检阶段就应该被拦截住。

3.3 医学检测场景下的关键训练参数设置

通用目标检测的参数默认值在医学单类别小数据集上经常不适用,需要针对性调整。

Anchor 参数。YOLOV5 默认在训练开始前用 k-means 重新计算 anchor。如果你的病灶框尺寸分布和 COCO 差异很大,自动计算的 anchor 可能不稳定。对于单类别任务,可以先不干预,因为只有一类目标,anchor 自适应能力足够强;但如果发现训练到 20 轮后目标框尺寸仍然在剧烈变化,可以在命令里加 --noautoanchor,然后使用自定义 anchor 配置。实际操作中,我更倾向于先看训练日志里的 autoanchor 输出,确认 anchor 是否符合预期再决定要不要关掉。

数据增广。YOLOV5 的 hyp.scratch-low.yaml 默认开启了颜色抖动、旋转、缩放、翻转等增广。但医学病理图像的染色颜色是有诊断意义的,hsv_h、hsv_s、hsv_v 三个参数如果保持默认,会把染色差异当作可变化特征去学习,导致模型对真实病理切片的颜色变化过于敏感。建议把这三个值调低:hsv_h 从 0.015 调到 0.005,hsv_s 从 0.7 调到 0.3,hsv_v 从 0.4 调到 0.2。同时确认 fliplr 是开启的,flipud 在病理图像上可以开,但如果你后续要检测的方向性很强(比如组织排列结构),翻转反而会降低泛化能力。

Loss 权重。单类别检测任务里分类压力远比多类别小,因为模型只需要区分“病灶”和“背景”,定位反而是主要难点。如果训练日志显示 cls_loss 已经很低但 box_loss 降不下去,可以把 loss 权重配置里 box 的权重适当提高。这个在 YOLOV5 中不是直接暴露的参数,需要改 utils/loss.py 里的相关常数,不建议新手直接改源码;更稳妥的做法是先增加训练轮数和输入分辨率,让模型有更多时间优化定位。如果验证集上误检(背景被当病灶)比例过高,把 --conf 阈值从 0.25 提高到 0.35 再验证,能帮助你判断是定位框不准还是分类置信度不足。

4. 医学数据集训练避坑:宫颈癌检测常见的 5 个翻车点

这一章是血泪经验汇总。医学数据集和自然图像数据集最不一样的地方在于:错误不报、结果不直观。以下 5 个翻车点按“现象 → 原因 → 解决”顺序写,都是单类别医学检测里最容易踩的坑。

4.1 现象:loss 正常下降,验证集 mAP 恒为 0

这是新手最容易困惑的情况。训练时 loss 从 0.1 一路降到 0.02,看着一切正常,但每个 epoch 结束后的验证 mAP 永远是 0。原因:最常见的是图片和标签对不上,所有标签文件都没被加载,模型把所有样本都当成了背景。虽然 loss 会下降,因为背景类占绝对主导,但模型没有任何正样本输出,mAP 自然为 0。解决:跑 3.1 的目录体检脚本,检查 labels 目录是否存在、文件前缀是否匹配、txt 里是否有内容。另一个常见原因是标签坐标是像素值而非归一化值,坐标大于 1 的框在加载时被丢弃,同样导致 mAP 为 0。解决:检查 txt 中是否出现大于 1 的数值;如果有,写脚本用图片宽高归一化。

4.2 现象:训练报 Assertion 错误或 class 索引超界

运行 train.py 后直接抛出Assertion 'labels should not be negative'或class 0 is not in class list之类的报错。原因:标签文件中出现了负数坐标,或者类别编号超出 nc 范围。医学数据集很多由第三方标注工具导出,部分工具默认类别编号从 1 开始,导出的 txt 里 class 是 1,而 data.yaml 里 nc=1 只接受 class=0;负数坐标则多是因为标注框部分超出图像边界后被工具编码成了负值。解决:写一个清洗脚本,把所有 txt 里的 class 值减 1,把负坐标裁剪到 0,宽度和高度小于 1 像素的框直接删除。这类问题在训练前体检时就应该发现,脚本里加上坐标合法性校验能直接拦下来。

4.3 现象:训练集 mAP 很高,验证集也不低,但实际推理效果差

原因:训练集和验证集存在“同患者”图像。宫颈癌病理图像同一患者的多个视野之间颜色和纹理高度一致,如果随机划分,模型在训练时见过这位患者的纹理,验证时相当于开卷考试,mAP 虚高但不代表泛化能力。解决:按患者 ID 重新划分数据集,确保验证集中的患者不在训练集中出现过。这种问题在已划分好的数据集里也可能存在,文件名里通常带有患者 ID 或病例编号,先提取再比对,有重叠就重新划分。

4.4 现象:训练早期 loss 震荡剧烈、难以收敛

原因:单类别医学数据中,大量图像可能根本没有病灶(阴性切片)。这些纯背景图像进入训练集后,YOLOV5 在计算 loss 时会把它们当作背景样本,如果阴性样本占比超过一半,梯度方向被背景主导,模型很难稳定学习病灶特征。解决:先统计每个 txt 里的目标框数量,把没有目标的图片抽出来。阴性样本可以保留少量用于抑制误检,但占比控制在 20% 以内比较稳妥;如果数据量太少,可以考虑用过采样让每个 batch 里至少有一部分包含正样本的图像。

4.5 现象:换 --img 分辨率后,所有目标框位置都偏了

原因:YOLO 标签用归一化坐标,理论上与分辨率无关。但有些医学数据集制作时先对原图做了裁剪或 resize,再直接导出标注框,导致标签坐标和图像内容错位。这种问题在别人已经转好的目录格式里最隐蔽,因为你不知道它之前经历了什么处理。解决:换分辨率后做一次可视化验证,用 YOLOV5 自带的检测脚本在几张训练集图片上画框,对比框是否贴合目标。如果框系统性偏移,说明标签坐标系和图片不一致,需要用脚本重新对齐:先读取每张图的实际尺寸,再裁掉导致偏移的边距,最后重新计算归一化坐标。

5. 把训练好的模型用起来:验证命令、滑窗推理与增广选择

5.1 用 val.py 复现验证集结果

训练完成后,用独立的验证命令确认模型在验证集上的真实表现。

python val.py \ --data /data/cervical-cancer/cervical_data.yaml \ --weights runs/cervical/exp1/weights/best.pt \ --img 640 \ --conf 0.25 \ --iou 0.45 \ --project runs/cervical \ --name val_exp1

跑完看两个文件:confusion_matrix.png 和 results.csv。对单类别检测而言,混淆矩阵里“背景被误检成病灶”的比例比 mAP 更有参考价值。如果这个比例超过 5%,先把 --conf 调高到 0.35 再验证,观察误检下降幅度;如果下降明显,说明模型对背景纹理的判别能力不足,需要补充阴性样本或减少颜色增广。

5.2 病理大图上的滑窗推理

病理切片原图经常是几万像素的超大图,直接往 YOLOV5 里送会爆显存。常见做法是滑窗推理:把大图切成 1024x1024 的小块,相邻块之间重叠 100 到 200 像素,逐块检测后再把检测框映射回原图坐标,最后用 NMS 去掉重复框。这个流程能让单类别模型真正用起来,也方便按病例统计病灶数量和面积占比。具体实现要注意边缘块补齐,不足 1024 的边角用零填充,推理时记录填充偏移量,映射坐标时减掉。

5.3 迭代习惯:每次训练前必须确认的清单

现在每拿到一个新数据集,我都会固定做三件事:先跑目录体检脚本确认格式,再按患者 ID 检查划分是否有重叠,最后抽 30 张图人工看标签框是否贴合病灶。这三步做完才允许训练。以前我图省事跳过体检直接训练,结果被“loss 很低但 mAP 为 0”这种情况整整耗了一个周末才定位到是标签文件前缀对不上。训练时低层网络特征可以复用,但数据格式和划分逻辑必须自己确认——在这个领域,数据比模型更值得花时间。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表