简介面向农作物病虫害检测与图像分类场景这份资料以PDF文档形式提供了一套完整的数据集配套说明共1个文件大小5.63MB内附数据集详细介绍与百度网盘获取方式。数据集包含1000张真实场景高质量农作物图片覆盖腰果、木薯、玉米、番茄四大类作物细分出Cashew anthracnose、Cassava bacterial blight、Maize fall armyworm、Tomato leaf curl等22个类别采用文件夹区分标注质量高可直接用于YOLO11cls等分类算法训练。除数据外还提供YOLO11cls一键训练脚本并附有博主训练结果日志作为参考适合智慧农业、作物病害识别方向的算法工程师、科研人员及学习者用于项目验证或通用分类数据集补充。目前已有63人学习浏览资料结构清晰能帮助快速上手模型训练与效果评估。1. 1000 张图 22 类作物病虫害这份分类数据集能直接喂给 YOLO11cls 吗做农作物病虫害识别的第一道坎往往不是算法是数据。自己下田拍图费时费力从网上爬来的图分辨率参差、类别混乱标到一半就想放弃。这份数据集把 Cashew、Cassava、Maize、Tomato 四类作物的 22 种病虫害状态整理成了 1000 张真实场景图片文件夹的名字就是分类标签解压之后按 YOLO 分类任务的标准目录结构放好就能开训还附带 YOLO11cls 一键训练脚本和博主训练日志做参照。适合正在做农业视觉检测项目、又不想在数据整理上耗太多时间的从业者也适合拿来做通用图像分类数据集的场景补充。下面我从数据分布讲到训练脚本把能复现的细节和踩过的坑一并拆开。2. 数据集长什么样四类作物 22 个类别与文件夹标注的真实分布2.1 类别清单Cashew、Cassava、Maize、Tomato 怎么细分这份数据集覆盖三种大田作物加一种茄果类作物类别划分按照作物种类加病虫害英文名组合比如Cashew anthracnose是腰果炭疽病Maize fall armyworm是玉米草地贪夜蛾。完整类别如下表。作物类别数具体类别Cashew腰果5anthracnose炭疽病、gumosis流胶病、healthy健康、leaf miner潜叶蛾、red rust赤锈病Cassava木薯5bacterial blight细菌性枯萎病、brown spot褐斑病、green mite绿叶螨、healthy健康、mosaic花叶病Maize玉米7fall armyworm草地贪夜蛾、grasshoper蝗虫、healthy健康、leaf beetle叶甲、leaf blight叶枯病、leaf spot叶斑病、streak virus条纹病毒Tomato番茄5healthy健康、leaf blight叶枯病、leaf curl卷叶病、septoria leaf spot斑枯病、verticulium wilt黄萎病合计 22 类。这里有两类情况值得注意一类是虫害像 leaf miner、fall armyworm、leaf beetle图片里往往能直接看到虫体或明显的啃食痕迹另一类是病害和生理性状态像 cassava mosaic 的退绿花叶、leaf curl 的卷叶特征集中在叶片纹理和颜色变化上。这两类特征在卷积网络里的表征方式完全不同虫害靠形状和边缘病害靠颜色和纹理分布训练时对图像增强的参数取向也不一样。这个类别体系有实际项目背景不是随便凑的。腰果、木薯、玉米、番茄在热带和亚热带种植区是主要经济作物这四类作物的病虫害直接影响产量做农业植保项目时这 22 个类目基本覆盖了常见巡检需求。对做通用分类的人来说这份数据也能当场景补充尤其是 Cassava 和 Maize 的叶片纹理差异明显适合用来验证模型在细粒度分类上的表现。2.2 文件夹即标签YOLO 分类标注的核心逻辑YOLO 分类任务和检测任务在标注方式上完全不同。检测需要框坐标分类只需要告诉模型这张图属于哪个类。YOLO11cls 读取标签的方式就是看图片所在的文件夹路径文件夹叫什么里面所有图片就都属于这个类。所以这份数据集的标注形式非常直接Maize_leaf_blight文件夹下放的就是玉米叶枯病的图片没有额外的 XML、TXT 或 JSON 标注文件。这种标注方式的优点第一是省事整理数据的时候只要建好文件夹、把图片丢进去标注工作就完成了第二是出错率低不会出现标签和图片内容对不上的情况因为错误在归类那一刻就会暴露。缺点是粒度粗糙一张图里如果同时有健康叶片和病斑叶片模型只能学到这张图整体属于病叶做不到像素级或实例级的区分。所以这份数据集适合做田块级或单株级的病害识别不适合做病斑定位。用文件夹做标签还有一个隐含要求路径里不能出现中文和空格。YOLO 的 dataloader 在解析路径时对特殊字符很敏感中文路径在 Windows 上偶尔能跑在 Linux 服务器上大概率报错。我接手这类数据集第一件事就是把所有文件夹重命名为纯英文后面训练会少很多莫名其妙的报错。2.3 1000 张图对 22 类是否够用从分布和增广两个角度看1000 张图平均到 22 类每类大约 45 张这个规模在深度学习里属于小而致密的数据集。说实话每类 50 张左右的图直接训练一个大模型很容易过拟合但 YOLO11cls 带 ImageNet 预训练权重从预训练模型做迁移学习的话这个数据量足够训练出一个可用的分类器前提是类别分布相对均衡。你可以在解压后用下面这个命令快速统计各类图片数量看看数据分布是否均匀find . -type f \( -name *.jpg -o -name *.jpeg -o -name *.png \) | \ awk -F/ {print $(NF-1)} | sort | uniq -c | sort -rn这段命令的含义是find递归找出所有图片文件awk按斜杠切分路径并取出倒数第二个字段也就是图片所在文件夹的名字再用sort | uniq -c统计每个类别的图片数最后按数量倒序排列。如果看到某个类别只有十几张而其他类别有六十多张训练时就要考虑类权重或者多做增广。1000 张图还有一个现实意义单卡训练速度快。用 YOLO11cls 的 n 版本在消费级显卡上100 轮几分钟就能训完迭代调参的成本很低。这对做项目验证非常友好可以快速试不同的数据增强组合和超参数而不是一次训练等半天。数据量小意味着容错率高这是小数据集在工程上的隐藏优势。3. 训练前先把数据捋顺YOLO11cls 的目录组织与数据划分3.1 把分类文件夹转成 YOLO11cls 能读的标准目录结构YOLO11cls 分类训练默认读取的数据目录结构是train和val两个子目录每个子目录下再按类别建文件夹。解压这份数据集后初始状态是一个一个的类别文件夹需要先手动整理成下面的形式crop_pest_cls/ ├── train/ │ ├── Cashew_anthracnose/ │ ├── Cashew_gumosis/ │ ├── Cashew_healthy/ │ ├── ... 其余类别 │ └── Tomato_verticulium_wilt/ └── val/ ├── Cashew_anthracnose/ ├── Cashew_gumosis/ ├── ... 其余类别 └── Tomato_verticulium_wilt/YOLO11cls 的训练入口yolo classify train在接收data参数时指向的是上面这个crop_pest_cls父目录脚本会自动识别父目录下的train和val子目录不需要额外写数据配置文件。这一点和 YOLOv5 分类任务的做法一致和检测任务的 YAML 配置方式有区别。如果你没有做验证集划分直接拿全部 22 个类别文件夹当训练数据也能跑但训练时模型会把一部分数据随机留作验证这样你没法精确控制验证集的比例。更规范的做法是自己做一次划分把每个类别图片总数的 15% 到 20% 抽出来做验证集。下面这个脚本可以直接解决划分问题。3.2 用脚本做 train/val 划分按类别比例取样而不是固定数量这里的关键是按比例而不是按固定数量。假设某个类别只有 20 张图固定抽 5 张做验证就抽走了 25%训练只剩 15 张类别会严重缩水。按比例抽样能保证每个类别保底有 80% 进入训练集。import os import random import shutil src_root ./crop_pest_src # 解压后的类别文件夹所在目录 dst_root ./crop_pest_cls # 目标目录脚本会自动创建 train/val val_ratio 0.15 # 验证集比例新手建议先 0.15 random.seed(42) for class_name in os.listdir(src_root): class_path os.path.join(src_root, class_name) if not os.path.isdir(class_path): continue images [f for f in os.listdir(class_path) if f.lower().endswith((.jpg, .jpeg, .png))] random.shuffle(images) val_count int(len(images) * val_ratio) val_images images[:val_count] train_images images[val_count:] for split, split_images in [(train, train_images), (val, val_images)]: dst_class_dir os.path.join(dst_root, split, class_name) os.makedirs(dst_class_dir, exist_okTrue) for img in split_images: shutil.copy2( os.path.join(class_path, img), os.path.join(dst_class_dir, img) ) print(f{class_name}: total{len(images)}, ftrain{len(train_images)}, val{len(val_images)})这个脚本的逻辑分三步先遍历源目录下每个类别文件夹用random.shuffle打乱图片顺序然后按val_ratio计算验证集数量最后用shutil.copy2复制到目标目录的 train 或 val 对应类别下。random.seed(42)固定随机种子保证每次运行划分结果一致方便复现。几个参数按实际需求改val_ratio可以调成 0.2如果类别总图片数偏少就别超过 0.2src_root是数据集解压后的路径注意不要和dst_root设成同一个目录否则复制到自己里面会出问题。用copy2是保留原始文件不改动如果你磁盘吃紧改成shutil.move可以省一半空间。3.3 训练前看一眼类别分布少数类怎么处理划分完之后做一次分布检查。前面find命令拿到的数据配合 Excel 或 Python 画个柱状图一眼就能看出有没有类别严重不足。常见问题是某个病害类别在真实采集时本身就少比如早期病害症状不明显采集人员容易漏掉。遇到少数类我一般按优先级做三件事第一检查是不是划分脚本出了问题导致某些类别没进训练集第二对少数类做针对性增强比如水平翻转、随机旋转、色彩抖动第三调整 YOLO11cls 的类别权重。如果你发现某个类别只有十几张图靠增强硬训是撑不起来的这种类别在标注时就应该多采集数据层面的问题靠算法兜底始终是权宜之计。分布检查也可以直接在训练前用 Ultralytics 的库来验证目录结构是否合法from ultralytics import YOLO model YOLO(yolo11cls.pt) # 用 model.val 前先检查数据是否能被正确解析 results model.val(data./crop_pest_cls, splitval)正常情况会输出 Validation 的指标汇总。如果这一步报错说明目录结构有问题比如 train 或 val 下缺了类别文件夹、图片格式不被支持等。把这一步当成训练前的冒烟测试能省掉后面白跑一轮的时间。4. 一键训练脚本实战YOLO11cls 训练参数与日志解读4.1 一键脚本做了什么从数据校验到训练完成的完整链路这份资源附带的 YOLO11cls 一键训练脚本核心是把校验目录结构、启动训练、保存权重、输出日志串成一条命令。典型实现如下#!/bin/bash # 一键训练脚本 train_cls.sh DATA_DIR./crop_pest_cls EPOCHS100 IMGSZ640 BATCH16 DEVICE0 # 检查数据目录结构是否完整 if [ ! -d $DATA_DIR/train ] || [ ! -d $DATA_DIR/val ]; then echo [ERROR] data dir must contain train/ and val/ subdirectories exit 1 fi # 启动 YOLO11cls 分类训练 yolo classify train \ data$DATA_DIR \ modelyolo11cls.pt \ epochs$EPOCHS \ imgsz$IMGSZ \ batch$BATCH \ device$DEVICE \ patience20 \ project./runs \ namecls_crop_pest脚本首先用if [ ! -d ... ]检查 train 和 val 目录是否存在缺了就报错退出。然后通过yolo classify train启动训练modelyolo11cls.pt表示加载 YOLO11 分类预训练权重做迁移学习patience20是早停参数验证集准确率连续 20 轮不提升就自动终止训练project和name指定输出目录训练日志、权重文件都会落在./runs/cls_crop_pest下。这个脚本的价值在可复现。博主训练日志里记录的实验环境、参数组合都对应这条命令你拿同一份数据跑同一个参数得到的结果理论上应该接近。实际会有硬件层面的小浮动比如显卡不同导致 batch 大小变化但幅度不会太大。4.2 关键超参数怎么改imgsz、batch、epochs、patience 的取舍参数不能照搬得按你自己的显存和任务调整。先说imgsz。YOLO11cls 默认用 640但对于分类任务224 或 256 通常已经足够因为分类不需要检测那么高的分辨率来定位小目标。imgsz 减半训练速度大概是原来的两倍显存占用也明显下降。如果图片里的病斑很小比如早期炭疽病只有几个斑点那就保留 640分辨率低了会丢失纹理细节。batch受显存约束。12GB 显存跑 yolo11cls 的 n 版本batch 16 到 32 都可以如果你用 s 或 m 版本batch 8 就要小心显存溢出。显存不够时报错一般是CUDA out of memory这时把 batch 降到 8 或 4同时配合梯度累积也就是 Ultralytics 里的accumulate参数可以在不大幅降低训练速度的前提下维持稳定的收敛。epochs从 100 起步。小数据集上 YOLO11cls 通常在 30 到 50 轮之间就收敛了100 轮配patience20是稳妥组合。如果 50 轮后验证准确率还在缓慢爬升说明数据多样性比预期高可以加到 150 轮如果 20 轮就到了平台期说明模型已经吃饱了早停会自动结束训练不用手动干预。这里有一个容易踩的误区patience设太大训练时间被无效拉长设太小比如 5模型可能因为验证集随机波动被过早终止。我一般先设 15 到 20 跑一轮看训练曲线确认平台期的波动幅度再决定要不要收紧。4.3 训练日志怎么读top1_acc、top5_acc、P/R 的含义与参照训练过程中的终端输出每隔一个verbose周期打印一行指标博主提供的训练日志里这些字段都能看到。分类任务重点看三个指标top1_acc、top5_acc和loss(cls)。top1_acc是模型预测最可能的类别恰好正确的比例这是最终要交付的指标top5_acc是前五个预测中包含正确类别的比例在类别有相似性时这个指标很有参考价值。比如 Cassava mosaic 和 Cassava healthy如果健康叶片有轻微黄化模型可能把两者都排在前几位top5 高而 top1 一般说明模型学到了相关性但区分度不足。P精确率和R召回率在分类任务里是每个类别单独计算的YOLO11cls 会输出 macro 平均结果。对于病虫害识别我偏向看召回率漏报一个病株比误报一个健康株代价更大因为漏报意味着病害扩散。如果某个类别召回率明显低于其他类回到第 3 章的方式检查这个类别的样本数量和增广配置。日志里还有个容易忽略的GFLOPs字段表示模型单次推理的浮点运算量。它决定你的部署端是否扛得住。yolo11cls 的 n 版本 GFLOPs 很低适合边缘设备如果你的应用跑在服务器上用 s 版本拿更高精度更划算。5. 训练翻车避坑指南从数据路径到过拟合的 5 个高频问题5.1 报错 No labels found in dataset但数据明明放在那里现象运行一键训练脚本终端直接报类似No labels found in .../train的错误训练直接退出。原因YOLO11cls 分类模式解析的是父目录下的train和val子目录不是train下再套一层。如果你把解压后的类别文件夹直接命名为train里面放着 22 个类别文件夹这本身没问题但如果你把图片直接平铺在train下没有按类别建子目录YOLO 会把每张图当成一个独立的类数据路径就乱了。另外路径里带中文或空格也会触发类似报错。解决严格按照第 3 章的目录结构组织数据每一级目录用纯英文命名。检查crop_pest_cls/train/Cashew_anthracnose/下确实有图片文件而不是嵌套了一层文件夹。图片套图片的结构用find . -name *.jpg -exec ls -la {} \;扫一遍就能发现。5.2 训练时 loss 下降但验证集准确率停滞在 60% 上下现象训练集 loss 一路下降top1_acc 到了 95%验证集却卡在 60% 左右两者差距越来越大。原因典型过拟合。1000 张图分到每类 40 多张模型很容易在训练集上背答案尤其是背景单一的图片。另一个常见诱因是验证集划分时没有做随机化同一次采集的图片在光照、角度上高度相似训练集和验证集之间存在数据泄漏。解决先把数据增强打开YOLO11cls 默认开了 hsv_h、hsv_s、hsv_v 和 fliplr你需要确认degrees、translate、scale这些参数没有被设成 0。给训练命令加degrees10 scale0.3 hsv_h0.015 hsv_s0.7 hsv_v0.4这组常见配置能明显提升泛化。同时检查第 3 章划分脚本里的random.seed确保每次运行顺序都打乱过。5.3 训练 Curve 显示 top1_acc 在第 30 轮突然跳水到 20%现象训练过程平稳到某一轮 top1_acc 从 80% 级别直接掉到 20% 级别之后再也没恢复。原因大概率是学习率策略的问题。Ultralytics 默认用余弦退火调度器如果初始学习率lr0设得偏高比如 0.1退火到后期学习率过小模型从局部最优跳出后找不到新最优点。也遇到过验证集里混入了全黑或全白的坏图导致这一轮指标异常。解决把lr0从默认值调低到 0.001 到 0.01 区间配合warmup_epochs5。另外用find . -name *.jpg -size -5k找出小于 5KB 的图片这类文件大概率是损坏或纯色图直接删掉。我用一个数据清洗步骤把所有异常的图片先剔除再进训练流程基本能避开这个坑。5.4 训练完成后导出模型推理结果和训练时差距很大现象训练日志里 top1_acc 85%用yolo predict跑单张图片时预测类别和肉眼判断经常不一致。原因训练时模型会做随机缩放、裁剪和翻转如果推理时没有做同样的预处理尤其是imgsz不一致输出会有偏差。还有一个隐蔽原因训练图里有大量带水印或框线标注的图片模型把水印学成了判别特征推理时遇到干净图片就翻车。解决训练和推理统一用同一个imgsz导出模型时也传入相同的尺寸。对于水印问题回到数据层面检查图片内容把带明显标注痕迹的图片剔除或裁掉标注区域。这个现象说明模型泛化能力被脏数据干扰不是参数问题。5.5 叶斑病和早疫病混淆严重健康叶片被误判为病害现象混淆矩阵里 Maize_leaf_spot 和 Maize_leaf_blight 互相误判率高甚至 Cashew_healthy 被频繁判成 Cashew_anthracnose。原因病害初期的叶片症状本就相似叶斑病和叶枯病在视觉上都是叶片褐变区别在病斑形状和分布。150 张图以内的类别想让模型学到这种细节差异难度很大。健康叶片被误判往往是病害早期症状不明显模型学到的是叶片颜色偏黄就算病而不是真正的病斑特征。解决这类问题要从数据侧解决。如果你有原始采集图片优先补充歧义类别的样本。如果数据集已经固定就靠类别权重Ultralytics 支持class_weights参数给易混淆类别更高的损失权重。我一般先跑混淆矩阵确定哪两类最容易混再针对这两类做额外的色彩增强比如把色调扰动加大强迫模型关注更稳定的纹理特征。6. 训练完别急着部署混淆矩阵、batch 验证与 ONNX 导出训练结束不等于项目做完。YOLO11cls 训练过程中会生成confusion_matrix.png和results.png先看混淆矩阵。矩阵里对角线越亮越好非对角线出现了高亮块说明特定两个类别在打架。前面 5.5 的案例就是靠混淆矩阵定位出来的。看矩阵的时候把每行加起来算一下被误判到哪一类最多这个就是后续补数据的优先级排序。验证环节我习惯跑一次完整的 batch 推理用真实图片而不是测试集图片看模型的预测概率分布。命令是yolo classify predict \ model./runs/cls_crop_pest/weights/best.pt \ source./real_samples \ imgsz640 \ save_txtTrue注意save_txtTrue它会把每个预测结果按类别 置信度的格式写入 txt 文件。批量检查这个文件如果大部分置信度集中在 0.5 到 0.7 之间说明模型对自己不自信部署时就要在业务逻辑里加置信度阈值低于阈值的样本进入人工复核。部署前导出 ONNX 是 Ultralytics 的常规操作一条命令yolo classify export \ model./runs/cls_crop_pest/weights/best.pt \ formatonnx \ imgsz640到这里要提醒一句导出 ONNX 后用onnxruntime做推理时输入预处理要和训练保持一致包括归一化、通道顺序和 resize 方式。这个细节翻车率极高我见过好几个项目在 Python 里精度正常换到 C 部署就掉点最后定位到是 resize 的插值算法从双线性变成了最近邻。我自己养成了一个习惯数据到手先跑分布统计训练前固定随机种子训练中盯 confusion_matrix 而不是只看 top1_acc部署前拿真实场景图片做一轮 batch 验证。这套流程走完模型能不能上线心里有数。从那以后我每次做分类项目都强制走一遍这三步省掉的全是返工的时间。这份数据集配套的脚本和日志刚好能帮你把整套流程跑通一次希望帮到你。本文还有配套的精品资源点击获取
