YOLO11cls农作物病虫害分类实战:数据集构建、训练调参与避坑指南

发布时间:2026/9/30 1:35:52
YOLO11cls农作物病虫害分类实战:数据集构建、训练调参与避坑指南 简介面向农作物病虫害识别与图像分类训练场景这份资源提供包含1000张真实图片的分类数据集覆盖腰果、木薯、玉米、番茄四类作物的22种健康与病害状态可直接用于YOLO11cls等图像分类模型训练也适合作为通用分类数据补充。数据按分类文件夹整理标签清晰、标注质量高省去手动整理环节配套一键训练脚本与博主训练结果日志便于复现实验、对比不同病害类别的识别效果并调整参数。资源包为1个PDF文件大小5.63MB内含数据集详细介绍与百度网盘获取方式。目前已有63人学习适合农作物病虫害分类初学者及需要评估样本形态的算法工程师。1. 农作物病虫害分类数据集不只是给 YOLO11cls 用的收到这份「目标分类-农作物病虫害分类数据集-1000张图对应分类文件夹整理YOLO11cls一键训练脚本」时我第一反应是又一个打包好的小数据集但解压看过后发现它比很多标称几千张的商用数据集更省心图片全部来自真实田间场景类别用文件夹区分不需要自己写标注格式转换配的 YOLO11cls 训练脚本改个路径就能跑通。适合正在做农业视觉项目、需要快速验证分类思路、或者想把 YOLO11 分类能力跑一遍的从业者。如果你正处于「手上没有靠谱数据、又不确定分类模型在病虫害场景下能到多少准确率」的阶段这份资源能直接跳过到处爬图、清洗、重命名的脏活。更关键的是它把训练入口压缩成一个脚本降低了从裸数据到模型产出的门槛。2. 数据到底怎么样22 个类别、文件夹标注与检查清单这一章不急着跑训练先把数据集的结构和内容摸清楚。这份数据集覆盖腰果Cashew、木薯Cassava、玉米Maize和番茄Tomato四类作物的主要病虫害与健康状态归类成 22 个类别。这是典型的植物病害分类任务Plant Disease Classification类别列表如下作物类别文件夹名腰果 Cashewanthracnose炭疽病、gumosis流胶病、healthy健康、leaf miner潜叶蝇、red rust赤锈病木薯 Cassavabacterial blight细菌性枯萎病、brown spot褐斑病、green mite绿螨、healthy健康、mosaic花叶病玉米 Maizefall armyworm草地贪夜蛾、grasshoper蝗虫、healthy健康、leaf beetle叶甲、leaf blight叶枯病、leaf spot叶斑病、streak virus条纹病毒番茄 Tomatohealthy健康、leaf blight叶枯病、leaf curl卷叶病、septoria leaf spot斑枯病、verticulium wilt黄萎病2.1 文件夹组织方式为什么能直接喂给 YOLO11clsYOLO 系列做图像分类时目录结构跟目标检测完全不同——检测需要 JSON/XML/TXT 标注文件分类只需要把图片按类别放进对应文件夹。这份数据用的就是后者dataset/ ├── Cashew_anthracnose/ │ ├── 0001.jpg │ ├── 0002.jpg │ └── ... ├── Cashew_gumosis/ ├── Cassava_mosaic/ ├── Maize_leaf_blight/ ├── Tomato_leaf_curl/ └── ...Ultralytics YOLO11cls 的数据加载逻辑是读根目录下的每个子文件夹名作为类别标签文件夹里的图片自动归入该类。所以拿到手后不用做任何格式转换只需要把数据按比例拆成 train 和 val 两个大目录即可。常见做法是用 Python 的train_test_split按 8:2 切分或者shutil逐类移动。我一般会保证每类的验证图片不少于 5 张否则验证指标波动会很大。2.2 数据质量检查训练前必须做的三件事标注格式干净不代表可以直接开工。第一次跑之前我建议花十分钟做三项检查第一统计每类图片数量。1000 张分 22 类必然存在不均衡——健康类往往多于病害类少数病害类别可能只有二三十张。用以下脚本快速摸底import os data_root dataset for cls in sorted(os.listdir(data_root)): cls_path os.path.join(data_root, cls) if os.path.isdir(cls_path): count len([f for f in os.listdir(cls_path) if f.lower().endswith((.jpg, .jpeg, .png))]) print(f{cls}: {count} 张)参数说明cls是类别名脚本判断路径下的文件后缀来计数避免把隐藏文件或临时文件算进去。输出会是一张 22 行的统计表能立刻看出哪些类别是少数类。第二随机抽图看尺寸是否统一。YOLO11cls 内部会做letterbox缩放不要求原始图尺寸一致但如果混入大量超小图小于 224×224模型学到的特征会受限。抽检方法是从每类随机选三张打印shapefrom PIL import Image import random, os sample_cls Tomato_leaf_curl files os.listdir(fdataset/{sample_cls}) for f in random.sample(files, 3): img Image.open(fdataset/{sample_cls}/{f}) print(f{f}: {img.size})第三确认图片不是损坏文件。真实场景采集的图片偶尔会有 IO 错误或截断轻则训练中断重则 tensor 维度异常。用PIL.Image.verify()遍历一遍能提前排雷这也是我把这个习惯保留到所有数据集项目的原因——多花五分钟好过训练到一半崩掉。3. YOLO11cls 一键训练脚本结构、参数与正确打开方式数据摸底做完后进入真正的训练环节。配套资源里的 YOLO11cls 训练脚本本质上是 Ultralytics 框架的封装核心逻辑是读数据路径、加载预训练权重、启动训练。这类脚本的好处是参数集中、开箱即用但如果你准备换数据集或调优还是得理解每一行在干什么。3.1 训练脚本里的关键代码块下面是我按这套资源的标准习惯整理出的训练入口脚本from ultralytics import YOLO if __name__ __main__: model YOLO(yolo11s-cls.pt) # 加载分类预训练权重 model.train( dataD:/crop_disease_dataset, # 数据集根目录含 train/ 与 val/ epochs50, batch32, imgsz224, patience10, lr00.001, optimizerAdamW, device0, # 单卡训练 workers4, projectruns/classify, namecrop_disease_yolo11s, pretrainedTrue, # 使用预训练权重 seed42 )逻辑说明脚本先加载yolo11s-cls.pt——这是 YOLO11 做图像分类任务的预训练权重n/s/m/l/x 对应不同的模型容量与推理速度。data指向数据集根目录Ultralytics 会自动识别 train 和 val 子目录。pretrainedTrue表示在 ImageNet 分类权重上继续训练这是小数据集场景下的常规操作——从零训练分类模型在千张图片规模上收敛慢且容易过拟合。参数说明epochs50对 1000 张图的规模50 轮训练在 NVIDIA 3060 上大约 15-25 分钟。如果验证准确率在 20 轮后就不再上升patience10会早停。imgsz224分类任务的标准输入尺寸。YOLO11cls 支持 160-640 区间但 224 是速度和精度的平衡点如果你要部署到移动端可以降到 160代价是准确率通常下降 1-3 个点。batch32显存不足时优先调小这个数8GB 显存建议 166GB 建议 8。optimizerAdamW小数据集上 AdamW 收敛比 SGD 稳适合快速出结果追求极限精度可以把优化器换回 SGD配合cos_lrTrue但训练时间会拉长。3.2 从裸文件夹到可训练目录还差一步切分很多第一次用这份数据的人会直接把根目录丢给data参数结果报错“找不到 train/val”。原因在于原数据只有类别文件夹没有拆训练验证集。正确做法是先建两个目录再按比例移动图片python -c import os, shutil from sklearn.model_selection import train_test_split src dataset train_dir, val_dir crop_disease_split/train, crop_disease_split/val os.makedirs(train_dir, exist_okTrue) os.makedirs(val_dir, exist_okTrue) for cls in os.listdir(src): cls_path os.path.join(src, cls) if not os.path.isdir(cls_path): continue files os.listdir(cls_path) train_files, val_files train_test_split( files, test_size0.2, random_state42 ) for split, subset in [(train_dir, train_files), (val_dir, val_files)]: os.makedirs(os.path.join(split, cls), exist_okTrue) for f in subset: shutil.copy(os.path.join(cls_path, f), os.path.join(split, cls, f)) print(切分完成) 说明test_size0.2控制验证集比例random_state42固定随机种子保证每次运行切分结果一致——这一点在复现训练日志时非常重要种子不同导致数据分布不同准确率差异会被误判成模型问题。这里用copy而不是move是避免原始文件夹被破坏如果你确认不再需要原目录可以换成move省一半磁盘空间。3.3 训练启动与日志观察脚本写好、目录切分完成后运行入口是一行命令python train.py第一次启动时Ultralytics 会自动校验数据集结构输出类似 22 classes、train images 800、val images 200 的摘要。训练过程会实时打印每个 epoch 的 loss、top1_acc、top5_acc。跑完后runs/classify/crop_disease_yolo11s/下会生成weights/best.pt和last.pt以及results.png训练曲线、confusion_matrix.png混淆矩阵。这里有个值得注意的点Ultralytics 的Trainer默认会在yolo11s-cls.pt同目录下找配置文件如果你环境变量配置得乱可能加载到缓存里的旧权重。我习惯在model YOLO(yolo11s-cls.pt)前加一行print(model.model_name)确认模型身份免得训了半天发现用的是别人的自定义权重。4. 训练结果日志怎么读准确率之外要看的四个指标博主随资源附了训练结果日志这比脚本本身更值得研究。很多新手拿到日志只会看最后的 top1_acc但实际项目中准确率只是及格线还要看混淆矩阵、每类召回、loss 曲线收敛性和早停位置。4.1 从 results.png 判断模型是否正常收敛训练结束后会自动画出results.png里面通常包含训练损失、验证损失、top1/top5 准确率四张子图。正常收敛的标准是训练损失曲线单调下降最后趋于平台没有明显拉升验证损失前期下降、后期轻微上升属于正常波动但如果训练损失持续下降而验证损失一路走高就是典型的过拟合需要提前早停或加大数据增强top1_acc 在 50 轮内达到 80% 以上说明数据质量是够的如果看到验证损失曲线的形状像笑脸先降后升表示模型在第 20 轮附近就开始记住训练集的噪声。此时不要盲目增加 epochs而是回看patience设置——Ultralytics 默认 patience100 对 1000 张图太宽建议收紧到 10-15让它在验证集开始恶化时立刻保存最优权重。4.2 混淆矩阵解读错误集中在哪类confusion_matrix.png是 22 行的热力图行代表真实类别列代表预测类别。对角线越亮越好看矩阵时重点找两类问题第一相似病害互相混淆。比如番茄叶枯病Tomato_leaf_blight和斑枯病Tomato_septoria_leaf_spot叶片症状在视觉上高度相似混淆率高是正常的。如果项目对这两种病必须严格区分仅靠 RGB 图像训练到 90% 以上的分类准确率很困难常见做法是引入多光谱数据或做细粒度分类fine-grained classification。第二少数类整体偏暗。某个类别的行整体暗淡代表该类别几乎没被正确预测到原因是训练样本太少。解决方式不是立刻加数据而是先给这个类单独打印置信度输出——我在调试时通常把模型输出的probs保存成 CSV统计每个类别的平均置信度判断是「模型学不会」还是「模型学会了但置信度被压低了」。4.3 用博主日志做基准对比而不是迷信数字附赠的训练日志最大的价值是给你一个可参考的基准。假设日志里记录的最佳准确率是 97%你复现时跑到 94%这 3 个点的差距可能来自训练硬件不同导致 batch 行为差异切分数据时随机种子不同环境依赖版本不一致Ultralytics 版本号差异会影响默认超参我的做法是把博主日志里的 epoch 数和 loss 值当成「这条数据在这个模型规模下应该有的表现」而不是「必须达成的目标」。复现时只要曲线趋势一致、最终准确率在 2-3 个点以内浮动都算正常。5. 避坑指南训练农作物分类数据集最容易踩的五个坑这部分写的是我用这套数据和同类农业数据集时真实遇到过的坑每条按「现象 → 原因 → 解决」整理希望能让你少走弯路。5.1 文件夹路径含有中文模型直接报错现象训练启动后报NotADirectoryError或FileNotFoundError指向的路径看起来是完整的。原因Windows 环境下如果数据集根目录或类别文件夹名包含中文比如「番茄_叶霉病」Ultralytics 底层调用的文件操作在部分编码环境下会失败。解决把所有目录名、文件名统一改成英文或拼音这也是这份数据集中类别全部用英文命名的原因。改动命令rename s/[\x80-\xff]//g dataset/*/ # Linux 下清除非 ASCII 字符Windows 用户直接在资源管理器里批量重命名即可操作完再跑python -c import os; print(os.listdir(dataset))确认路径干净。5.2 类别极度不均衡多数类准确率高、少数类全是 0现象训练日志显示 top1_acc 高达 95%但打开混淆矩阵发现某一两个类别完全没有正确预测。原因1000 张图分到 22 个类别后部分病害类别可能只有 20-30 张。模型在训练时把多数类的梯度主导了少数类的特征完全被淹没。解决优先降低多数类的采样权重而不是直接删数据。Ultralytics 支持通过class_weights参数指定各类别的损失权重先统计频次再计算权重import numpy as np counts np.array([35, 80, 120, 30, ...]) # 按类别顺序填实际数量 weights counts.sum() / (len(counts) * counts) model.train(..., class_weightsweights)如果不想动权重另一个常见做法是对少数类做离线增强——旋转、亮度抖动、随机裁剪各生成 3 份副本把单类数据量补到 50 张以上。注意是「补」不是「超采样同一张图」后者会让模型记住特定图片而非病害特征。5.3 验证集没有按类别分层抽样现象训练 loss 正常下降但验证准确率忽高忽低波动超过 10 个点。原因如果用随机切分而不是分层切分400 张验证集里某些类别只有 1 张图这一张被预测对还是错直接影响 2-3 个百分点的整体准确率造成指标不稳定。解决切分时必须按类别分层。train_test_split加上stratifyy其中y是每条样本对应的类别标签数组。前面给出的切分脚本如果漏了stratify请务必补上。5.4 显存不足OOM 崩溃只在训练到一半时出现现象训练前几个 epoch 正常第 3 轮后报CUDA out of memory。原因PyTorch 在训练过程中会缓存中间激活值显存占用随 batch 累积不是启动时就能暴露的。另外如果开了cacheTrue把图片加载进内存也会增加显存压力。解决先把batch从 32 降到 16 再降到 8同时把workers从默认的 8 调低到 2避免数据加载线程抢占内存。如果还是 OOM检查imgsz是否被无意中调高——有人会在调试时把imgsz640跑分类显存开销直接翻倍。5.5 复现结果不一致明明跑同一个脚本准确率差 5 个点现象同一份数据集、同一个脚本换了台机器或隔了几天重跑top1_acc 从 93% 掉到 88%。原因最常见的是随机种子没固定其次是 Ultralytics 框架更新导致默认超参变化。YOLO11 的版本迭代很快v8.2 和 v8.3 的数据增强策略有实际差异。解决把所有随机源固定下来。PyTorch 的随机性来自三处——数据加载顺序、权重初始化、数据增强。在脚本开头写入import random, torch random.seed(0) torch.manual_seed(0) torch.cuda.manual_seed_all(0)然后把训练参数里的seed42固定住。另外务必在项目里记录 Ultralytics 版本号pip freeze | grep ultralytics否则未来环境重建时很难追查指标漂移。6. 从训练到部署项目落地前我认为最有用的三个验证模型训练完不是终点。你如果想要在真实场景里用它这三个验证步骤我建议一个都别省。第一步单张图推理测试。用训练好的best.pt对每类各抽一张图做预测看输出类别和置信度分布。执行以下命令yolo classify predict modelruns/classify/crop_disease_yolo11s/weights/best.pt sourceD:/test_images注意source如果是文件夹Ultralytics 会遍历所有图片如果是单张图直接传图片路径。预测结果会存在runs/classify/predict目录下包含标注了类别和置信度的输出图。这一步能快速判断模型在「非训练集拍摄条件下」的泛化能力——比如换手机拍、换光照角度。第二步导出 ONNX 验证部署可行性。分类模型最终多半要集成到 App 或 Web 服务里ONNX 是跨平台部署的标准格式yolo export modelbest.pt formatonnx imgsz224导出后会生成best.onnx可用 ONNX Runtime 在 CPU 上跑。这一步最重要的意义是提前验证模型能不能脱离 PyTorch 环境独立推理很多项目就是训练阶段跑得好、导出阶段发现算子和版本不匹配才回头改架构。第三步构建最终的分类映射表。训练时用的类别名是英文文件夹名如Maize_fall_armyworm但部署时用户看到的是中文名或结构化字典。训练结束后我建议立刻维护一张映射表并写入 JSON 或 YAMLMaize_fall_armyworm: 玉米草地贪夜蛾 Maize_grasshoper: 玉米蝗虫 Tomato_leaf_curl: 番茄卷叶病这张表看起来不起眼但实际部署时几乎每个团队都会折在「模型输出是英文 label业务系统要的是中文别名」的对接上。开发者觉得是小事产品那边却要反复确认耗时远大于建表本身。从那次之后我形成了自己的习惯每次拿到这类带文件夹分类的数据集强制走一遍「统计类别分布 → 分层切分 → 固定随机种子 → 训练 → 导出 ONNX → 维护映射表」的流程。这套流程走完模型能不能用、哪里不行、部署有没有坑基本都心里有数了。希望这份笔记能帮到你也祝你的农作物分类项目顺利落地。资源获取方式在文末记得回复对应凭证就行。本文还有配套的精品资源点击获取