
简介这是一份面向医学图像目标检测的YOLO格式乳腺癌数据集包含训练集与验证集目标类别为breast cancer。图像均为640×640分辨率RGB图片边界框标注清晰图像完整且前景丰富适合用于YOLOv5等目标检测模型的训练、验证与算法研究。整个压缩包约12.87MB7z格式共1845个文件其中包含922个txt标签文件、921张jpg图像另附1个Python可视化脚本和1张预览图标签与图像一一对应可直接放入YOLOv5目录使用无需额外转换。训练集共778张图片及对应标签验证集143张图片及对应标签数据划分明确便于直接评估模型效果。可视化脚本随机读取一张图片即可绘制边界框并保存到当前目录无需改动即可运行帮助用户快速检查标注质量。目前已有1074人浏览学习适合刚接触医学图像检测的研究者或需要现成乳腺癌检测数据集的开发者使用。1. 单类别乳腺癌YOLO数据集医学影像检测最省心的起点乳腺癌检测在目标检测里是一个少见的“单类别反而更实用”的场景。你不区分肿块、钙化灶、结构扭曲的亚型只需要回答一个问题这块区域是不是癌变病灶。这个数据集已经按 YOLO 约定把训练集和验证集分开标注是统一的 txt 格式拿到手就能直接开训等于把往常要花两三周的 DICOM 清理、格式转换、专家标注工作提前做完了。它适合两类人做超声或钼靶影像辅助诊断的算法工程师以及想入门医学图像目标检测但找不到干净数据集的初学者。它的核心价值在于用最简单的数据组织方式跑通一条可评估、可迭代的乳腺癌检测流水线。2. 数据集内部结构与 YOLO 格式落地先做三件不花训练时间的事2.1 目录树与 data.yaml模型只认这一张地图标准的单类别 YOLO 医学检测数据集目录结构是固定的train 和 val 下各带 images 与 labels 两个平级文件夹breast_ultrasound_yolo/ ├── train/ │ ├── images/ │ │ └── case_001.jpg │ └── labels/ │ └── case_001.txt ├── val/ │ ├── images/ │ │ └── case_005.jpg │ └── labels/ │ └── case_005.txt └── data.yamldata.yaml 是训练时的唯一地图内容极简path: /datasets/breast_ultrasound_yolo train: train/images val: val/images nc: 1 names: - breast_cancer这里的 nc 必须等于 1names 列表只能有一个元素。我收到过一份自称“1 类别”的数据集结果它的 data.yaml 把 nc 写成 2、names 写成 [normal, cancer]训练时 loss 一直挂在 0.7 附近下不去——因为标签 txt 里的 class_id 全是 0模型却在努力区分两个类。拿到数据集后的第一个动作就是打开 data.yaml 确认 nc、names 和标签文件第一列完全对得上。YOLO 训练不看目录名只看 yaml 里的路径path 尽量写绝对路径避免换机器后缓存路径错乱。再看标签文件。train/labels/case_001.txt 每行五个数字0 0.5123 0.4876 0.1234 0.0987从左到右依次是 class_id、归一化中心 x、归一化中心 y、归一化宽度 w、归一化高度 h。归一化意味着除以整张图的宽高不是像素绝对值。这份数据集的特殊之处在于一张图通常只有 0 到 3 个框很多图甚至是完全没有框的阴性样本。这和 COCO 那种一张图平均七八个目标的分布完全不同后面所有参数调整都要围绕这个稀疏分布做。2.2 标注可视化脚本半小时内确认框是否贴边拿到数据集的第一件事不是训练而是把标注画出来看。这是所有排错的起点# check_boxes.py import cv2 import os img_file train/images/case_001.jpg txt_file train/labels/case_001.txt img cv2.imread(img_file) h, w img.shape[:2] with open(txt_file) as f: for line in f: c, cx, cy, bw, bh map(float, line.split()) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(check_case_001.jpg, img)脚本逻辑只有一步把 txt 里的归一化坐标还原成像素坐标。最容易写错的是顶点计算——左上角 x 是(cx - bw/2) * w不能直接拿cx * w当左上角否则框整体偏移半个框宽。乳腺病灶在超声图里多是低回声类圆形区域矩形标注必然会框进一小圈正常组织这是 YOLO 类水平框检测器的固有代价不算法错误。但如果框只有病灶的一半或者把周围一大片腺体全包进来这种标注必须回头找数据方核对。抽 train 和 val 各 20 张图跑一遍这个脚本能发现三类问题框和病灶错位、两张图误共用同一组坐标、图像被旋转 90 度导致框整体歪掉。最后一种在医学影像里格外常见DICOM 自带的 Orientation 标签在转 JPG 时常常被忽略转出来的人眼看上去是正的实际像素矩阵已经是旋转过的。2.3 数据泄露检查同病例出现在两端是最大隐患乳腺数据集的坑不在类别不平衡在数据泄露。一个病人的多张超声切面如果同时落在训练集和验证集模型记住的不是“癌变的普遍模式”而是“这个人的乳房纹理”。推理时换一个新病人性能立刻掉一截。检查手法非常直接ls train/images | sed s/_[0-9]*\.jpg// | sort -u train_cases.txt ls val/images | sed s/_[0-9]*\.jpg// | sort -u val_cases.txt comm -12 train_cases.txt val_cases.txtcomm -12 输出的 case_id 就是同时出现在两端的病例一个都不能留。这条命令依赖命名规范如果文件名是 case_001_view1.jpg 这类sed 能正确抽出 case_id如果是纯数字文件名就只能去翻数据表或元数据。我建议收到数据集的第一小时就做这一步比训练一晚上再发现指标虚高划算得多。注意数据泄露检查不是走形式。验证集指标虚高的模型上线后必然翻车而翻车在医学场景里是要担责任的。检查的第二件事是阴性图占比。单类别检测不存在类别不平衡但存在图像级不平衡大量图像没有病灶框。训练集里的阴性图教会模型“不要乱出框”这没毛病但验证集如果阴性图占比畸高Precision 会被抬得很虚。理想情况下验证集的阳性图占比应该贴近真实筛查场景的阳性率这个数字通常在 10% 到 30% 之间而不是 50% 以上。3. YOLO 训练乳腺癌检测模型最小命令与五个必调参数3.1 跑通训练的最小命令用 ultralytics 的 YOLOv8 或 YOLO11环境只需一个pip install ultralytics。训练命令yolo detect train \ data/datasets/breast_ultrasound_yolo/data.yaml \ modelyolov8n.pt \ epochs200 \ imgsz640 \ batch8 \ device0modelyolov8n.pt会自动加载 COCO 预训练权重到当前目录。训练开始后终端会按轮打印 box_loss、cls_loss、Precision、Recall 和 mAP50。第一次跑通只盯两件事box_loss 是否在稳步下降Recall0.5 是否在逐步上升。如果 box_loss 降了、Recall 不动优先怀疑标注框和病灶边缘严重不齐回到第 2.2 节的可视化脚本查一遍。训练结束后runs/detect/train/weights/ 下会有 best.pt 和 last.pt 两个权重乳腺癌检测我基本只取 best.ptlast.pt 留给断点续训用。关于 imgsz我一般先用 640 跑一个 baseline同时统计验证集病灶的像素尺寸分布。把 batch 从默认 16 改到 8不是玄学乳腺数据集通常只有几百到几千张图batch16 时一个 epoch 只有几十步BN 统计量波动大配合 0.002 的低学习率更容易稳。3.2 五个必调参数单类别医学图像和 COCO 就是不一样YOLO 的默认参数是按 COCO 自然图像调的用在乳腺数据上至少有五个要改。下表是我在乳腺超声和钼靶数据上常用的起点值参数COCO 常用默认乳腺数据推荐调整原因imgsz640512~800病灶常小于 32 像素分辨率不够直接压没batch16~328灰度图被复制成 3 通道显存占用和彩色图差不多epochs100150~300数据量小需要更多轮次慢慢收敛lr00.010.001~0.003医学图纹理差异小学习率太大会震荡mosaic1.00.25 或 0拼接增强会切碎病灶上下文小病灶直接消失lr0 是我改动后收益最明显的参数。乳腺超声图的背景结构高度相似梯度方向一致0.01 的默认学习率很容易第一轮就把预训练权重冲坏表现为前 10 轮 loss 不降反升。降到 0.002 并配合 cosine lr让最后 20 个 epoch 缓慢收敛效果通常比大学习率跑满 300 轮还稳。mosaic 是另一个大坑。YOLOv8 默认开启 Mosaic 增强把四张图裁开再拼成一张但乳腺病灶本来可能只有几十个像素拼图过程中病灶被切掉一半是常态模型学到的是残破病灶而不是完整病灶。第一轮我一般设mosaic0.25后面如果小目标漏检严重直接改成 0。3.3 轮数与早停小数据集别迷信 patienceYOLO 自带早停机制默认 patience50验证集指标 50 轮不涨就停。但在医学小数据集上验证集指标抖动比 COCO 大得多经常第 30 轮涨一点、第 45 轮又跌回去50 轮不动的判断很容易提前刹车。我一般显式设patience50但前提是学习率已经降到 0.002 附近如果 lr 还是默认的 0.01早停反而容易停在一个次优点上。另一个冷知识best.pt 是按验证集 mAP50 选的。mAP50 是通用目标检测的主指标但乳腺癌检测更关心召回率。所以训练结束后我会用 best.pt 再跑一遍验证集把 conf 阈值放到 0.15 到 0.2 重新统计一次 Recall那个数字才是模型真实能力的上限。具体怎么找阈值第 5 章单独讲。4. 乳腺影像训练踩坑记录5 条现象、原因与排查步骤4.1 现象box_loss 降到了 0.3验证集 mAP 始终接近零原因排查后通常是标注文件里混入了错误的 class_id。数据提供方导标注时可能沿用了旧表txt 里 class_id 既有 0 又有 1而 data.yaml 的 nc 是 1。模型收到两个类别标签训练 loss 照常下降但验证时类别预测一半概率落空mAP 自然接近零。解决的第一步是查脏数据grep -rE ^[1-9] train/labels/ | head -40任何第一列不是 0 的行都是脏标注。如果确认这个数据集就是单类别直接批量改写import os for root, _, files in os.walk(train/labels): for fn in files: p os.path.join(root, fn) lines open(p, encodingutf-8).readlines() fixed [] for line in lines: parts line.split() if parts and parts[0] ! 0: parts[0] 0 fixed.append( .join(parts) \n) if fixed ! lines: open(p, w, encodingutf-8).writelines(fixed) print(fixed:, fn)这个脚本只做一件事把所有非 0 的 class_id 统一改成 0不动框坐标。改完重训前再跑一次第 2.3 节的病例泄露检查因为很多脏文件其实是同一个病例的重复导出。4.2 现象微钙化簇几乎全漏大肿块全部能检出这是乳腺钼靶最常见的失败模式。YOLO 的下采样步长是 8/16/32病灶在最后几层特征图上至少要占一个网格位置太小就直接被跳过去。先量化问题有多大import cv2, glob for txt in glob.glob(val/labels/*.txt): img_file txt.replace(/labels/, /images/).replace(.txt, .jpg) img cv2.imread(img_file) if img is None: continue h, w img.shape[:2] for line in open(txt): c, cx, cy, bw, bh map(float, line.split()) pw, ph int(bw * w), int(bh * h) if pw 32 or ph 32: print(f{txt}: {pw} x {ph} px)如果小框占比超过 30%第一选择不是换模型而是提高输入分辨率。imgsz 从 640 升到 800小病灶的像素面积能多出五成以上代价是显存和推理时间各涨约三成。第二选择是关掉 Mosaic小病灶在拼接图中更容易失踪。第三选择是检查验证集标注里有没有把小病灶和大病灶混在同一张图的不同层级导致回归目标互相干扰。这些手段都试过还漏就得承认当前数据自己有一个分辨率天花板。这时应该去要更高分辨率的原始图像或者做全幅切片推理而不是继续调置信度阈值。4.3 现象推理结果里同一病灶出现十几个重叠框重复框大概率是 NMS 之前候选框没有被有效抑制常见原因一是推理时 conf 设太低二是 iou 阈值设得太小。先看每张图输出多少框yolo detect val \ modelruns/detect/train/weights/best.pt \ data/datasets/breast_ultrasound_yolo/data.yaml \ conf0.25 iou0.45 \ save_txtTrue单类别乳腺影像一张图正常情况下最多 4 到 5 个框超过 10 个就是 NMS 出了问题。解决方法是把推理的 iou 提高到 0.5 到 0.6让重叠框被压得更狠。但也有一种例外必须排除标签文件本身就带了重复框。标注工具卡顿、鼠标双击同一个框被保存两次很常见。去重脚本# dedup_boxes.py seen {} for line in open(val/labels/case_005.txt): key tuple(round(float(v), 4) for v in line.split()) seen.setdefault(key, line) open(val/labels/case_005.txt, w).writelines(seen.values())对每个标签文件都跑一遍然后用第 2.2 节的可视化脚本复查能消除一批来源不明的重复框。4.4 现象验证集指标反而比训练集好心里不踏实验证指标优于训练集先别高兴。常见原因有三个第一是数据泄露同病例的图进了双端模型相当于开卷考第二是验证集阴性图占比过高Recall 虚高、Precision 缺少参考意义第三是训练时增强开得太猛训练图像被 Mosaic 和旋转折腾得面目全非训练集上误差大验证集用的是原始图所以指标好看。排查顺序先跑第 2.3 节的 comm 命令确认没有病例重叠再统计 val 目录的阳性图占比最后把训练集增强前后的图像各抽几张并排看。如果只是 Mosaic 过猛把 mosaic 调成 0.25 或 0 重新训练验证集和训练集的差距会收敛到合理范围。4.5 现象推理时把正常腺体、钙化点当成癌框出来单类别模型的假阳性在医学图像里最恼人。原因是乳腺正常组织的密集纹理和早期癌灶在灰度上非常接近模型没见过足够多“难负样本”。排查顺序先把推理置信度从默认 0.25 提到 0.5观察漏检率是否还能接受如果 Recall 掉得厉害回头检查训练集里有没有把“边界不清的良性组织”也标成了阳性——这属于标注问题不是模型问题。最后再考虑难负样本挖掘把验证集里假阳性最高的那批图挑出来确认没有病灶后加入训练集让模型学会拒绝这些纹理区域。5. 验证集评估不看 mAP50筛查场景的指标组合与置信度调优5.1 mAP50 之外乳腺癌检测真正该看的是 RecallYOLO 训练输出的指标有 Precision、Recall、mAP50、mAP50-95。通用目标检测以 mAP50 为主评但医学筛查里漏掉一个癌的代价远大于误报一次所以乳腺癌检测的第一指标应该是 Recall0.5——也就是在默认 conf0.25 下模型能找回多少比例的真实病灶。如果 R 低于 0.85这个模型离辅助诊断还有距离。指标通用目标检测乳腺癌检测mAP50主指标参考指标Recall0.5重要首选指标Precision重要次要但要控住F2 score少用更贴近场景漏检率不大关注首要关注这张表不是标准答案而是提醒你评估前先想清楚业务目标。做筛查场景R 要大于 0.9做辅助标注场景P 要大于 0.7。同一个模型在不同的 conf 阈值下会落在 PR 曲线的不同位置所以光看训练日志里那一行数字远远不够。5.2 用 PR 曲线找最佳置信度阈值训练结束后runs/detect/train/ 下会生成 val/PR_curve.png这是找 conf 阈值的决策图。曲线上的每一个点对应一个候选框 score 阈值默认 conf0.25 在曲线上的位置偏向右下。如果只追求高召回把 conf 降到 0.15但 Precision 会掉反过来要保证 P 大于 0.6就到曲线上找对应位置那个点的横坐标就是你要用的 conf 阈值。要把这个操作量化可以跑一次推理再把预测结果重新做阈值搜索import json preds json.load(open(runs/detect/val/predictions.json)) # predictions.json 里的每条记录包含 image_id / bbox / score / category_id for t in [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]: tp, fp, fn 0, 0, 0 # 这里按 t 过滤 preds然后和真实框做 IoU 匹配 # IoU 0.5 且类别正确为 TP否则为 FPGT 未匹配到则为 FN # 算出当前阈值下的 recall 和 precision记录到一张表里这段代码骨架想说明的思路是训练日志里的指标固化了 conf0.25但实际上线时的置信度阈值可以按场景重新选。手动补全 IoU 匹配逻辑后你会得到一张“阈值-R-P”对照表再结合筛查场景要的 Recall 下限直接读出该用哪个 conf。5.3 分析错误样本的收敛模式而不只是看指标数字评估的最后一步是可视化错误样本。验证时开启 save_txt 和 save_conf预测结果会按图存成 txt。我习惯把假阴性样本单独挑出来看它们到底是微钙化簇还是大肿块是低对比度图还是被伪影覆盖的图如果假阴性全部集中在微小病灶说明输入分辨率不够回到 imgsz 而不是调阈值如果假阳性都集中在正常腺体高回声区说明需要加难负样本。这里还要提醒一句只有一个 train 和 val 的数据集val 指标只能说明模型在这套数据分布上表现如何。真要考虑上线最好再收集一批来自另一家机构、另一台设备的外部数据做双盲验证否则 val 指标再高也只是内部自评。医学图像的设备差异、采集参数差异会对模型性能造成明显影响这是数据分布问题不是调参能完全解决的。6. 数据增强与迁移学习把单类别数据集的潜力逼出来6.1 针对乳腺影像的增强开关YOLO 内置增强里hsv_h、hsv_s、hsv_v 对乳腺灰度图基本没有正面意义图上没有真实色彩随机色偏只会制造伪彩色噪声。fliplr 对乳腺图像有用左右乳在解剖结构上对称水平翻转等于免费扩充数据flipud 不建议开上下翻转会破坏解剖方向。Mosaic 在第 3.2 节已经说过先给 0.25等模型下采样到合适分辨率后才考虑调回 0。我常用的训练命令yolo detect train \ data/datasets/breast_ultrasound_yolo/data.yaml \ modelyolov8n.pt \ imgsz640 batch8 epochs300 \ lr00.002 mosaic0.25 \ hsv_h0.0 hsv_s0.0 hsv_v0.0 \ fliplr0.5 flipud0.0 \ patience50注意 hsv 全关、fliplr 留 0.5、flipud 是 0。这些开关直接放在训练命令里比改配置文件更直观重跑时一眼能看到这轮用了什么增强。6.2 两阶段迁移学习先冻结 backbone再解冻微调针对只有一两千张图的乳腺数据集我现在的习惯是两阶段训练先用冻结 backbone 的方式跑 50 轮让检测头和 neck 先学会粗定位再解冻全部层把学习率降到 0.0005 左右跑 100 轮让模型慢慢去精修病灶纹理。第一阶段的权重用 COCO 预训练模型第二阶段再加载第一阶段的 best.pt 继续训。这个做法比从头直接全层微调稳定得多尤其当数据集里不少图只有一个小病灶时先用粗定位锚住目标后面细调不会把预训练特征冲散。做医学检测这一年多我最大的教训就是收到任何数据集的第一动作永远不是提交训练任务而是可视化标注、查病例泄露、统计病灶尺寸分布。这三件不花训练时间的事帮我省下的排错时间比训练本身还多。希望帮到你。本文还有配套的精品资源点击获取