这篇文章记录我如何使用 Google Quick, Draw! 数据集训练一个 YOLO11 模型。目标是先用公开的手绘数据训练一个基础模型,让模型具备识别手绘线条、简笔画、图形轮廓的能力,后续再用真实纸面拍摄数据进行微调。
一、目标
我想做的是:识别人在纸上绘制的不同线条或图形。
例如:
- 直线
- 曲线
- 折线
- 波浪线
- 箭头
- 圆形
- 方形
- 三角形
- 简笔画图案
- 不规则手绘线条
一开始我考虑直接找现成的数据集,但发现完全匹配“纸上手绘线条识别”的数据集并不多。Quick, Draw! 虽然不是专门的线条检测数据集,但它有大量人类随手画出来的矢量笔画,非常适合用来训练一个手绘风格的基础模型。
这次的方案是:
| |
二、重要说明
Quick, Draw! 原始数据并不是 YOLO 检测数据集。
它的数据形式更接近这样:
| |
例如每个样本里会有一组 drawing,里面保存了手绘笔画的 x/y 坐标。
所以这次我们需要自己做一步转换:
| |
也就是说,这次生成的 YOLO 标签框不是人工标注的,而是通过笔画的最小外接矩形自动生成的。
这个方法适合先训练 baseline,但最终如果要用于真实纸面照片,还是需要收集真实图片并人工标注一部分数据来微调。
三、项目目录结构
我把整个项目整理成下面的结构:
| |
新建项目:
| |
新建目录:
| |
四、安装环境
建议使用 Python 3.10 或 Python 3.11。
创建虚拟环境:
| |
Windows 激活:
| |
Linux / macOS 激活:
| |
安装依赖:
| |
检查 YOLO 环境:
| |
如果有 NVIDIA GPU,可以检查 PyTorch 是否识别到 GPU:
| |
如果输出:
| |
说明可以使用 GPU 训练。
五、下载 Quick, Draw! 全部类别
第一个脚本用于下载 Quick, Draw! 的全部类别。
保存为:
| |
代码:
| |
运行:
| |
下载完成后,数据会放在:
| |
六、检查 Quick, Draw! 原始下载完整度并补下载
下载 Quick, Draw! 全部类别时,可能会因为网络波动导致某些类别没有下载成功,或者留下 .part 临时文件。
因此在转换 YOLO 数据集之前,我需要先检查原始 NDJSON 文件是否完整。
这一步检查的是:
| |
它和后面的 YOLO 数据集检查不一样:
| |
保存脚本为:
| |
代码:
| |
运行:
| |
如果全部正常,会看到:
| |
如果有缺失或异常文件,脚本会列出类似:
| |
然后它会自动重新下载这些类别。
如果仍然失败,会写入:
| |
之后可以再次运行同一个脚本继续补下载。
这个脚本主要检查以下问题:
| 检查项 | 说明 |
|---|---|
| missing | 类别文件不存在 |
| empty | 文件大小为 0 |
| too small | 文件小于设定阈值,默认小于 1MB |
| first line does not look like ndjson | 文件首行不像 JSON 行 |
| read error | 文件无法读取 |
| .part 文件 | 上次下载中断留下的临时文件 |
需要注意的是,这个检查是基础完整度检查。它不会逐行解析整个 NDJSON 文件,否则全部类别检查会比较慢。一般情况下,配合文件大小、首行格式和 .part 清理,已经足够发现大多数下载失败问题。
七、转换成 YOLO 数据集
第三个脚本负责把 Quick, Draw! 的 NDJSON 数据转换成 YOLO 检测数据集。
保存为:
| |
主要逻辑:
| |
代码:
| |
运行:
| |
生成的数据集结构:
| |
八、检查转换后的 YOLO 数据集完整性
在正式训练 YOLO11 之前,除了要检查 Quick, Draw! 原始 NDJSON 是否下载完整,还需要检查转换后的 YOLO 数据集是否正常。
这一步非常重要,因为 YOLO 训练时如果 label 有问题,可能会出现:
| |
所以我额外准备了一个完整性检查脚本,用来扫描转换后的数据集。
保存为:
| |
代码:
| |
运行:
| |
如果一切正常,最后应该能看到类似:
| |
如果出现 warning,不一定代表数据不能用。例如 Quick, Draw! 有些图形本身就是细长的线条,所以可能出现:
| |
这些需要结合样本查看,不一定要全部删除。
但如果出现下面这些 hard error,就需要优先处理:
| |
我的训练流程里,这一步放在可视化预览之前:
| |
九、抽样可视化检查 YOLO 标签框
脚本检查完之后,还要人工看一批图片,确认框的位置是否符合预期。
保存为:
| |
这个脚本会从训练集或验证集随机抽样,把 YOLO 框画出来,保存到:
| |
代码:
| |
运行:
| |
检查输出目录:
| |
确认框没有明显偏移、类别没有错乱,再进入训练。
十、训练 YOLO11
保存为:
| |
代码:
| |
运行:
| |
也可以直接用命令行训练:
| |
训练完成后,最佳模型会保存在:
| |
最后一轮模型一般在:
| |
十一、预测测试
保存为:
| |
代码:
| |
把测试图片放到:
| |
运行:
| |
预测结果会输出到:
| |
十二、完整执行顺序
整理一下,完整流程是:
| |
对应脚本功能:
| 脚本 | 作用 |
|---|---|
01_download_quickdraw_all.py | 下载全部 Quick, Draw! 类别 |
02_verify_and_fix_quickdraw.py | 检查 NDJSON 下载完整度并补下载 |
03_convert_quickdraw_to_yolo.py | 转换为 YOLO 数据集 |
04_check_yolo_dataset.py | 检查 YOLO 数据集完整性 |
05_preview_yolo_labels.py | 抽样可视化标签框 |
06_train_yolo11.py | 训练 YOLO11 |
07_predict.py | 预测测试 |
十三、第一次训练建议参数
第一次不要直接上超大数据量,先跑通流程。
我建议先这样设置:
| |
这样可以快速验证:
| |
确认流程没问题后,再扩大到:
| |
如果显卡性能足够,再考虑:
| |
十四、后续调参方向
1. 调整每类样本数量
最重要的参数之一是:
| |
不同设置大概对应:
| 每类样本数 | 总图片数量 | 适合阶段 |
|---|---|---|
| 200 | 约 6.9 万 | 流程验证 |
| 500 | 约 17 万 | 小规模训练 |
| 1000 | 约 34.5 万 | 正式 baseline |
| 3000 | 约 103.5 万 | 更充分训练 |
| 10000 | 约 345 万 | 大规模训练 |
我的建议:
| |
2. 调整模型大小
YOLO11 有不同规模的模型。
一般可以按这个顺序尝试:
| |
建议:
| 模型 | 特点 | 适合场景 |
|---|---|---|
| yolo11n.pt | 最快,最轻 | 测试流程、低显存 |
| yolo11s.pt | 精度和速度平衡 | 推荐正式 baseline |
| yolo11m.pt | 更强,但更慢 | 数据量更大、有较好 GPU |
如果只是先验证 Quick, Draw! 方案,使用:
| |
如果效果稳定,可以换成:
| |
3. 调整训练轮数
训练轮数在脚本里是:
| |
建议:
| 训练轮数 | 适合阶段 |
|---|---|
| 10 | 快速测试 |
| 30 | 初步训练 |
| 50 | baseline |
| 80 | 更充分训练 |
| 100+ | 大数据长期训练 |
如果训练过程中验证集指标已经不再提升,可以减少 epochs。
如果模型还在持续提升,可以增加 epochs。
4. 调整 batch size
batch 参数:
| |
如果显存不够,训练时报 CUDA out of memory,可以降低:
| |
甚至:
| |
如果显存充足,可以提高:
| |
经验上:
| |
5. 调整图片尺寸
当前图片尺寸是:
| |
训练时也是:
| |
如果想训练更快,可以改成:
| |
如果想保留更多细节,可以改成:
| |
但是图片越大,显存占用越高,训练越慢。
我的建议:
| |
6. 调整是否只使用 recognized 样本
转换脚本里有:
| |
如果为 True,只使用 Quick, Draw! 中被系统识别成功的样本。
优点:
| |
缺点:
| |
如果想让模型更鲁棒,可以后期尝试:
| |
但建议 baseline 先保持:
| |
7. 调整数据增强
当前转换脚本里的增强比较保守:
| |
增强内容包括:
| |
这些增强不会改变几何位置,所以 YOLO 框不用重新计算。
后续如果想更贴近真实纸面照片,可以加入:
| |
但要注意:
| |
如果加入这些增强,就必须同步变换标注框,否则标签会错。
8. 调整检查脚本阈值
YOLO 数据集检查脚本里有几个阈值:
| |
如果训练的是线条类目标,很多框天然会比较细长,所以 extreme_ratio 和 small_wh 的 warning 可能会比较多。
如果确认这些是正常样本,可以适当放宽:
| |
但是 hard error 不建议轻易忽略,例如:
| |
这些问题应该先修复再训练。
9. 调整置信度阈值
预测脚本中有:
| |
如果误检很多,可以提高:
| |
如果漏检很多,可以降低:
| |
一般可以测试:
| |
观察哪个阈值最适合自己的场景。
10. 训练结果怎么看
训练结束后重点看:
| |
简单理解:
| 指标 | 含义 |
|---|---|
| Precision | 检出的东西有多少是真的 |
| Recall | 真实目标有多少被检出来 |
| mAP50 | IoU=0.5 下的平均检测性能 |
| mAP50-95 | 更严格的平均检测性能 |
如果:
| |
说明模型比较保守,漏检可能比较多。
如果:
| |
说明模型检得比较多,但误检可能比较多。
十五、后续微调真实纸面数据
Quick, Draw! 数据是干净白底手绘图,而真实纸面照片会有很多额外问题:
| |
所以 Quick, Draw! 训练出来的模型更适合作为基础模型。
真正落地时,建议继续做:
| |
微调命令示例:
| |
真实纸面数据建议至少准备:
| 数据量 | 适合阶段 |
|---|---|
| 300 张 | 快速验证 |
| 1000 张 | 初步可用 |
| 3000 张 | 比较稳定 |
| 10000 张以上 | 更接近生产使用 |
十六、我的当前结论
这套方案的意义不是直接得到一个最终可商用的纸面线条识别模型,而是先训练出一个手绘风格基础模型。
当前流程可以总结为:
| |
我后续主要会继续优化三件事:
| |
最终目标是让模型不仅能识别干净白底手绘图,也能识别真实纸张上拍摄出来的线条和图形。