做视觉这行,如果只让选一个模型给新人上手,我大概率推YOLO。从YOLOv1提出到现在,YOLO几乎成了目标检测的代名词,工业缺陷检测、安防监控、自动驾驶、体育分析,到处都有它的影子。网上教程一搜一大把,但真正能把环境搭建、数据准备、模型训练、推理部署串成一条完整链路讲清楚的并不多。YOLO-Master是我自己一直在维护的一个实战项目,核心目标就一句话:让一个完全没接触过目标检测的人,照着这套流程也能把YOLO跑起来,而且能跑通自己的数据。
这篇文章就是整个项目的开始,也相当于一份完整的上手指南。我会一路从环境配置、AMD老显卡能不能跑YOLO这种现实问题讲起,再到VisDrone数据集转YOLO格式、data.yaml配置、模型训练、损失函数和YOLO架构,最后落到TensorRT engine部署、K230/Atlas边缘设备、Flask+Vue+MySQL整套Web检测服务。适合两类人看:一是刚开始学目标检测的学生或转行工程师;二是手里有真实业务场景,想快速用YOLO验证效果的技术从业者。YOLO-Master不是什么神奇框架,它是把常见坑提前填平的一套工程模板,你照着走,能省下大量试错时间。
1. YOLO-Master 是什么,以及为什么需要一条完整路线
1.1 先搞清楚 YOLO 到底在解决什么问题
目标检测本质上做两件事:框出物体在哪里,同时说出它是什么。你可以把检测当成“分类 + 定位”的组合。在YOLO出现之前,主流方案是两阶段检测,比如Faster R-CNN,它先通过区域建议网络生成一堆可能包含目标的候选框,再去逐个识别。这种思路精度高,但速度慢,很难满足实时场景。
YOLO走的是另一条路:一阶段检测。它在名字里就把思想说透了——You Only Look Once,你只看一次。整张图送进网络,不再单独生成候选区域,而是直接预测边界框坐标和类别概率。用一个生活化的类比:两阶段像你进一个房间,先扫一眼锁定几个可疑角落,再走过去仔细确认;YOLO则是站在门口瞄一眼全局,直接告诉你哪个角落有人、哪个桌上有杯子。
这种“把检测当回归问题来做”的设计,让YOLO在速度和工程化上占尽优势。尤其在实际项目里,模型最终是要部署到服务器甚至边缘设备上的,推理延迟直接决定方案可不可行。这也是YOLO能成为工业落地首选的原因之一。
1.2 YOLO-Master 的项目定位与结构设计
YOLO-Master不是某个神秘的开源框架,它是我在工作里沉淀下来的一套完整工程目录和流程规范。所谓“完整”,指的是从数据集到部署的每个环节都有对应的目录、脚本和文档,而不是把代码乱扔在一堆笔记本里。
我建议任何YOLO项目都先按这样的结构组织:
YOLO-Master/ ├── configs/ # 所有配置文件:模型yaml、数据yaml、超参数 ├── datasets/ # 数据集统一目录,原始图与标注分开 ├── scripts/ # 格式转换、数据集划分等工具脚本 ├── runs/ # 训练输出、权重、日志、指标曲线 ├── deploy/ # ONNX/TensorRT导出、边缘设备部署代码 ├── web/ # Flask后端、Vue前端、MySQL脚本 └── docs/ # 实验记录和踩坑文档这个结构看起来简单,但每个目录都是为了解决一个实际问题。configs把配置集中管理,避免训练参数散落在代码里;scripts只做单一职责,一个脚本只负责一件事,比如VisDrone转YOLO格式就单独一个文件;runs天然形成了按时间排列的实验版本,每次训练结果都在这里留档。你可能会觉得这是小题大做,但等你想复盘两个周之前的实验时,就会发现这种“可复现性”的设计比任何技巧都重要。
2. 环境准备:你的 AMD 580 到底能不能跑 YOLO
2.1 Python 与 PyTorch 环境搭建
YOLO当前主流的实现是Ultralytics维护的ultralytics包,它把训练、验证、导出、推理全部封装在一起,一条命令就能跑。安装路径非常简单:
conda create -n yolo-master python=3.10 -y conda activate yolo-master pip install --upgrade pip pip install ultralytics如果你没有NVIDIA显卡,直接装CPU版PyTorch就行:
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu如果是NVIDIA显卡,就把最后的链接换成cu121或cu118版本。装完之后在命令行输入yolo version,能输出版本号说明环境已经通了。这里提醒一句:正式项目开始前,最好用pip freeze > requirements.txt把依赖版本固定住,否则队友拉代码的时候,可能因为ultralytics版本升级,训练结果和你完全对不上。
2.2 关于 CUDA、AMD 显卡最容易踩的坑
热词里有人问“AMD 580显卡能跑YOLO吗,需要安装CUDA吗”,这个问题非常典型。先说结论:RX 580不能安装CUDA,因为CUDA是NVIDIA专用的并行计算平台;AMD的对应方案是ROCm,但RX 580属于GCN架构,在ROCm里早就进入了维护甚至弃用状态,Windows下尤其不建议折腾。
那老AMD显卡用户怎么办?最稳的路径是CPU推理。YOLO的n和s这种小模型,在CPU上推理一张640x640的图片,通常只要几百毫秒到一两秒,做验证和原型开发完全够用。训练的话,小数据集、小模型在CPU上也能跑,但速度确实慢,正式训练还是建议租一张NVIDIA云GPU,按小时计费,省心得多。
还有一条路是ONNX Runtime + OpenVINO,CPU推理速度能比纯PyTorch快不少。我在YOLO-Master里就专门留了一个deploy/openvino的目录,遇到客户没有独立显卡的情况,直接导出OpenVINO模型给他们用。
2.3 一键部署脚本与最新版本更新内容
为了减少重复劳动,我把环境初始化写成脚本,放到scripts目录下:
conda create -n yolo-master python=3.10 -y conda activate yolo-master pip install --upgrade pip pip install ultralytics onnx onnxruntime opencv-python flask flask-cors pymysql这就是你的一键部署脚本,核心逻辑很简单:创建虚拟环境、安装训练和部署所需的依赖。真正值得注意的是版本变化。Ultralytics的主分支已经从YOLOv8迭代到了YOLO11系列,新版本的最大变化在于:全部任务统一用一套API,detect、segment、pose、obb、classify都可以通过同一个yolo命令调用;模型体积更小,推理速度更快;导出格式也更多样,ONNX、TensorRT、OpenVINO、CoreML都支持得不错。
3. 数据集准备:VisDrone 转 YOLO、标注工具与 data.yaml
3.1 标注工具的选型
做目标检测,数据标注永远绕不开。工具选型我只有一个原则:任务复杂度和工具复杂度匹配。如果你只做矩形框检测,LabelImg就够用,轻量、免费、导出YOLO格式也方便。如果要做多边形实例分割或者关键点标注,建议用Labelme或者X-AnyLabeling,前者经典稳定,后者更新更快。Roboflow这类在线工具功能很强,自带数据增强和格式转换,但涉及企业数据上传,合规问题要提前搞清楚,别数据上云之后才后悔。
我自己实际使用中最喜欢的组合是:检测框用LabelImg,需要分割或关键点时用X-AnyLabeling。标注导出之后,经常还需要人工复核一遍,尤其边界模糊的小目标,机器标得再好也不能全信。
3.2 VisDrone2019 转 YOLO 格式实战
很多公开数据集的标注格式和YOLO不一致,转换是家常便饭。VisDrone2019-DET是无人机视角目标检测的经典数据集,它的标注文件是纯文本,每行是8个字段:
bbox_left, bbox_top, bbox_width, bbox_height, score, category, truncation, occlusion其中第5列score表示置信度,只有score大于等于1的框才是有效标注。类别编号从0到11,第0类叫ignored regions,一般直接扔掉;剩下1到11分别对应pedestrian、people、bicycle、car、van、truck、tricycle、awning-tricycle、bus、motor、other。而YOLO格式每一行是:
class_id x_center y_center width height所有坐标都归一化到0到1之间。转换脚本思路很直接,逐行读取VisDrone标注,把左上角宽高格式转成中心点宽高格式,再除以图片宽高:
import os from glob import glob from PIL import Image ID_MAP = { 1: 0, 2: 1, 3: 2, 4: 3, 5: 4, 6: 5, 7: 6, 8: 7, 9: 8, 10: 9, 11: 10 } SRC = "VisDrone2019-DET-train/annotations" IMG = "VisDrone2019-DET-train/images" DST = "VisDrone2019-DET-train/labels" os.makedirs(DST, exist_ok=True) for ann_path in glob(os.path.join(SRC, "*.txt")): img_name = os.path.basename(ann_path).replace(".txt", ".jpg") img_path = os.path.join(IMG, img_name) if not os.path.exists(img_path): continue # 注意:宽高必须从图片读取,不能写死 with Image.open(img_path) as img: w_img, h_img = img.size out_lines = [] with open(ann_path, "r", encoding="utf-8") as f: for line in f: parts = line.strip().split(",") if len(parts) < 8: continue x, y, w, h, score = map(float, parts[:5]) category = int(parts[5]) if score < 1: continue if category == 0: continue new_id = ID_MAP.get(category) if new_id is None: continue xc = (x + w / 2) / w_img yc = (y + h / 2) / h_img nw = w / w_img nh = h / h_img out_lines.append(f"{new_id} {xc:.6f} {yc:.6f} {nw:.6f} {nh:.6f}") if out_lines: out_path = os.path.join(DST, os.path.basename(ann_path)) with open(out_path, "w", encoding="utf-8") as f: f.write("\n".join(out_lines))最容易踩的坑就是图片尺寸写死。很多转换脚本图省事,用固定宽高,结果不同分辨率的图全部标注错位。图片宽高必须从原图读,别偷懒。
3.3 data.yaml 配置文件与数据增强
YOLO的数据配置是一个yaml文件,它是训练时的“数据说明”。一个典型的data.yaml长这样:
path: datasets/visdrone train: images/train val: images/val nc: 11 names: - pedestrian - people - bicycle - car - van - truck - tricycle - awning-tricycle - bus - motor - otherpath是数据集根目录,train和val是相对path的子目录,nc是类别数量,names是类别名列表。新手最容易在这里出错:class id从0开始编号,names列表的顺序必须和标注文件里的类别id一一对应,差一位全错。
至于数据增强,Ultralytics内置了Mosaic、HSV变化、随机翻转、平移缩放等。Mosaic把四张图拼成一张训练,对小目标检测特别有帮助。我自己训练无人机视角数据集的时候,Mosaic基本都是开着的。业务场景里常见的吸烟检测、积水识别、消防设施检测、矿井人员安全行为检测,本质都是垂直领域数据集的构建问题。我的经验是“公开数据 + 自采数据 + 半自动标注”三管齐下:先找相关公开数据集,再用预训练模型做半自动预标注,最后人工修正,效率能提升一倍以上。
4. 模型训练:从命令到损失函数,再到架构理解
4.1 第一次训练,先把官方命令跑通
很多人第一次训练就直接上自己的业务数据,结果一堆报错还不知道从哪排查。我的建议是先用ultralytics自带的coco8这个小数据集把流程跑通,只需要一张命令:
yolo detect train data=coco8.yaml model=yolo11n.pt epochs=50 imgsz=640 device=cpucoco8只有8张图片,两三分钟就能训完,用来验证环境、熟悉命令行再合适不过。跑通之后,你对整个训练流程有了感觉,再换自己的数据。
这里整理几个高频参数的取值经验:
| 参数 | 作用 | 我的常用值 |
|---|---|---|
| model | 模型权重或模型结构yaml | yolo11n.pt |
| data | 数据集配置yaml路径 | data.yaml |
| epochs | 训练轮数 | 100起步 |
| batch | 批大小,显存不够就往下调 | 16或8 |
| imgsz | 输入分辨率 | 640,小目标用960 |
| device | 设备,cpu或者GPU编号 | 0 |
| patience | 早停轮数,mAP不再提升就停 | 30 |
| lr0 | 初始学习率 | 0.01,一般不用动 |
| workers | 数据加载线程数 | 8 |
如果显存只有8G,batch别硬扛,降到8甚至4都行。训练稳定性比单次迭代速度重要。
4.2 损失函数:YOLO 到底在优化什么
理解YOLO的损失函数,是看懂训练日志的关键。YOLO的总损失大致分三块:分类损失、边界框回归损失、以及部分版本里的DFL损失。
分类损失计算的是预测类别概率和真实类别的差距,YOLO框架里常用BCE。边界框回归损失衡量预测框和真实框的重合程度,现代YOLO用得最多的是CIoU损失。CIoU不只是看两个框交并比,它还会惩罚中心点距离和宽高比,避免出现“框位置对了但尺寸偏了”也被判成高分的尴尬。DFL则把框的坐标预测当成一个离散分布来学,让模型对目标边界更敏感,精度上有实打实的提升。
看训练曲线的时候,不要只盯着总loss。我会把box_loss和cls_loss分开看。如果box_loss已经平稳了,cls_loss还在跳动,说明模型对类别的置信度还没收敛,这时候可以考虑降低学习率,或者检查类别样本是否均衡。
4.3 快速看懂 YOLO 架构
YOLO的模型结构说复杂也复杂,说简单也就三块:Backbone、Neck、Head。
Backbone是特征提取器,负责从原图里提取由浅到深的特征。现代YOLO里你能看到C2f、SPPF这类模块,C2f是跨阶段部分连接结构的改进版,兼顾了信息流动和计算效率;SPPF通过不同尺度的池化,把多尺度信息揉在一起。
Neck是特征融合层,最经典的是PAN-FPN结构。浅层特征位置信息丰富但语义弱,深层特征语义强但分辨率低,PAN-FPN通过自顶向下和自底向上的路径,把两者融合起来。这就是为什么YOLO能同时检测大目标和小目标的关键。
Head是检测头,现代YOLO基本都走向了Anchor-Free,不再依赖预设的锚框尺寸,而是直接预测目标的中心点偏移和宽高,泛化能力更好。
想在YOLO-Master里看模型结构,简单得很:
from ultralytics import YOLO model = YOLO("yolo11n.yaml") print(model.model)或者在训练完导出模型后用model.info()看参数量和计算量。我个人的建议是,架构图不用死记硬背,打开项目里的模型yaml文件,对照着逐层看输入输出,几遍下来自然就记住了。
4.4 模型改进方向:别急着上 MoE
网上“YOLO改进”的内容多如牛毛,加注意力、换Backbone、改检测头、引入可变形卷积,什么都有。但我的态度很明确:改进之前必须先跑通官方基线,并且用AB实验记录数据。一次只改一个模块,改完记录mAP50、mAP50-95、推理延迟三个指标,只有这三个指标综合变好才算有效改进。
YOLO MoE是最近比较热的思路,把一部分重计算模块替换成多个专家子网络,用门控机制动态选择专家,理论上能不显著增加计算量就提升表达能力。但工程复杂度高,新手不建议一上来就试。Volo这类基于Transformer的视觉模型在部分高分辨率任务上表现很好,但和YOLO比,部署生态和推理速度差距明显,选型时要看实际场景。
还有一个经常被忽略的方向是工业软件集成,比如Halcon。较新版本的Halcon可以通过ONNX接口加载YOLO导出的模型做工业质检,很多做机器视觉的老工程师很吃这一套。关键还是那四个字:预处理一致,否则模型在你本机上跑得好好的,到Halcon里预测就全乱套了。
5. 训练自己的数据集:完整流程与调优心得
5.1 从收集图片到划分数据集
训练自己的数据集,至少要走过这几步:
- 收集图片,尽量覆盖不同光照、角度、背景;
- 清洗图片,剔除模糊、重复、目标遮挡严重的图;
- 标注,导出YOLO格式的txt文件;
- 划分训练集、验证集、测试集,常见比例是8:1:1;
- 写data.yaml;
- 正式训练,建议从官方预训练权重开始微调;
- 用测试集做最终评估。
第4步容易被忽略,但特别重要。划分数据集时要保证验证集的分布和真实场景接近,而且同一个场景的连续帧不要同时出现在训练集和验证集里,否则指标虚高,上线之后立刻现原形。
5.2 训练时的几个关键细节
预训练权重对收敛速度影响巨大。用model=yolo11n.pt,模型会从COCO预训练权重开始微调,几百张图片也能训出不错的效果。如果去掉预训练权重从头训练,对数据量和epoch数的要求会高出一个量级。
遇到显存不足,优先降batch而不是降imgsz。因为imgsz直接决定模型能看到的细节,尤其小目标检测,分辨率越低,小目标越难检。目标检测任务里小目标占比高时,我一般把imgsz提高到960甚至1280,同时打开Mosaic增强。
训练时建议开启早停:
yolo detect train data=data.yaml model=yolo11n.pt epochs=200 imgsz=640 patience=30 device=0patience=30意味着连续30轮验证集mAP没提升就自动停止,能省下大把时间。多GPU训练时设置device=0,1,同时batch要相应翻倍,学习率也可以按线性缩放规则适当调大。
5.3 判断模型好坏:mAP 到底怎么看
模型训完,Ultralytics会在runs目录下生成一堆曲线和指标。重点看两个值:mAP50和mAP50-95。mAP50只要求预测框和真实框的IoU超过0.5就算对,看的是“大概框住了没有”;mAP50-95对框的精细程度要求更高,看的是“框得够不够准”。小目标数据集这两个指标差距大非常正常,因为小目标稍微偏一点,IoU就掉得很快。
如果训练loss很低、验证loss却很高,这是过拟合,解决办法是减少epoch、加数据增强、加大weight decay。如果训练和验证loss都在高位下不去,那是欠拟合,换更大的模型或者提高分辨率。我的习惯是先用200张图片做一次快速过拟合实验,确认数据格式和训练链路都通了,再上全量数据。这一步能省掉很多无效时间。
6. 推理部署与 Web 服务:engine、边缘设备与 Flask+Vue+MySQL
6.1 导出 ONNX 和 TensorRT engine
训练的终点是部署。Ultralytics官方的导出命令一条搞定:
yolo export model=runs/detect/train/weights/best.pt format=onnx imgsz=640 yolo export model=runs/detect/train/weights/best.pt format=engine device=0engine是TensorRT的序列化格式,专为NVIDIA显卡优化,推理速度比PyTorch模型快很多。Python加载engine推理的核心代码大概是这样的思路:
import tensorrt as trt def load_engine(engine_path): logger = trt.Logger(trt.Logger.WARNING) with open(engine_path, "rb") as f: engine_data = f.read() runtime = trt.Runtime(logger) return runtime.deserialize_cuda_engine(engine_data) engine = load_engine("best.engine") context = engine.create_execution_context() # 构造输入输出GPU显存buffer # context.execute_v2(bindings) 执行推理 # 再拷贝回CPU做后处理这里有一个高频坑:TensorRT engine和CUDA、显卡型号强绑定,在一台机器导出的engine,换一台机器很可能直接加载失败。解决办法就是在目标机器上重新导出,不要试图跨机器复用engine文件。
6.2 边缘设备部署:Atlas 与 K230 的大原则
K230、Atlas这类带NPU的边缘设备部署流程高度相似:训练权重导出ONNX,用厂商工具链转成设备支持的格式,再调用SDK推理。昇腾Atlas一般用ATC工具把模型转成om格式;嘉楠K230用NNCase转kmodel,再在CanMV环境里调用。
真正花时间的不是转换命令,而是预处理和后处理的移植。训练脚本里的letterbox、归一化、NMS阈值,部署端必须和训练时完全一致。很多时候板子上模型跑起来了,但检测框全偏移,问题就出在预处理重写时不统一。我在YOLO-Master里反复强调:预处理函数一定要从训练脚本里原封不动拷贝过去,不要重新实现。
6.3 完整小型检测系统:Flask + Vue + MySQL
模型部署的常见形态是Web服务。我自己的一个典型项目是:Vue前端上传图片,Flask后端调用YOLO推理,把结果图片和检测记录写入MySQL,前端还能看历史列表。这个系统的核心数据流是:
用户上传图片 → Flask接收 → 调用模型推理 → 绘制检测框 → 保存结果图 → 写入MySQL → 返回JSON → Vue展示结果
Flask后端最关键的一段代码是这样:
import cv2 from uuid import uuid4 import pymysql from flask import Flask, request, jsonify from ultralytics import YOLO app = Flask(__name__) model = YOLO("best.pt") # 全局只加载一次 @app.route("/detect", methods=["POST"]) def detect(): file = request.files["file"] img = cv2.imdecode( np.frombuffer(file.read(), np.uint8), cv2.IMREAD_COLOR ) results = model.predict(img, imgsz=640, conf=0.25) save_path = f"static/results/{uuid4().hex}.jpg" rendered = results[0].plot() cv2.imwrite(save_path, rendered) conn = pymysql.connect( host="localhost", user="root", password="123456", database="yolo_master", charset="utf8mb4" ) with conn.cursor() as cur: cur.execute( "INSERT INTO records(filename, result_path, count) VALUES(%s, %s, %s)", (file.filename, save_path, len(results[0].boxes)) ) conn.commit() conn.close() return jsonify({ "result_path": "/" + save_path, "count": len(results[0].boxes) })几个细节别忽略:模型要全局加载一次,不要每次请求都重新加载;上传图片要先解码再推理;MySQL连接建议用连接池,不然高并发下数据库会变成瓶颈。
再回到热词里的那个问题:“YOLO切割只能切矩形图片吗”。准确地说,YOLO的输入张量是固定尺寸的矩形,所有输入图片在进网络前都会被letterbox成比如640x640的矩形。你切块推理时,切出来的块也是矩形块,每个块再被resize成网络输入尺寸。如果你用分割模型的mask做不规则区域的检测,mask本身可以是不规则的,但一旦要送进YOLO,它必须先变成矩形输入。所以结论是:YOLO不是“只能检测矩形区域”,而是它的输入必须是矩形张量,这在工程上是个约束,要用切图策略去适配。
7. 高级任务:实例分割、姿态检测与 SAM2 对比
7.1 实例分割:不只是抠图
YOLO不只做检测框。实例分割任务的模型权重名称里带seg,比如yolo11n-seg.pt,训练命令就是固定的套路:
yolo seg train data=coco8-seg.yaml model=yolo11n-seg.pt epochs=50 imgsz=640推理时,分割模型返回的不只是边界框,还有每个目标的像素级mask。这在工业场景里特别有用。比如你提到“模型孔洞测试”,如果是检测目标内部是否有孔洞缺陷,用分割模型比用检测框更合适,因为可以通过mask计算连通域,直接判断目标内部有没有空洞、孔洞面积占比是多少。检测框只能告诉你“这里有个目标”,无法表达目标内部结构。
7.2 姿态检测与关键点
姿态检测用的是pose模型,比如yolo11n-pose.pt。它检测的对象是人或物体的关键点,输出格式是每个关键点的坐标和可见度。调用方式非常简单:
yolo pose predict model=yolo11n-pose.pt source=bus.jpg这类模型在健身动作纠正、老人跌倒检测、运动姿态分析里应用很多。进一步,你可以把YOLO Pose输出的关键点和检测框喂给ViTPose、HMR2、GVHMR这类人体网格重建模型,实现从2D视频直接恢复3D人体模型。不过我要多说一句:这些模型的权重尽量走官方渠道获取,比如GitHub release或Hugging Face模型库,不要随手下载来源不明的网盘分享链接。一是版本可能对不上,二是有安全隐患。磨刀不误砍柴工,官网上找权重真的不难。
7.3 SAM2 和 YOLO 怎么选
SAM2是Meta推出的图像和视频分割基础模型,你给它一个点或者一个框,它能帮你把目标精细地分割出来。它的定位和YOLO完全不同:SAM2擅长交互式分割和精细边缘,但直接部署到边缘设备不现实,因为模型太大、速度太慢;YOLO擅长实时检测,训练完直接导出部署,但精度和边缘质量不如SAM2这种大模型。
正确姿势是扬长避短。最常用的组合是SAM2自动标注 + YOLO训练部署。先用SAM2给业务数据生成精细的伪标签,人工快速复核修正,再用这些数据训练YOLO,最终得到一个又小又快、能上边缘设备的模型。如果目标是精细分割,还可以先用YOLO快速定位目标,再把目标区域交给SAM2细化,速度和精度就能兼顾。
8. 常见问题与避坑实录
8.1 高频问题速查表
我整理了实际项目里最常遇到的几个问题,直接对照排查:
| 问题 | 可能原因 | 解决办法 |
|---|---|---|
| 训练报显存OOM | batch或imgsz过大 | 降batch到4或8,imgsz降到512 |
| mAP低但loss正常 | 数据量少/样本不均/标注有误 | 增加数据、检查标注、做类别平衡 |
| 小目标漏检严重 | imgsz太小或特征融合不足 | imgsz提至960,用SAHI切图推理 |
| engine文件加载失败 | TensorRT版本与CUDA不匹配 | 在目标机器重新导出engine |
| 部署后检测框全偏移 | 预处理和训练时不一致 | 直接复用训练脚本里的预处理函数 |
| VisDrone转换后没目标 | score小于1的框没过滤 | 确认按第5列score>=1过滤 |
| Web服务多请求下卡死 | 每次请求都加载模型 | 全局加载模型只做一次 |
8.2 调试经验分享
排查问题有个笨但好用的方法:拆解输入输出。先打印送入模型的图片shape和像素范围,确认预处理正确;再打印results[0].boxes.xyxy,看坐标是否超出图像范围;最后用results[0].plot()保存画框后的图,肉眼确认检测效果。这三步走完,90%的问题都能定位。
YOLO-Master项目里,我有一条铁律:所有实验必须配一个实验记录文档,记录数据集、配置、参数、结果、备注。哪个实验数据集改了什么、模型改了什么,一目了然。这样做不是为了写文档而写文档,而是为了让你三个星期后还能准确复现当时的结论。
我做完整个链路之后最大的一个体会是,YOLO本身并不难,难的是从环境到数据到部署这条链路上的琐碎问题。很多人一开始就想着把mAP刷到90,结果卡在数据格式转换上折磨了好几天。我后来把所有项目都改成同一个启动顺序:先拿官方自带的小数据集跑通训练流程,再拿二三十张自己的图验证数据格式,最后才上全量数据正式训练。这个顺序帮我省下的时间,远比任何花哨的模型技巧都多。YOLO-Master这个名字,就是想提醒自己和身边的人:再复杂的算法,也得从最小闭环开始跑通,跑通一次,后面全都是加速度。