
简介YOLO民族服饰识别数据集面向目标检测入门及民族服饰相关项目开发者包含5000张真实场景高质量图片经LabelImg精细标注配套VOCxml、COCOjson、YOLOtxt三种格式标签按文件夹分类存放可直接用于训练YOLO系列检测模型。资源共2000个文件以xml标签为主1985个另有划分脚本py、说明文档html、txt列表等辅助内容压缩包约253.12MB整体结构清晰便于直接使用。附赠YOLO环境搭建Windows/Linux和训练案例教程以及训练集、验证集、测试集划分脚本可根据自身数据规模灵活划分省去格式转换与手动分集的麻烦。目前已吸引923人学习适合作为课程设计、算法实训或民族服饰识别研究的起步数据集。1. 民族服饰识别为什么值得用 YOLO 做一遍一份带三种格式标签的 5000 张数据集民族服饰识别这个方向数据一直比模型更卡脖子。翻遍公开数据集行人、车辆、COCO 那二十来类随手就有但你想数清一件苗族盛装上的银饰、识别一件蒙古袍的滚边基本只能自己攒图、自己标。这份 YOLO 民族服饰识别数据集含5000张图片对应voc、coco和yolo三种格式标签划分脚本训练教程.rar 补齐的正是这个缺口5000 张带框标注的服饰图片VOC、COCO、YOLO 三种标签格式全给齐划分脚本和训练教程一并附上解压就能往 YOLOv5/YOLOv8 的管线里喂。适合非遗数字化展示的工程团队、做电商或博物馆服饰检索的产品同学以及想拿真实垂直数据练手的目标检测初学者。这套数据的价值不在于类别多而在于样本垂直、标签统一、流程配套省掉的是你做数据集最耗时的三个环节标注、转格式、划分。2. 拆开 .rar 看数据形态VOC、COCO、YOLO 三种标签格式的字段与取舍拿到压缩包直接双击解压然后开训是新手最常见的急躁动作。我的建议是先花十分钟把目录结构和标签格式看明白因为后面所有训练报错、评估偏差八成都能在这十分钟里找到答案。这一章就把这套资源包里最核心的三种标签格式拆开讲清楚。2.1 解压后先看目录结构别急着开训练这套资源常见做法是解压出几块内容一个放原图的目录、三个放标签的目录或一个目录里按 VOC/COCO/YOLO 再分子目录、一个划分脚本、一份训练教程文档。原图和标签的组织方式决定了你后续训练时 data.yaml 怎么写、图片清单怎么生成所以先整体过一遍确认下面三件事。第一确认图片和标签的命名是否一一对应。YOLO 格式要求标签文件名与图片名完全一致只是扩展名从.jpg变成.txt如果解压后发现多出来一些没有标签的图片或者有标签找不到对应图片这就是后面训练报错的地雷。第二确认 VOC 目录里是否有JPEGImages、Annotations和ImageSets/Main这三个子目录其中Annotations里的 XML 是否包含size节点——没有width和height的 XML 在转 YOLO 时没法做归一化。第三确认 COCO 的 JSON 文件里images、annotations、categories三段是否都有内容images里每张图的width/height是否正确。这套数据一次性给出三种格式很多人不理解为什么这么重复。其实这是为不同工具链准备的VOC 格式适合在 labelImg 里继续改标注、也适合视觉化核对COCO 格式是 Detectron2、MMDetection 这类框架的标准入口YOLO 格式则是直接喂给 YOLO 系列训练的最小单元。你如果只用 YOLO就用它的 TXT如果后续要换框架对比COCO 的 JSON 不用再做二次转换。2.2 三种格式的字段对比坐标体系与类别表达三种格式的核心差异是坐标体系和类别表达方式理解了这两点后面任何转换脚本都不会看懵。对比项VOCXMLCOCOJSONYOLOTXT标注载体每张图一个 XML 文件整个数据集一个 JSON每张图一个 TXT 文件框坐标xmin, ymin, xmax, ymax绝对像素x, y, width, height绝对像素class, cx, cy, width, height归一化 0~1类别写法name字符串category_id 整数 categories 映射每行行首整数图片关联filename标签image_id 指向 images 数组文件名与图片同名典型适用labelImg、VOC 评测体系Detectron2、MMDetectionYOLO 系列原生训练VOC 的 XML 里size存的是图片宽高object下每个name是类别名bndbox里四个坐标是绝对像素值其中xmax/ymax表示矩形最右下角像素的坐标这一点在转格式时很关键后面第 4 章会展开讲。COCO 的 JSON 里annotations数组中的bbox是[x, y, width, height]前两个值是左上角坐标category_id是一个整数需要到categories数组里反查类别名它比 VOC 多一层image_id关联所以从 COCO 转 YOLO 需要维护一张「image_id → 图片路径」的映射表。YOLO 的 TXT 最简单每行五个数字第一个是类别编号后四个是归一化后的中心点 x、中心点 y、宽、高取值都在 0 到 1 之间训练时框架直接读这些相对坐标省去再查图片尺寸的步骤。2.3 用框画在图上核对一遍可视化是检验标签的唯一标准不管是压缩包自带的标签还是你自己转出来的标签开训练之前我强烈建议先抽几十张图把框画出来看一眼。标注错位、坐标比例不对、类别顺序乱了光看数字是看不出来的画出来一眼就暴露。下面这段脚本读 YOLO 格式的 TXT 并画框可以用来检查这套资源里 YOLO 目录的标签质量。import cv2 # 读取 YOLO 格式的 txt把归一化坐标折算回像素并画框 def draw_yolo(img_path, txt_path, class_names, out_pathcheck.jpg): img cv2.imread(str(img_path)) h, w img.shape[:2] with open(txt_path, encodingutf-8) as f: for line in f: parts line.split() if len(parts) 5: continue cls, cx, cy, bw, bh map(float, parts[:5]) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) color (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[int(cls)], (x1, max(0, y1 - 8)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imwrite(out_path, img) print(已输出:, out_path) # 用法示例路径按你解压后的实际目录改 draw_yolo(images/0001.jpg, labels_yolo/0001.txt, [头饰, 银饰, 袍服, 绣片])这段脚本的核心是把 TXT 里归一化后的中心点坐标乘回图片宽高再换算成左上角和右下角。参数说明cls是类别编号必须和后面训练用的data.yaml里names的顺序一致cx/cy/bw/bh是归一化值如果图片本身被缩放处理过这里计算出的框会整体偏移。我一般会在 VOC、COCO、YOLO 三种标签里各随机抽 30 张来画看同一张图在三种格式下画出的框是否一致——这套数据既然声称「对应」三种格式那它们之间的框应该完全重合如果发现某个格式的框明显错位直接弃用那个目录别将就着训。3. 划分脚本怎么用train/val/test 比例、随机种子与类别平衡压缩包附带划分脚本的目的是把 5000 张图切成训练集、验证集和测试集。但实际用下来很多人直接跑完脚本就开训结果 val 里某个类别一条都没有训练时这个类永远不更新最后模型对这类服饰完全无感。这一章教你把划分脚本用对而不是只用「能跑」。3.1 为什么要自己再划分一遍随机种子与划分比例的坑压缩包自带的划分脚本常见做法是按 8:1:1 或 7:2:1 的比例随机切分然后生成train.txt、val.txt、test.txt三个图片清单文件。它本身没问题但你直接依赖它有两个隐患。第一脚本里的随机种子不固定每次运行划分结果都不同你今天训的模型和明天训的模型用的验证集不一样评估结果没法对比复现。第二全局随机切分只保证「图片总数」的比例不保证「每个类别」的比例。举个例子5000 张图里如果某个民族服饰类别只出现了 40 张全局随机切分有概率把 30 张分到 val、10 张分到 train训练集里这个类几乎没有正样本。所以无论压缩包脚本写得多好我都建议自己写一遍划分逻辑至少要做到三点固定SEED、按类别分层、划分后做数量核对。3.2 分层划分脚本按类别分桶避免小类目在验证集里消失下面是一个按「类别组合」分桶的分层划分脚本它先统计每张图片包含哪些类别再把包含同一组类别的图片放进同一个桶最后在每个桶内部按比例切分。这样即使某个类别只出现几十次它也会均匀地落入 train、val、test 三个子集不会整体跑到某一边。import random from collections import defaultdict from pathlib import Path IMG_DIR Path(images) # 原图目录 LAB_DIR Path(labels_yolo) # YOLO 格式标签目录 RATIO [0.8, 0.1, 0.1] # train / val / test 比例 SEED 42 # 固定随机种子保证可复现 random.seed(SEED) buckets defaultdict(list) # 第一遍按图片包含的类别组合分桶 for img in sorted(IMG_DIR.glob(*.jpg)): txt LAB_DIR / (img.stem .txt) if not txt.exists(): print(跳过无标签图片:, img.name) continue # 读取该图包含的所有类别编号拼成一个字符串作为桶的 key cls_set {line.split()[0] for line in txt.read_text(encodingutf-8).splitlines() if line.strip()} buckets[|.join(sorted(cls_set))].append(img) # 第二遍在每个桶内部按比例随机切分 train, val, test [], [], [] for key, imgs in buckets.items(): random.shuffle(imgs) n_train int(len(imgs) * RATIO[0]) n_val int(len(imgs) * RATIO[1]) train imgs[:n_train] val imgs[n_train:n_train n_val] test imgs[n_train n_val:] # 输出图片清单供 YOLO 训练时指定 train/val for name, part in [(train, train), (val, val), (test, test)]: with open(f{name}.txt, w, encodingutf-8) as f: f.writelines(str(img.resolve()) \n for img in part) print(f{name}: {len(part)} 张)逻辑说明第一遍遍历所有图片时先检查同名 TXT 是否存在不存在就跳过并打印提示这一步是为了避免把没有标签的图片带进训练集。然后读取每张图包含的类别编号集合用|连接成字符串作为桶 key比如某张图同时含类别 0 和类别 2它的 key 就是0|2。第二遍在每个桶内部先随机打乱再按RATIO依次切出三份这样包含稀有类别的桶也会按同样比例拆分。参数说明RATIO里的三个值建议根据任务规模改。5000 张图、类别数量不多时8:1:1 够用如果后续要做模型选型对比可以改成 7:2:1给验证集多留一点样本评估指标更稳。SEED务必固定你复现实验、换超参数重训时训练集和验证集不变跑出来的指标差异才能归因到模型改动上。图片扩展名如果混有.png把IMG_DIR.glob(*.jpg)改成同时遍历多种后缀比如exts (*.jpg, *.jpeg, *.png) imgs [p for ext in exts for p in IMG_DIR.glob(ext)]3.3 划分后必做的三件事数量核对、类别分布核对、路径对账划分脚本跑完不算完下面三步缺一不可。第一步数量核对train、val、test三个清单里的图片数加起来要等于有效图片总数也就是「有标签的图片」数量不是 5000如果差很多说明有图片没进桶回头看是否扩展名不匹配或标签缺失。第二步类别分布核对统计每个子集里各类别的框数确保 val 和 test 里每个类别至少有一条标注否则验证指标会虚高或虚低。from collections import Counter from pathlib import Path LAB_DIR Path(labels_yolo) def class_distribution(img_list_file): dist Counter() for line in open(img_list_file, encodingutf-8): img_path Path(line.strip()) txt_path LAB_DIR / (img_path.stem .txt) if not txt_path.exists(): continue for row in txt_path.read_text(encodingutf-8).splitlines(): if row.strip(): dist[int(row.split()[0])] 1 return dist for split in [train, val, test]: d class_distribution(f{split}.txt) print(split, dict(d))这段脚本第三处关键点在路径对账上面划分脚本输出的是img.resolve()的绝对路径如果你解压后又移动了文件夹train.txt里记录的旧路径就全部失效训练时会报找不到图片。我通常会把划分脚本和数据集放在同一个根目录下运行并且在移动数据集后重新执行一遍划分绝不手动改清单文件里的路径。Windows 用户尤其注意解压路径和图片路径都不要带中文YOLO 相关框架对中文路径的支持时好时坏与其花一下午排错不如一开始就用英文目录。4. 把 VOC 转成 YOLO转换脚本与四个边界坑这一章是整套资源里最容易被卡住的环节。很多人拿到手后只用了 YOLO 格式的目录VOC 目录放着吃灰。但如果你后续要用 labelImg 补充标注或者从别的项目里拿了一批 VOC 数据要合并进来就必须自己完成 VOC 到 YOLO 的转换。转换本身没难度难得是四个边界情况处理不好轻则 mAP 下降重则 loss 直接 NaN。4.1 转换流程与核心脚本VOC 转 YOLO 的流程可以用一句话概括从 XML 里读出类别名和绝对坐标再除以图片宽高得到归一化的类别编号、中心点和宽高。下面这个脚本可以直接套用它会遍历一个Annotations目录下所有 XML输出同名的 YOLO 格式 TXT 到yolo_labels目录。import xml.etree.ElementTree as ET from pathlib import Path VOC_ANN Path(VOC/Annotations) # VOC XML 目录 YOLO_LAB Path(yolo_labels) # 输出目录 YOLO_LAB.mkdir(exist_okTrue) # 类别表按首次出现的顺序构建跑完后务必保存一份 CLASSES [] def class_id(name: str) - int: if name not in CLASSES: CLASSES.append(name) return CLASSES.index(name) def voc2yolo(xml_file: Path): tree ET.parse(xml_file) root tree.getroot() size root.find(size) if size is None: print(缺少 size 节点跳过:, xml_file.name) return img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) w xmax - xmin h ymax - ymin if w 0 or h 0: # 过滤空框和零宽高框见 4.2 continue cx (xmin w / 2) / img_w cy (ymin h / 2) / img_h nw w / img_w nh h / img_h lines.append(f{class_id(name)} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}) out YOLO_LAB / (xml_file.stem .txt) out.write_text(\n.join(lines) \n, encodingutf-8) for xml_file in sorted(VOC_ANN.glob(*.xml)): voc2yolo(xml_file) # 保存类别表后面写 data.yaml 的 names 时必须用同一顺序 with open(classes.txt, w, encodingutf-8) as f: f.write(\n.join(CLASSES))逻辑说明脚本先读size节点拿到图片宽高这是归一化的分母分母出错后面整个坐标体系全错。然后遍历所有object把每个bndbox里的四个角点坐标换算成中心点加宽高的表示公式是中心点x (xmin w/2) / img_w宽w就是xmax - xmin。最后把类别名通过class_id()映射成整数编号。参数说明VOC_ANN和YOLO_LAB两个路径要按实际解压目录改。CLASSES这个列表的顺序完全取决于 XML 的遍历顺序不同脚本版本可能得到不同顺序所以脚本最后必须把classes.txt保存下来后面第 4.4 节会展开讲这个顺序的坑。如果你是复跑这个脚本建议先清空yolo_labels目录再跑避免上次残留的同名 TXT 干扰判断。4.2 边界坑一空框与零宽高框现象转换脚本跑完不报错但你拿第 2 章的画框脚本一看发现个别图上有个点或者训练到第二个 epoch loss 突然变成 NaN。原因标注工具可能留下xmin等于xmax或ymin等于ymax的脏框这类框算出来宽度或高度为 0归一化后还是一条线训练时它的损失贡献会出问题。另一类更隐蔽XML 里可能直接出现负数坐标或未闭合的bndbox坐标缺失时float()读出来是空字符串直接异常。解决转换脚本里加一行过滤if w 0 or h 0: continue这是最常见的解法。如果不想静默丢弃可以把这些异常框打印出来人工去标注软件里修掉。我的习惯是过滤掉但不删 XML 原文件只在转换阶段跳过因为原文件可能还有别的正确标注删了反而丢信息。4.3 边界坑二归一化越界与 clip 策略现象训练完 val 的 bad case 里很多预测框贴在图片边缘或者 mAP 明明不低但看检测结果框的中心点离目标差一大截。原因部分标注框略微超出图片边界比如标注时手抖把xmax拉到了图片宽度之外归一化后cx大于 1 或者nw大于 1。YOLO 训练时这类框不会报错但它会在特征图上对应到不存在的区域把模型训歪。解决在转换时对归一化坐标做 clip把值限制在 0 到 1 之间。下面的写法放在cx/cy/nw/nh计算之后cx max(0.0, min(1.0, cx)) cy max(0.0, min(1.0, cy)) nw max(0.0, min(1.0, nw)) nh max(0.0, min(1.0, nh))注意 clip 不是万能的。如果原框绝大多数面积在图内clip 只是把越界的边收回来影响很小如果整个框都在图外clip 之后框会贴到图片边缘这种图应该直接删掉而不是强行保留。我会在转换脚本里统计越界框的数量超过 1% 就回头检查是不是某个标注文件整体偏移了这通常不是手抖而是图片和标注不是同一版本。4.4 边界坑三类别顺序错位是「静默事故」现象loss 正常下降训练 mAP 也不差但推理时把「银饰」预测成「头饰」把甲民族的服装预测成乙民族而且错的规律很一致。原因这是最隐蔽的坑。VOC 转 YOLO 时CLASSES列表按照某个顺序生成但你后来写data.yaml的names时可能按自己的想法重新排了序或者参考了另一份文档里的类别表两边顺序不一致。YOLO 训练只认整数编号它不会检查编号和类别名的对应关系于是模型学到的「类别 0」在你的names里显示成另一个名字所有预测类别整体错位。解决转换脚本跑完后把classes.txt保存下来data.yaml里的names直接一行一行对照它填不要凭记忆重排。这也是为什么我建议在转换阶段就用「固定顺序」而不是「首次出现顺序」构建类别表。如果项目里已经有官方类别列表就先按它初始化CLASSES再在转换时对未知类别报错这样能及早发现问题。血泪经验我踩过两次这个坑每次都是训练跑了一整天才发现预测类别错位返工成本太高了。4.5 边界坑四EXIF 旋转导致框图错位现象训练集里某几张图标注框看起来和内容对不上但只有部分图片这样同一张图用不同看图软件打开横竖方向都不一样。原因手机或部分数码相机拍摄的图片带有 EXIF Orientation 信息标注软件可能按旋转后的方向显示图片来标框但 OpenCV 的imread()默认不应用 EXIF 旋转直接把原始像素读进来框和像素就错位了。这个坑在包含手机拍摄样本的民族服饰数据集里非常常见因为你不可能每张图都用单反拍。解决在做数据集前先统一图片方向把 EXIF 旋转批量落掉。用 PIL 一行就能处理from PIL import Image, ImageOps img Image.open(images/0001.jpg) if img.getexif().get(274, 1) ! 1: # 274 是 Orientation 字段 img ImageOps.exif_transpose(img) img.save(images_normalized/0001.jpg, quality95)逻辑说明getexif().get(274, 1)读取旋转状态值为 1 表示不需要旋转其他值代表不同角度的旋转exif_transpose()会按 EXIF 信息把图片转正。参数说明quality95是 JPEG 保存质量转正后再次压缩会损失一点画质对检测任务影响很小但如果你后续要做精细的纹理分类建议保存成 PNG 无损格式。做完批次处理后VOC 标注里的坐标也要基于转正后的图片重新核验这个坑只能人眼抽查没有捷径。5. 训练 YOLO 的常见问题排查标签错位、类别不平衡、过拟合训练民族服饰识别和训练 COCO 这种成熟数据集的最大区别是没有太多现成的坑替你踩过。标签错位、类别不均衡、背景过拟合每一条单拎出来都不致命凑在一起就是反复翻车的玄学现场。下面五条是我在类似垂直数据集上真实遇到过的现象、原因和解决顺序你可以直接照着排查。5.1 现象loss 降得很好但预测框全偏loss 曲线一直在降训练集上画框也正常一验证就发现框偏了半个身位或者预测框大小明显不对。先别调模型按顺序查两件事第一把训练用的图片和验证用的图片用同一个可视化脚本画一遍框看是不是某些图标签本身就偏第二检查转换脚本里归一化时用的宽高是不是来自size节点如果你用了别的代码库读取图片宽高而那套代码读的图片被预处理缩放过所有坐标都会按错误缩放比偏移。这个问题的特征是有规律偏移比如所有框都偏大 20%那基本就是归一化分母错了而不是模型问题。5.2 现象某个民族服饰类别一个都检测不到训练完测试别的类都不错唯独某一种服饰的召回率是 0。原因通常是两类一种是这个类别在训练集里框太少目标检测按图片数统计一个类别只有二三十个框模型很难学到稳定的特征尤其民族服饰里有些类别本身外观相似比如不同支系的银饰造型接近样本少就更难区分。另一种是这个类别被划分脚本全部分到了 val 或 test训练时压根没见过。解决很简单回到第 3 章用分层划分脚本重新切一遍然后统计每个类在 train 里的框数建议每个类至少 100 个框再开训。如果框数实在太少可以考虑对该类做离线增强比如对包含该类别的图做水平翻转、随机裁剪、亮度抖动扩充到 300 个框以上。5.3 现象训练集 mAP 高验证集掉一半这就是典型的过拟合5000 张图说多不多说少不少尤其某类样本少时模型很容易记住训练图的背景而不是服饰本身。民族服饰数据集有个通病很多图是在展厅、舞台、摄影棚拍的背景高度单一模型可能靠「台子」「灯光」来识别换到街头穿着的场景就露馅。解决方向有几个优先级从高到低开大 mosaic 和 mixup 增强让模型没法依赖完整背景调大weight_decay让模型权重别撑太大把epochs降低配合早停在验证集最优时就停。个人经验是遇到这类现象先别急着换骨干网络数据增强的收益通常最直接。5.4 现象Windows 下训练到一半报 FileNotFoundError训练跑了几百个 step突然报找不到某张图路径里还带着中文或者超长目录。原因基本就三类一是解压后的目录路径太长Windows 默认路径长度限制会截断二是图片或目录名里有中文部分版本的 YOLO 依赖库在读取时对中文路径支持不完整三是你移动过数据集train.txt里的绝对路径还指向旧位置。解决把整个数据集放到一个纯英文的短路径下比如D:\dataset\重新运行划分脚本生成新的清单文件再训练。如果是路径长度问题可以试试开启 Windows 的 LongPathsEnabled但不建议依赖它治标不治本。5.5 现象换预训练权重后前几轮 loss 是 NaN第一次用 YOLO 训练自己的数据集很多人会直接下载 COCO 预训练权重来迁移但忘了改模型的类别数。YOLOv8 这类框架加载预训练权重时如果data.yaml里的nc和权重里不一致前向传播输出维度对不上前几轮 loss 直接 NaN。还有一种情况是nc改对了但学习率设太高自定义数据集类别少、样本分布和 COCO 差异大从 0.01 起步可能直接发散。解决第一次迁移训练前严格核对data.yaml里的nc和names的顺序如果还不行就把lr0从默认值降到 0.001 重新试。损失函数这一块建议先用默认配置CIoU 在绝大多数检测任务上都够用不要一上来就换等基线跑通再考虑替换。6. 用 YOLO 训练民族服饰识别的参数调整与验证技巧6.1 服饰类目标的超参数起点这套数据集的难点主要集中在头饰、银饰、绣花这类小目标上所以超参数起点和通用检测任务略有不同。下面是我在类似垂直数据集上常用的起点你可以先按这个跑一轮再调。参数起点值说明imgsz640显存够用就上 1280小目标召回会明显改善batch显存能装多大就多大类别差异细batch 太小 BN 统计不稳epochs100~1505000 张图不算大类别少时 100 轮基本收敛lr00.001~0.01自定义数据集建议从 0.001 起步稳定后再调大lrf0.01余弦退火到初始学习率的 1%防止后期震荡weight_decay0.0005类别少、样本少时正则化要跟上训练命令按 YOLOv8 的常规写法指定数据配置文件和预训练权重即可。无论你用 YOLOv8 还是 YOLOv5 训练自己的数据集喂进去的都是前面划分好的train.txt和val.txt区别只在框架内部的数据读取逻辑目录结构不用改。yolo detect train datadataset.yaml modelyolov8n.pt imgsz640 epochs100 batch166.2 用混淆矩阵定位易混类别训练结束后先别急着看 mAP 总指标跑一轮验证并打开混淆矩阵yolo detect val modelruns/detect/train/weights/best.pt datadataset.yaml验证结果目录里会生成confusion_matrix.png和confusion_matrix_normalized.png。重点看哪两个服饰类别互相串比如「袍服」和「披风」、「银饰」和「头饰」经常混就把这些 bad case 单独导出来人工核对一遍。很多人会问为什么混淆矩阵每行总合不唯一未归一化版本是计数矩阵行和列自然不相等归一化版本按每类真实框总数归一每行和为 1你如果拿的是未归一化图看到行和不一致很正常。我自己每次跑完一轮必看三样东西按类别分的 PR 曲线、归一化混淆矩阵、bad case 图。数据集的坑八成在标签不在模型先查完再调参否则容易把本来合适的超参调坏。这套数据带三种格式标签就是要让你能互相校验用 VOC 画一遍、用 COCO 画一遍、用 YOLO 画一遍三份框一致才说明标签可信。希望这个流程能帮你在民族服饰识别上少走弯路。本文还有配套的精品资源点击获取