☰
YOLO民族服饰识别数据集:VOC/COCO/YOLO三种格式与训练实战
2026/10/2 19:07:06 网站建设 项目流程

简介:YOLO民族服饰识别数据集面向目标检测入门及民族服饰相关项目开发者,包含5000张真实场景高质量图片,经LabelImg精细标注,配套VOC(xml)、COCO(json)、YOLO(txt)三种格式标签,按文件夹分类存放,可直接用于训练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 三种格式的字段对比:坐标体系与类别表达

三种格式的核心差异是坐标体系和类别表达方式,理解了这两点,后面任何转换脚本都不会看懵。

对比项VOC(XML)COCO(JSON)YOLO(TXT)
标注载体每张图一个 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_path="check.jpg"): img = cv2.imread(str(img_path)) h, w = img.shape[:2] with open(txt_path, encoding="utf-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(encoding="utf-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", encoding="utf-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, encoding="utf-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(encoding="utf-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_ok=True) # 类别表:按首次出现的顺序构建,跑完后务必保存一份 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", encoding="utf-8") for xml_file in sorted(VOC_ANN.glob("*.xml")): voc2yolo(xml_file) # 保存类别表,后面写 data.yaml 的 names 时必须用同一顺序 with open("classes.txt", "w", encoding="utf-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", quality=95)

逻辑说明:getexif().get(274, 1)读取旋转状态,值为 1 表示不需要旋转,其他值代表不同角度的旋转,exif_transpose()会按 EXIF 信息把图片转正。参数说明:quality=95是 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 data=dataset.yaml model=yolov8n.pt imgsz=640 epochs=100 batch=16

6.2 用混淆矩阵定位易混类别

训练结束后,先别急着看 mAP 总指标,跑一轮验证并打开混淆矩阵:

yolo detect val model=runs/detect/train/weights/best.pt data=dataset.yaml

验证结果目录里会生成confusion_matrix.png和confusion_matrix_normalized.png。重点看哪两个服饰类别互相串,比如「袍服」和「披风」、「银饰」和「头饰」经常混,就把这些 bad case 单独导出来人工核对一遍。很多人会问为什么混淆矩阵每行总合不唯一,未归一化版本是计数矩阵,行和列自然不相等;归一化版本按每类真实框总数归一,每行和为 1,你如果拿的是未归一化图,看到行和不一致很正常。

我自己每次跑完一轮,必看三样东西:按类别分的 PR 曲线、归一化混淆矩阵、bad case 图。数据集的坑八成在标签不在模型,先查完再调参,否则容易把本来合适的超参调坏。这套数据带三种格式标签就是要让你能互相校验,用 VOC 画一遍、用 COCO 画一遍、用 YOLO 画一遍,三份框一致才说明标签可信。希望这个流程能帮你在民族服饰识别上少走弯路。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询