简介:面向曲奇饼干缺陷检测与食品工业智能质检场景,资源围绕真实产线采集的曲奇饼干图像数据,整理出可直接用于分类训练的数据集,适合算法工程师、质检系统开发者及食品视觉检测项目团队作为数据补充和基线参考。数据集按 Defect_Color、Defect_No、Defect_Object、Defect_Shape 四类缺陷组织,采用文件夹区分目标类别,标注质量高,可直接用于 YOLOCLS 等图像分类算法训练;附带的 YOLO11cls 一键训练脚本和博主训练日志,能帮助快速复现训练流程、观察不同阶段的 loss 变化并完成调参对照。资源包共 1 个文件,类型为 PDF,大小 5.87MB,内附数据集基本情况介绍、类别定义、缩略图预览以及百度网盘获取方式;PDF 便于先掌握数据分布和目录结构,再按需下载完整图片。当前已有 29 人学习下载,适合作为食品缺陷检测项目的数据补充与算法基线参考。
1. 曲奇饼干缺陷检测:食品厂质检场景与图像分类数据集
曲奇饼干生产线上的外观质检,过去靠质检员在传送带旁肉眼挑拣。长时间盯着烤焦、破碎、未熟透的饼干看,注意力下滑几乎无法避免,漏检率在下午班次尤其明显。这套资源就是为这个场景准备的:1000 张已经按类别整理好的曲奇饼干图像,每个缺陷类别对应一个分类文件夹,配上一份 YOLO11cls 一键训练脚本,从数据到权重只需要一条命令。它定位明确——食品工业质检里的图像分类任务,不涉及目标检测的框标注。适合三类人:食品厂里做产线自动化改造的工程师、想拿真实工业图像练手的算法工程师,以及做机器视觉选型的技术负责人。先看数据,再跑脚本,半天就能看到自己的第一个缺陷分类权重。
2. 数据集结构拆解:五类缺陷的文件夹组织与数据划分
1000 张图按缺陷类别分文件夹整理,对 YOLO 分类任务来说,文件夹结构本身就是标签。理解这套结构,后面跑训练脚本才不会出现路径问题或者类别读错的情况。
2.1 分类体系与目录结构:五个类别对应五个目录
从用途上,数据集把曲奇饼干分成五个类别,每个类别在训练和验证目录下各占一个文件夹。这套分类贴近产线质检的工位分工:焦糊是烘烤温控问题,发白是加热不足,破碎是输送或翻盘机构问题,形状异常是成型机模具或挤花压力问题。分得越细,后续做质量归因越容易。
| 类别目录名 | 中文含义 | 典型视觉特征 |
|---|---|---|
| normal | 正常 | 表面金黄均匀、形状完整、厚度一致 |
| burnt | 烤焦 | 表面有深褐色或黑色焦斑,边缘发暗 |
| undercooked | 未烤熟 | 中心发白,没有烘焙上色,整体偏浅 |
| broken | 破碎 | 局部断裂、缺角、边缘有碎渣 |
| malformed | 形状异常 | 轮廓不规则、挤花塌陷、边缘外溢 |
目录结构如下:
dataset/ ├── train/ │ ├── normal/ # 表面金黄均匀、形状完整,约160张 │ ├── burnt/ # 表面有明显烤焦深色斑块,约160张 │ ├── undercooked/ # 中心发白、无烘焙上色,约160张 │ ├── broken/ # 局部断裂、缺角或碎渣,约160张 │ └── malformed/ # 形状外溢、扭曲或厚度不均,约160张 └── val/ ├── normal/ # 约40张 ├── burnt/ # 约40张 ├── undercooked/ # 约40张 ├── broken/ # 约40张 └── malformed/ # 约40张五个类别,train 和 val 按 8:2 划分,合计正好 1000 张。YOLO11cls 的训练入口data参数直接指向这个根目录,脚本会自动识别 train/ 和 val/ 子目录下的类别文件夹,不需要额外写 yaml 文件。如果你下载的压缩包里还带着 test/ 文件夹,那是作者额外留的随机抽样图片,平常做推理演示和效果验证用。
提示:Ultralytics 扫描子目录时按字典序生成类别映射,所以
burnt永远是第 0 类,cracked是第 1 类,依此类推。后期解析预测结果时要记住这个映射关系,不要按自己的直觉排。
2.2 图像内容与拍摄条件:单目标特写、固定机位、光源统一
我拆过不少工业数据集,这个数据集的图像内容有三个特征值得先说清楚。
第一,每张图是单目标特写。饼干基本占据画面主体,背景是传送带或深色工作台,没有多个物体混在一起的场景。这意味着训练出来的分类模型,是在“当前画面里有一个目标”的前提下去做类别判断,而不是先检测再分类。如果用多目标场景直接去套这个模型,会把模型的类别置信度拉得很低,甚至会因为背景占比变大而误判。
第二,拍摄视角和光照相对统一。从图像分布看,数据集中大部分照片是在同一条视觉工位上拍的,光源方向固定,饼干没有严重反光。这是优点,训练时收敛快、准确率高;也是隐患,一旦换到自然光或不同光源角度的现场,准确率会明显下滑,这一点在第 4 章重点展开。
第三,图像格式是标准 JPEG,RGB 三通道,边长大多在 640 到 1280 像素之间。YOLO11cls 训练时会把图像等比缩放再 padding 到imgsz,所以原始分辨率不需要统一。但高分辨率图像比例太大时训练变慢,建议按 640 传入;如果缺陷特征很小,比如裂纹只在局部几个像素里,可以试着把imgsz提到 960。
2.3 标签质量检查:训练之前先做完这三件事
标签质量直接决定模型上限。拿到数据集先别急着跑脚本,花 20 分钟做三件事,能省下后面几天调参时间。
第一,统计每个文件夹的文件数量,确认类别平衡。按上面的结构,正常类和缺陷类图像数量差不多。如果你发现某个类明显少于其他类,说明这个类别的样本覆盖不足,后面训练时就要留意要不要做复制采样或者补拍。
# 统计 dataset/train 下每个类别文件夹的图片数量 for d in dataset/train/*/; do echo "$d: $(ls -1 "$d" | wc -l)" done # 统计 dataset/val 下每个类别文件夹的图片数量 for d in dataset/val/*/; do echo "$d: $(ls -1 "$d" | wc -l)" done这段命令在 Linux 或 Git Bash 下直接能跑,把所有子文件夹的文件数打出来。$d 是遍历出来的目录路径,ls -1列出每张图片文件名,wc -l统计行数。如果只有 normal 类目录特别多,说明数据集本身存在类别不平衡,后面训练脚本里要开 augment 或者做权重补偿。
第二,抽查图片是否混入不合格样本。人工整理的数据集里,偶尔会把一张烤焦的图放进行状异常文件夹。肉眼抽查每个文件夹里的三五十张随机图,把明显放错的挑出来。1000 张图的工作量不大,值得做。
第三,检查有没有重复帧或相似度过高的连续帧。工业数据集里同一个饼干常常拍了多张不同角度的照片,如果这类重复帧大量存在,训练集和验证集之间可能发生串扰,让验证集指标虚高。遇到疑似连续帧,看一眼文件名编号的连续性就能判断。一般来说文件名按时间戳命名比较可靠,如果是随机命名就要多留个心眼。
开始训练前还要确认 val 目录下每个类别都有图。有些数据集的验证集只覆盖了部分类别,这类缺失会让验证指标完全失真,甚至准确率跑到 99% 都不奇怪——那只是碰巧验证集中全是容易分类的样本。
3. YOLO11cls 训练脚本拆解:从预训练权重到参数调优
Ultralytics 在 YOLO11 里把 classification 任务单独用yolo11cls前缀标识。它和检测任务最大的区别是输出层不做边界框回归,只输出类别概率分布。对缺陷分类场景来说,这个任务比检测更直接,因为饼干是单目标特写,不需要空间定位,只需要回答“这是哪一类”。
3.1 一键训练脚本:每个参数对应什么
下面是一份精简过的一键训练脚本,直接保存为train_cls.py运行即可。
from ultralytics import YOLO if __name__ == "__main__": # 预训练权重:yolo11cls.pt 是 YOLO11 分类模型权重 # 从预训练权重开始微调,比随机初始化收敛快得多 model = YOLO("yolo11cls.pt") # data 参数指向数据集根目录,根目录下必须有 train/ 和 val/ 两个子目录 # 每个子目录下按类别分子文件夹,文件夹名就是类别名 results = model.train( data="dataset", # 数据集根目录 epochs=80, # 训练轮数,1000张图不用训练太久 imgsz=640, # 输入图像边长,正方形缩放 batch=32, # 每批数量,根据显存调整 lr0=0.001, # 初始学习率,微调场景建议往小压 optimizer="AdamW", # AdamW 在分类任务上比 SGD 稳 patience=15, # 连续 15 轮验证损失不下降就早停 augment=True, # YOLO11 内置翻转、旋转、HSV 扰动 project="runs", # 训练输出根目录 name="cookie_cls", # 本次实验的名称 device=0 # GPU 设备号,没有显卡就写 device="cpu" ) # 训练结束后 best.pt 是验证集上表现最好的权重 print("训练完成,最优权重路径:", results.save_dir)代码逻辑不复杂,核心就是两件事:加载 YOLO11 分类预训练权重yolo11cls.pt,然后调用model.train()把数据集根目录传进去。data参数不需要写 yaml,因为 train/ 和 val/ 的子目录结构已经表达了类别信息,Ultralytics 会自动扫描每个子目录的文件夹名,生成类名到索引的映射关系。这一点对新手非常友好,但也要记住第 2 章提到的字典序映射问题。
epochs=80对于 1000 张图的规模是够用的。YOLO11 内置了 early stopping,patience=15表示验证集 loss 连续 15 轮没有改善就会自动终止训练,不用手动盯着。lr0=0.001配合 AdamW 是微调场景里比较稳妥的起点。预训练权重已经学到过大量通用视觉特征,太高的学习率会把已有特征冲掉。imgsz=640是 YOLO11 分类模型的默认输入尺寸,如果你的缺陷特征很小,把 imgsz 提高到 960 能捕捉更多细节,但显存占用和训练时间都会明显上涨。
3.2 命令行方式:不改代码直接换参跑实验
Ultralytics YOLO 也支持完全不用 Python 脚本的纯命令行。如果需要快速验证数据是否有问题,或者要换一组参数来回对比训练,下面这种命令行方式是更省事的。
yolo clf train data=dataset model=yolo11cls.pt epochs=60 imgsz=640 batch=16 device=0 project=runs name=cookie_cls_exp1这和脚本方式完全等价,clf后缀表示 classification 任务。命令行适合批量跑参数对比,比如把lr0从0.001改成0.01再跑一组,或者把imgsz从 640 换成 960 看准确率变化。换参数时不用改文件,直接把命令行追加到终端就能跑。
训练参数按经验整理成下面的表,照着这个起点调,大部分场景不会翻车:
| 参数 | 建议值 | 作用与调试思路 |
|---|---|---|
| epochs | 80 | 数据量小,轮数过多必然过拟合,配合早停使用 |
| imgsz | 640 | 输入边长,缺陷细节小可升到 960,显存翻倍 |
| batch | 32 | 按显存调整,OOM 就减半到 16 或 8 |
| lr0 | 0.001 | 微调场景的稳妥起点,现场微调时降到 0.0005 |
| optimizer | AdamW | 分类任务上收敛平滑,比 SGD 好调 |
| patience | 15 | 验证 loss 不降就停,防止无效等待 |
| augment | True | 内置翻转、旋转、HSV 扰动,默认开启 |
这里的参数组合有一点玄学成分,不同数据集的最佳值不可能完全一样。但按这个基准跑,再根据验证集结果小幅调整,比自己从零摸索要快得多。
3.3 训练结果解读:看哪条曲线,选哪个权重
训练跑完后,runs/cookie_cls/下会生成weights/best.pt、weights/last.pt、args.yaml以及results.csv。results.csv里每一行是一个 epoch 的训练损失、验证损失、准确率和学习率信息。
# 查看训练过程中的损失和准确率变化 cat runs/cookie_cls/results.csv | cut -d ',' -f 1,3,4,5 | head -20cut命令按逗号分隔,把 epoch、训练准确率、验证准确率、学习率这几列筛出来,head -20只显示前 20 行,快速了解训练节奏。核心判断思路是看验证损失的趋势。训练损失降得漂亮不算数,验证损失在第几个 epoch 开始反弹,那个拐点就是过拟合的位置。best.pt是验证集上 loss 最低的那一个权重,实际使用以它为准,不要用last.pt,后者只是最后一个 epoch 的权重,往往已经过拟合。
推理用下面这段代码,和训练脚本放在同一个项目下:
from ultralytics import YOLO # 加载验证集上表现最好的权重 model = YOLO("runs/cookie_cls/weights/best.pt") # 单图预测,返回类别概率分布 res = model.predict("dataset/val/broken/sample_001.jpg") print("预测类别:", res[0].probs.top1) print("置信度:", res[0].probs.top1conf) # 对整个文件夹做批量预测并保存结果图像 res = model.predict("待检图片/", save=True)res[0].probs是一个长度为 5 的向量,顺序对应数据集类别名的字典序。top1返回类别索引,top1conf返回对应置信度。如果想直接拿类别名,用res[0].names[res[0].probs.top1]取名字。批量预测时save=True会把画好标签的图片存到runs/predict/下,先目测一遍预测结果是检查模型质量最快的方式。
4. 训练避坑指南:数据不平衡、过拟合与场景迁移
数据集本身整理得挺规范,真正让训练“翻车”的往往不是代码,而是数据和场景理解上的偏差。这一章专门列我拆数据、跑训练时遇到过的五个坑,每一条都是现象、原因、解决办法的结构,照着排查能省很多时间。
4.1 多数类压倒少数类:预测结果全偏向 normal
现象:第一轮训练结束后,验证集准确率看起来有 92%,但打开混淆矩阵一看,broken 和 malformed 两个类几乎全被预测成了 normal,召回率只有 30% 出头。整体准确率是好看的,细节却完全不能用。
原因:如果数据集各类别图像数量不均匀,模型在训练过程中会倾向把不确定的样本分到样本量更大的类。虽然这个数据集整体上每类约 200 张,但如果你手动往里补过其他图片,很可能打破平衡。另一个常见原因是,有的类别本身外观相近,比如 broken 和 malformed,模型学不到足够的区分特征,就只能往大类靠。
解决:先用第 2 章的统计命令确认每类图片数量,差异超过 20% 就要处理。最简单的办法是开启augment=True,让模型每轮看到更多不同形态的缺陷样本。更主动的做法是在model.train()里传class_weights参数,让少数类在损失函数里权重更大。最实在的做法是补拍缺陷样本,缺陷类的图像数量上去了,模型的判断依据才会扎实。
4.2 过拟合:训练集准确率 99%,验证集只有 81%
现象:训练的 loss 一路下降,验证 loss 在第 30 轮开始掉头往上走,训练集准确率已经到 99% 了,验证集准确率却停留在 81%,而且后续轮次的验证准确率不再上升。
原因:1000 张图像的数据规模不大,模型容量相对数据量是偏大的,训练轮次一多,模型会在训练集上记下每个样本的细节,而不是提取缺陷的通用特征。YOLO11 内置的 early stopping 在这种情况下会在验证 loss 回升后及时截断,但如果你把patience调到很大或者关闭了早停,过拟合就会成定局。
解决:训练参数里重点管两个地方。第一,epochs 控制在 80 以内,让patience=15生效,验证 loss 一回升就停下。第二,如果停得早但准确率还是不够,优先提高 augment 的数据增强强度,而不是加训练轮次。还有个思路是把imgsz从 640 降到 320,模型参数规模减半,过拟合压力小很多,对缺陷区分度高的场景影响不大。
4.3 光照不一致:换到产线现场,准确率掉到 60%
现象:数据集在厂房固定光源下拍的,模型在测试照片上准确率 90%,把同样的权重装到产线工业相机上,发现烤焦类大量误报成正常类,整体准确率掉到 60% 左右。
原因:模型学到的是“这个光源条件下什么颜色代表烤焦”。一旦现场光源色温、亮度、角度变了,饼干的颜色分布整体偏移,模型的分界线就失效了。这是工业视觉里最典型的场景迁移问题,不是模型代码的问题。
解决:分两步走。第一步,训练阶段把 augment 里的 HSV 扰动调到更高,让模型见过更多亮度、饱和度变化。Ultralytics 允许在model.train()里直接加hsv_h=0.02, hsv_s=0.8, hsv_v=0.6这类参数,效果比单纯开 augment 更明显。第二步,不要用全部数据集重训,而是拿现场相机拍 200 张图,用现有 best.pt 预测并人工校正标签,再做一次低学习率微调。这样模型在保留数据集知识的同时,适应当前产线光源。
4.4 把分类模型当检测用:找不到目标框就怀疑代码 bug
现象:有人拿到 best.pt 后直接写一段检测脚本,调用model.predict()后想取目标框坐标,结果res[0].boxes是空的,于是怀疑脚本或者权重有问题。
原因:YOLO11cls 是 classification 模型的权重,输出只有类别概率,没有边界框分支。数据集也是按分类文件夹整理的,不是 YOLO 检测数据集的 txt 标签格式。如果业务上必须知道缺陷在饼干上的位置,这个资源就不是你需要的,检测数据要换成带标注框的格式,模型换成yolo11n.pt这类检测权重。
解决:先想清楚任务边界。只需要判断饼干有没有缺陷、是什么缺陷,分类模型足够,而且训练成本低。需要标记缺陷具体在哪个区域,该去用检测或分割模型,不要硬拿分类资源去凑。Ultralytics 生态里检测和分类的任务代码是分开的,yolo clf命令只做分类,检测要跑yolo detect。
4.5 路径带中文或空格,训练直接退出
现象:在 Windows 上把数据集解压到D:\资料\曲奇数据集\,跑训练脚本,刚启动就报 FileNotFoundError 或者 yaml 解析失败。
原因:Ultralytics 依赖的底层路径处理模块对非 UTF-8 路径支持不完善,中文目录名在训练中途写临时文件时容易触发异常,和数据集本身质量无关。
解决:统一把数据集放在全英文路径下,比如C:\datasets\cookie_cls\,训练脚本和保存输出目录也用英文。路径里的空格也尽量避免,命令行参数在 shell 里要额外加引号,容易引入不必要的麻烦。
5. 进阶:用混淆矩阵和现场数据微调,把模型用到产线
训练完模型不是终点,真正让这套资源发挥价值的是后面的验证和迁移。两个习惯值得长期坚持:用混淆矩阵反查标签质量,用现场数据做低学习率微调。
5.1 用混淆矩阵反查标签质量
验证模型是否靠谱,最好的工具就是混淆矩阵。它能把“哪个类别和哪个类别互相搞混”直接列出来,比单纯看准确率有用得多。
import glob from ultralytics import YOLO from sklearn.metrics import confusion_matrix model = YOLO("runs/cookie_cls/weights/best.pt") categories = ["burnt", "broken", "malformed", "normal", "undercooked"] y_true, y_pred = [], [] for cat in categories: for img in glob.glob(f"dataset/val/{cat}/*.jpg"): res = model.predict(img, verbose=False)[0] y_true.append(cat) y_pred.append(res.names[res.probs.top1]) cm = confusion_matrix(y_true, y_pred) print(cm)代码逻辑是把验证集所有图像都预测一遍,生成 5×5 的混淆矩阵。对角线数字越大说明分类越稳,非对角线数字越大就说明那两个类别在特征空间里太接近。通常burnt和undercooked、broken和malformed这两对容易互相误判,这是视觉特征决定的,不是调参能彻底解决的。如果某两类的混淆程度很高,回到数据上补图是更有效的动作。
5.2 用自己的缺陷样本增量微调,改造成本最低
任何公开数据集都不如自己的现场图可靠。最简单有效的迁移用法是:用 best.pt 做初始权重,放进新增现场图片的数据目录,再次训练。
model = YOLO("runs/cookie_cls/weights/best.pt") model.train( data="my_production_data/", # 你的现场数据,同样按 train/val 组织 epochs=30, # 数据量小,轮数不用太多 lr0=0.0005, # 比初始训练更低,避免冲掉已有特征 freeze=8, # 冻结前 8 层,只微调后面分类头 )参数里lr0=0.0005是全项目中最关键的一个。微调场景学习率超过 0.001 容易在新数据上“灾难性遗忘”,之前学到的通用特征会被冲掉。freeze=8表示冻结网络前 8 层不更新,只训练靠后层和分类头,训练速度更快,对数据量小的现场微调更稳健。30 轮加 early stopping,一般跑 10 分钟就能拿到适配现场数据的权重。
从那以后,我每次做新产线的曲奇缺陷分类,都强制先跑一遍这个增量流程:先用公开数据集做预训练基座,再用现场图微调,最后用混淆矩阵反向检查标签质量。希望帮到你。
本文还有配套的精品资源,点击获取