尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
YOLO数据集制作与模型训练全流程详解:从标注到调优
很多人第一次接触目标检测都是从YOLO开始的。但真正动手做项目的时候才会发现跑通官方自带的推理Demo只是第一步最磨人的其实是数据集制作这一关。我当时第一次做自己的检测任务时光是在“标注完图片之后怎么变成YOLO认识的格式”这一步就卡了整整两天后来靠逐个打开标签文件手动核对才搞清楚问题出在哪。这篇文章就围绕YOLO数据集的制作与模型训练整条链路展开把图片采集、标注、格式转换、目录组织、参数配置、训练调优这些环节全部拆开来讲。不管你是刚装好环境的新手还是被自己数据集折磨得头疼的初级开发者都可以对照这篇文章把整个流程完整跑通。1. 先弄懂YOLO数据集的格式后面才不会返工1.1 txt标签文件到底在表达什么YOLO系列模型读取的标签不是XML也不是JSON而是跟每张图片同名的纯文本文件后缀是txt。每一行对应图片里的一个目标格式固定为五个数字类别ID、归一化中心点x、归一化中心点y、归一化宽度、归一化高度也就是class_id cx cy w h。我举个例子你就明白了。假设一张宽640、高480的图片里有一个人在图片中间偏左的位置他的框左上角坐标是(160, 120)右下角坐标是(320, 240)。那么中心点x就是(160320)/2240归一化之后就是240/6400.375中心点y是(120240)/2180归一化之后是180/4800.375宽度是320-160160归一化是160/6400.25高度是240-120120归一化是120/4800.25。如果“人”这个类别的ID是0这一行就写成0 0.375 0.375 0.25 0.25。为什么要用归一化坐标因为图片尺寸在训练过程中会被统一缩放到640x640之类的固定大小坐标跟着图走会被拉伸变形归一化之后就完全不受图片原始尺寸影响不管原图是手机拍的还是监控截图模型看到的都是同一套坐标系这样处理既稳定又省内存。还有两个细节必须记住类别ID从0开始计数不是从1开始类别ID的顺序必须和数据集配置文件里的names列表完全一致。很多初学者在这里栽跟头自己在标注工具里把“人”放在第二位结果配置文件里写成了第一位训练出来模型把人也认成车完全错位。1.2 为什么标注质量直接决定模型上限这个道理说起来简单但很多人直到训练完才发现。模型训练的本质是让网络去拟合你给的标签分布标签错了模型学到的就是错误映射标注里的噪声会直接变成模型预测的误差。比如你把人的框画得很松把背景墙面都包进去了模型就会把墙面纹理当成人的特征一起学进去推理时遇到相似的墙面就可能误报。数据量少的时候标注质量的影响会被进一步放大。几十张图片里只要有一两张框画歪了损失函数就会被这几张带偏训练出来的模型精准度肉眼可见地下降。我自己的经验是几百张高质量标注的效果往往优于几千张随手画的粗糙标注。宁可少标一点也要保证每张图、每个框都经得起推敲。2. 图片采集与标注动手之前先把规则定好2.1 图片采集的三个硬性要求采集图片看起来谁都会但实际上很多项目数据翻车就是翻在这一步。第一个要求是场景多样性。同一类物体要在不同光线、不同角度、不同距离、不同背景下各拍一些。比如检测车辆白天晚上、晴天雨天、正面侧面、近景远景都要覆盖这样模型才能学到物体本身的结构特征而不是把“某个固定场景的颜色”当成物体特征。第二个要求是目标尺度多样性。一张图里既要有占画面很大一部分的大目标也要有只占几十个像素的小目标。YOLO是在多个尺度特征图上做检测的如果你的训练数据全是大目标模型的小目标检测能力就几乎为零测试时遇到远处小目标基本漏检。第三个要求是不要图省事只从同一个渠道抓图。全网铺天盖地用同一批公开图片训练出来的模型换到自己实际场景里泛化能力很差。最好的做法是拿自己在真实业务场景里拍的、带现场光照和背景噪声的图片再拿一部分公开图片做补充混合起来用。每类目标建议至少准备100到200张图片起步场景复杂、目标形态多变的类别还需要更多。另外在动手标注之前一定要先商量或者自己想清楚一个规则目标被遮挡了一部分框怎么画我的习惯是只框可见部分并且保持全数据集统一不要这张图把遮挡部分也框上那张图又不框。2.2 标注工具的选择与操作细节YOLO数据集标注最常用的工具是开源的LabelImg免费、轻量、支持Windows和Linux可以直接导出YOLO格式的txt对入门阶段来说足够了。操作流程很简单第一步建立图片文件夹和标签保存文件夹第二步打开LabelImg点击左侧的文件夹图标选择图片目录再指定标签保存目录第三步按快捷键W进入画框模式在目标四周拖出矩形框会弹窗让你输入类别名第四步画完一张按CtrlS保存按A或D切换上一张下一张。我建议在第一张图开始标注前先手动创建好一个classes.txt文件把所有类别名列进去然后用它预加载类别列表。这样画框的时候直接选类别不用每次手动输入还能防止类别名大小写不一致这种隐藏Bug比如“Person”和“person”在程序眼里是两个完全不同的类。还有一类工具适合做更精细的标注比如要对物体做多边形轮廓标注或者标注旋转矩形框可以用开源的labelme。另外如果多个人协作标注同一个数据集也可以考虑一些在线标注平台优点是方便分工和进度管理缺点是需要上传数据看你的业务能不能接受。2.3 标注的常见坑标注这件事不复杂但非常考验耐心坑也基本都是细节上的。第一个坑是框画得太松太紧。太松把背景包进来太紧会把目标的关键特征切掉比如检测人的时候框顶把人头截掉一半模型就会学到一个缺了脑袋的人形特征推理时遇到完整的人也容易框不准。正确做法是让框紧密贴合目标轮廓保留完整特征。第二个坑是漏标。一个场景里同时出现多个人和多个瓶子有些人标了有些人没标模型就会很困惑尤其是那些没标出的目标相当于被模型当成了背景负样本长期这样会在推理时提高漏检率。第三个坑是类别混淆。两个外观特别相似的类别比如不同厂家的相似包装盒如果它们确实需要区分那标注时一定要认真看如果实在难区分建议合并成一个大类等后续能稳定区分了再拆开。第四个坑是边界框超出图像范围。标注工具里鼠标稍微拖出图片边缘坐标就可能大于图片实际尺寸转换出来的归一化坐标会出现大于1的值训练时会直接报错或者产生诡异的loss。后面我会讲怎么用脚本批量检查这种问题。3. 目录组织与格式转换把原始标注变成YOLO能读的结构3.1 标准目录结构与data.yamlYOLO要求的目录结构很固定不建议自己发挥。最常用的是这样dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/图片放在images下的train和val里对应的标签文件放在labels下的同名目录里。关键规则是标签txt文件必须和图片文件同名只是扩展名不同。比如图片叫001.jpg标签就必须叫001.txt不能多一个少一个字符。另外图片和标签要严格一一对应不能出现有图片没标签或者有标签没图片的情况否则训练程序会报警告甚至跳过样本。在数据集根目录放一个data.yaml配置文件内容大致如下path: /your/absolute/path/dataset train: images/train val: images/val names: 0: person 1: car 2: bicyclepath建议写绝对路径避免因为当前工作目录不一致而找不到数据。names这个列表的顺序决定了类别ID的含义前面说过它必须和你标注时的类别顺序完全一致训练前务必逐行核对一遍。3.2 从VOC格式转成YOLO格式的脚本很多人在用LabelImg时习惯性选了PascalVOC格式也就是输出XML文件。没关系写一个小脚本就能批量转换成YOLO格式。转换脚本的核心逻辑是从XML里读出图片宽高和每个目标的框坐标把左上角和右下角坐标换算成归一化中心点加宽高。import os import xml.etree.ElementTree as ET # 这里必须和 data.yaml 里的 names 顺序完全一致 classes [person, car, bicycle] def convert_annotation(xml_path, out_txt): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in classes: continue cls_id classes.index(name) box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) # 有些标注工具可能把坐标写反先做最小值最大值处理 x1, x2 min(x1, x2), max(x1, x2) y1, y2 min(y1, y2), max(y1, y2) cx (x1 x2) / 2 / img_w cy (y1 y2) / 2 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h # 防止边界框越界导致归一化坐标超过 1 cx min(max(cx, 0.0), 1.0) cy min(max(cy, 0.0), 1.0) w min(w, 2 * min(cx, 1 - cx)) h min(h, 2 * min(cy, 1 - cy)) if w 0 and h 0: lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines)) xml_dir annotations txt_dir labels os.makedirs(txt_dir, exist_okTrue) for xml_name in os.listdir(xml_dir): if not xml_name.endswith(.xml): continue base xml_name[:-4] convert_annotation( os.path.join(xml_dir, xml_name), os.path.join(txt_dir, base .txt) )这段脚本里我对坐标做了防越界处理这是我在实际项目里踩坑之后加上的。当时标注的图片边缘目标框略微超界生成的txt里宽度是负值训练到一半loss直接变成nan。所以转换这步一定要把坐标做边界约束哪怕是裁剪掉一点边界信息也比让训练崩溃强。3.3 转换后的校验方法转换完不能直接开训我强烈建议先校验一遍。最直观的方法是写一个小脚本把txt里的框画回图片上肉眼检查框的位置、大小和类别是否正确看个几十张就能发现大多数问题。另一个快速检查的办法是扫描标签文件里的数值范围import os def check_label(txt_path): with open(txt_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(字段数量不对:, txt_path, line) continue c, cx, cy, w, h map(float, parts) if not (0 cx 1 and 0 cy 1): print(中心点越界:, txt_path, line) if w 0 or h 0: print(宽高非法:, txt_path, line) for txt_name in os.listdir(labels): check_label(os.path.join(labels, txt_name))除此之外还要统计每个类别的目标数量。如果某个类别只有几十个目标而其他类别有几千个这个类基本就废了训练时模型会优先学大类的特征。类别数量分布统计下来之后才能决定是继续补数据还是考虑类别加权。3.4 训练集与验证集的划分策略图片和标签都准备好了接下来要划分训练集和验证集。常见比例是8比2或9比1用随机抽样的方式划分即可。但有两个原则要注意一是同一场景的连续截图不要同时分进训练集和验证集比如几秒钟内连续拍的同一辆车的多帧画面如果两边都有验证集就失去了独立评估的意义测出来的指标会虚高二是保证每个类别在验证集里都有一定的样本量特别是稀有类别如果验证集里根本没有这个类那这个类的检测指标就无从评估。写个简单的脚本就能完成划分关键是用固定的随机种子保证划分结果可复现import os import random from shutil import copy2 src all_images train_dir dataset/images/train val_dir dataset/images/val os.makedirs(train_dir, exist_okTrue) os.makedirs(val_dir, exist_okTrue) files [f for f in os.listdir(src) if f.lower().endswith((.jpg, .jpeg, .png))] random.seed(42) random.shuffle(files) val_count int(len(files) * 0.2) for f in files[:val_count]: copy2(os.path.join(src, f), val_dir) for f in files[val_count:]: copy2(os.path.join(src, f), train_dir)注意图片拷过去之后对应的txt标签也要同步拷贝到labels目录下对应子目录两边不能错位。拷贝完记得比对一下两边文件名集合是否一致这一步很基础但漏做会导致训练时大量图片没有标签白白浪费时间。4. 训练环境配置与模型训练实操4.1 环境搭建的最低要求训练YOLO对硬件的要求不算高但不代表没要求。个人电脑建议显卡显存至少8GB这样训练小模型不会太吃力比如检测两三类物体的入门项目完全够用。显存只有4GB的话也不是不能跑只是要牺牲batch size和输入分辨率训练时间会明显拉长。至于CPU训练我只能说入门Demo可以跑通流程但训练一个实际可用的模型时间成本太高不建议。软件环境方面安装好Python之后装YOLO官方训练包一条命令就能搞定pip install ultralytics注意装完后在命令行敲一下yolo能正常输出帮助信息就说明环境OK。如果之前装过旧版本先升级到最新版本再训练旧版本的一些参数行为和判断逻辑跟新版本差别挺大。4.2 从头训练还是用预训练权重这是新手问得最多的问题之一。我的建议是只要不是做完全没见过的新奇物体识别一律用预训练权重做微调。YOLO官方提供的预训练权重在大型公开数据集上学习过通用的特征比如边缘、纹理、颜色分布这些底层特征对大多数任务都是通用的。你用自己的小数据集从头训练相当于让模型把通用特征重新学一遍数据量不够根本学不出来。从头训练只建议在两种情况使用一是你的任务和通用物体检测差异太大预训练特征完全不适用二是你想深入理解训练机制拿小型实验数据集做实验。实际项目里最常见的做法是加载官方预训练权重微调几个epoch就能达到不错的效果。4.3 核心训练参数到底怎么调训练命令看起来简单参数却很多。我挑几个影响最大的说一下。先看一个完整的训练命令yolo detect train datadata.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ workers4 \ seed42 \ patience30modelyolov8s.pt表示加载官方预训练权重模型规模从n、s、m、l到x依次变大精度一般更高但显存占用和训练时间也更多。入门阶段我建议从s起步数据量少的时候n和s反而更容易收敛。epochs100是最大训练轮数配合patience30也就是说连续30轮验证集指标不提升就自动提前停止既能保证训练充分又不会傻等。batch是最需要根据显存调整的参数。显存报错的时候把它从16降到8甚至4往往问题就解决了。imgsz640是训练输入分辨率默认值一般够用。如果业务场景里小目标特别多可以尝试调到768或更高但显存和时间成本都显著上升而且训练和推理时的imgsz最好保持一致否则效果会有落差。lr0是初始学习率默认0.01数据量特别少的时候容易震荡可以降到0.001再观察。workers是数据加载线程数Windows下建议不要超过4太高可能出现莫名其妙的卡死。seed42保证实验可复现调参时务必固定。4.4 训练过程的观察与记录训练启动后终端会实时打印每一轮的loss和验证指标。你需要重点看的指标包括box_loss、cls_loss、dfl_loss这三项分别代表框回归损失、分类损失和分布焦点损失总体趋势应该随着训练轮数下降。同时看precision、recall和mAP50这些验证指标它们应该总体上升。训练过程中程序会自动保存权重文件位置在runs/detect目录下的一个自动命名子目录里里面有两个关键文件best.pt是验证集指标最好的权重last.pt是最后一轮的权重。实际部署和测试永远用best.pt不要用last.pt。训练结束后目录里还会生成各种可视化图表包括PR曲线、混淆矩阵、验证集预测结果图这些是判断模型好坏的第一手资料。一个细节如果你开启训练后想中途看效果不用等训练结束可以用另一个命令行窗口加载当前的last.pt对单张图片做推理能直观看到当前阶段模型学到了什么。5. 训练结果评估与模型改进5.1 loss曲线和评估指标怎么读看到训练结束就想欢呼别急先冷静看看指标。YOLO的验证指标里mAP50和mAP50-95是最核心的两个。mAP50是IoU大于0.5就算预测命中时的平均精度相对宽松适合快速判断模型是否“学起来了”mAP50-95把IoU从0.5到0.95以0.05为步长取平均值标准严格得多更能反映框定位的精准程度。如果mAP50很高但mAP50-95很低说明你模型能找到目标但框的位置不够准大概率是标注框本身不够紧贴或者数据集中目标尺度差异太大。如果两者都低那就是模型没学好回到数据采集和标注上找原因而不是急着换大模型。还有一个容易被忽略的点是precision和recall的权衡。业务上“宁可错报不能漏报”和“宁可漏报不能错报”是完全不同的两种需求前者可以把置信度阈值调低后者调高。推理时加conf0.25这样的参数就能控制。5.2 用训练好的权重做推理和导出评估通过之后用训练好的权重对新图片做预测yolo detect predict modelruns/detect/xxx/weights/best.pt \ sourcetest_images \ conf0.25 \ iou0.45conf是置信度阈值低于这个值的结果不显示iou是NMS去重的IoU阈值两个目标重叠超过这个比例就只保留置信度高的那个。实际部署到服务端时一般还会把权重导出成ONNX格式推理速度更快、不依赖训练框架yolo export modelruns/detect/xxx/weights/best.pt formatonnx导出成功后可以用ONNX运行时加载这个模型做推理整个过程和训练完全解耦部署起来干净利落。5.3 效果不佳时按顺序尝试的改进方向第一次训练效果不理想太正常了关键是排查要有顺序。我的习惯是先查数据再查参数最后才换模型。具体来说看看是不是某些类别样本太少如果是就去补充这一类别的不同场景图片再检查标注有没有系统性偏差比如一类物体的框普遍左边留白过多然后才考虑把模型从s换成m或者l看看是不是模型容量不够。另一个常用手段是数据增强YOLO训练默认开启Mosaic、翻转、亮度对比度变化等增强策略一般情况下不需要额外配置。如果你发现训练集和验证集分布差异比较大可以适当增强强度。如果数据集特别小比如只有一两百张优先加大数据量增强救不了小数据集。最后别忘了周围环境光线变化大的业务采集数据时一定要把光照变化覆盖进去这比调任何参数都管用。6. 常见问题与排查技巧实录6.1 典型问题速查表把我遇到过的、以及身边人经常问的问题整理在一张表里方便你排查时直接对照。现象可能原因排查与解决训练loss一直是nan学习率过大、标签里有0面积或越界框调低lr0跑标签校验脚本检查txtloss下降很慢或不降数据集太小、类别样本不均衡、标注噪声大补数据、核对标注质量、考虑换小模型部分类别完全检测不出来该类样本太少、data.yaml中类别顺序错位统计各类别数量检查names顺序是否和标注一致mAP50高但mAP50-95低框定位不准、标注框不紧贴抽样检查标注质量重新修正松散的框显存不足OOMbatch太大、输入分辨率太高batch减半、imgsz降到640或512、换成更小模型训练中断想继续断电、手动停止等用resumeTrue从last.pt续训推理速度慢模型太大、输入分辨率高换n/s模型、导出ONNX、降低推理imgsz6.2 调试经验和防坑心得这里分享几个我反复踩过的坑。第一类别顺序错位这个问题值得再强调一次。我做一个四类检测项目时数据标注阶段的类别列表顺序和训练配置里的names不一致训练了快三个小时才发现验证集指标里四个类别的精度完全对不上排查了半天才定位到是ID错位。从那以后我每次训练前都会写一行脚本随机抽一张图片打印它的txt内容和data.yaml的names肉眼对照一遍再开训。第二小数据集不要迷信大模型。有一次我只有三百张图片强行上了yolov8l结果loss反复震荡后来换成yolov8s反而指标更好。模型容量太大、数据量跟不上模型就会记住训练集的细节噪声学不到泛化特征。第三每标完一批图就随手打开几张看看框的位置不要等全部标完再统一检查。标注是个体力活人很容易标到后半程手感疲劳错框漏框高发分批检查能及时止住返工。第四训练日志目录别乱删runs/detect下每次训练都会自动生成新的子目录文件名带时间戳按时间排序就能找到最新那次别用一两次就手动清理。最后再分享一个我现在的固定套路拿到一个新检测任务先标50张图片把整条训练流程跑通确认数据格式、目录结构、训练命令都正确之后再安心把数据补齐到几百张。这个顺序看起来多了一步实际能省下大量返工时间。真等几百张图全标完了才发现某个环节错了那才是真的欲哭无泪。数据集的制作和模型训练本质上就是一个“精细活加体力活”的组合前面每多一分仔细后面训练和调试就少一分折腾。
RELATED

相关推荐

MCU上直接生成PDF:嵌入式C库实现与内存优化

MCU上直接生成PDF:嵌入式C库实现与内存优化

简介:面向MCU嵌入式开发者的PDFlib移植包,解决单片机等资源受限环境下生成PDF文档的难点。该库针对小内存、低算力平台做了裁剪优化,可配合FatFS文件系统直接保存文件,适用于工业自动化实时报告、医疗设备诊断结果、物联网终端数据…

📅 2026/10/18 12:53:07
VsCode 配置 Latex 编译环境并指定输出目录:用 TaoToken 统一管理 API 调用

VsCode 配置 Latex 编译环境并指定输出目录:用 TaoToken 统一管理 API 调用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/18 12:53:07
分子克隆、蛋白质纯化与质谱分析:研究生复习资料中的原理链条与避坑指南

分子克隆、蛋白质纯化与质谱分析:研究生复习资料中的原理链条与避坑指南

简介:这份PDF是中国科学技术大学2024-2025学年《生化原理与应用Ⅰ》期末复习资料,面向生命科学、生物化学及相关专业研究生与高年级本科生,帮助系统梳理实验技术原理与高频考点。内容覆盖色谱法、电泳技术、质谱分析、NMR、X射线晶体学、单颗…

📅 2026/10/18 12:53:07
MORE NEWS

更多资讯

📰

金三银四网安跳槽指南:十大岗位方向与技术底气解析

金三银四这四个字,放在网安圈和通用研发圈完全是两种滋味。通用研发岗位主要看技术栈新旧,而安全岗位的跳槽,往往跟着预算周期、合规节点和上一年的项目复盘走。每年二三月份,各家安全负责人开始敲定新一年的编制和预算&#xff0…

📰

tiny11builder 教程:一条命令把 Windows 11 官方 ISO 瘦身为可引导精简镜像

tiny11builder 教程:一条命令把 Windows 11 官方 ISO 瘦身为可引导精简镜像 【免费下载链接】tiny11builder WinUI app for building smaller, customized Windows 11 images. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder 老电脑过不了…

📰

Chrome远程调试Pending authentication报错:从ADB授权到USB调试排查指南

刚插上USB线,打开电脑上的Chrome,敲下chrome://inspect,设备列表里确实看到了那台安卓手机,但点一下inspect,页面却卡在一个灰条上:Pending authentication: please accept debugging session on the devic…

📰

ComfyUI-LTXVideo 快速上手:一次装好 LTX-2 视频生成与 IC-LoRA 控制全链路

ComfyUI-LTXVideo 快速上手:一次装好 LTX-2 视频生成与 IC-LoRA 控制全链路 【免费下载链接】ComfyUI-LTXVideo LTX-Video Support for ComfyUI 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-LTXVideo ComfyUI-LTXVideo 是给 ComfyUI 加 LTX-2…

📰

任意长视频的连贯深度:Metric-Video-Depth-Anything-Base-MLX如何实现32帧窗口推理与跨帧一致性

计算机视觉深度学习 【免费下载链接】Metric-Video-Depth-Anything-Base-MLX 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/Metric-Video-Depth-Anything-Base-MLX 点击查看 免费下载 Metric-Video-Depth-Anything-Base-MLX 是 ByteDance Video Dep…

📰

零样本学习实战:从语义对齐到CLIP升级的完整复现指南

简介:本资源是一份面向人工智能方向研究者与进阶学习者的零样本学习(Zero-Shot Learning)实践套件,聚焦于算法复现与语义建模能力训练,适用于计算机视觉、跨模态理解等场景下的小样本泛化问题研究。压缩包共11个文件&a…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬