
简介面向水稻种植智能化与农业视觉应用开发者的水稻叶病虫害分类数据集共5000张真实场景高清叶片图像覆盖细菌性叶枯病、褐斑病、叶瘟病、稻飞虱等常见病虫害及健康叶片。数据按类别分文件夹整理标注质量较高可直接用于YOLO11cls等图像分类任务训练也可作为通用分类数据集的补充。资源包为PDF格式1个文件2.46MB内附数据集基本情况、缩略图以及百度网盘获取方式适合需要完整数据集的算法工程师、科研人员及农业AI学习者。此外附赠YOLO11cls一键训练脚本与博主训练结果日志可快速启动训练并对照参考。目前已有114人学习是开展水稻病害识别模型验证与调参的实用资源。1. 先让5000张图说话再谈YOLO11cls一键训练单看“目标分类-水稻叶病虫害分类数据集-5000张图对应分类文件夹整理YOLO11cls一键训练脚本”这个标题容易误以为重点是“训练脚本”但实际项目里最先卡壳的往往是数据那一半。5000张水稻叶病虫害图不算大真正麻烦的是类别分布不均、文件夹命名不统一、偶发坏图以及不清楚YOLO11cls到底要什么格式。分类任务和检测任务对数据集的要求完全不同后者需要逐框标注前者只要“文件夹名字等于类别名”。这篇会从数据集整理讲起把目录结构、校验脚本、训练脚本、参数设置、过拟合排查和推理导出一路串完适合从零做农业图像分类、或想把手头杂图整理成YOLO11cls可训练工程的人。2. 水稻叶病虫害分类数据集的整理核心是把目录做成交叉验证能识别的样子2.1 关键一步把“分类文件夹”整理成YOLO11cls需要的ImageFolder结构YOLO11cls是Ultralytics YOLO11系列里的分类任务形态它不读VOC或COCO的标注文件也不需要任何边框。它直接按ImageFolder规则读图也就是说文件夹的名字就是类别标签图片放对文件夹就等于标注完成。这一点和YOLO11检测任务的格式差别巨大很多人习惯性去找labels目录结果发现分类模型根本不需要。拿到5000张有“对应分类文件夹”的图时我一般会先看原始目录长什么样。常见的有三种情况一是已经按类别分好但train、val、test混在一起二是每类一个文件夹但图片命名带日期或相机编号三是类别文件夹里有子文件夹嵌套。无论哪种都要先统一到一个中间结构再做train/val切分。# 以类别为根的原始结构示例 # 原始路径假设是 ./rice_raw/稻瘟病/*.jpg # 目标结构./datasets/rice_cls/train/稻瘟病/*.jpg python3 - PY import os, glob, random, shutil random.seed(42) src_root ./rice_raw dst_root ./datasets/rice_cls # 建议预先查看每个类别的图片数量 for cls_dir in sorted(glob.glob(os.path.join(src_root, *))): if os.path.isdir(cls_dir): imgs glob.glob(os.path.join(cls_dir, *.jpg)) \ glob.glob(os.path.join(cls_dir, *.JPG)) \ glob.glob(os.path.join(cls_dir, *.png)) print(f{os.path.basename(cls_dir)}: {len(imgs)} 张) PY这段代码的作用是列出每个类别目录下的图片数量先看类别分布再决定怎么切。按常见做法train、val、test按7:2:1或8:1:1切分。5000张图规模偏小建议test可以单独留10%val留20%剩下的进train。切分时要保证每个类别在三个集合里都有样本否则验证阶段某个类完全没出现过会直接造成accuracy指标偏乐观或偏误差。# 继续在同一脚本中执行切分类别名用目录名 classes [os.path.basename(p) for p in sorted(glob.glob(os.path.join(src_root, *))) if os.path.isdir(p)] for cls_name in classes: src_dir os.path.join(src_root, cls_name) imgs glob.glob(os.path.join(src_dir, *.jpg)) \ glob.glob(os.path.join(src_dir, *.JPG)) \ glob.glob(os.path.join(src_dir, *.png)) random.shuffle(imgs) n_test int(len(imgs) * 0.1) n_val int(len(imgs) * 0.2) test_imgs imgs[:n_test] val_imgs imgs[n_test:n_test n_val] train_imgs imgs[n_test n_val:] for split_name, split_imgs in [(train, train_imgs), (val, val_imgs), (test, test_imgs)]: out_dir os.path.join(dst_root, split_name, cls_name) os.makedirs(out_dir, exist_okTrue) for p in split_imgs: shutil.copy(p, os.path.join(out_dir, os.path.basename(p))) print(切分完成:, dst_root)这段切分脚本的关键有三点固定random.seed保证可复现用glob同时匹配.jpg/.JPG/.png避免大小写漏图逐类别切分避免全量随机后某类在test中缺失。复制而非移动原图保留一份原始材料以防切分后想调整比例。2.2 YOLO11cls和YOLO11检测在数据标注上的本质区别常见误区是以为YOLO11所有任务都要配txt标注。实际项目里YOLO11检测需要每张图对应一个同名txt文件每行是“类别id x_center y_center width height”而YOLO11cls只要文件夹结构对。标题里写的“分类文件夹整理”正是cls任务的核心标注动作。对比项YOLO11检测YOLO11cls分类标注文件每图一个txt坐标归一化不需要标注文件类别信息classes.txt或yaml中的names文件夹名即类别名多目标支持支持一图多框不定位整图一个类别数据量要求通常每类500张起步每类100张可以跑通baseline数据增强依赖增强但坐标会联动可以放心做翻转旋转做目标分类时YOLO11cls的yaml配置比检测简单很多。常见做法是只写path和namestrain和val可以省略路径让Ultralytics自动推断。# rice_cls.yaml - YOLO11cls 数据配置 path: ./datasets/rice_cls train: train val: val test: test names: 0: 稻瘟病 1: 白叶枯病 2: 稻曲病 3: 健康叶这个yaml最实用的参数是path建议写成相对路径或绝对路径都行但相对路径会跟随当前工作目录变化跑训练脚本前用cd进入工程根目录最省心。names顺序必须与文件夹名的字母排序一致这个坑常见于中文类别名Ultralytics内部会按文件夹名的排序索引类别。2.3 5000张图规模下的校验与类别均衡建议分类文件夹整理完之后不要急着训练。先做三步校验坏图检查、尺寸分布统计、类别样本数确认。坏图经常来自手机拍摄后传输中断或爬图时产生的0字节文件深度学习框架读到一半会报解码错误。# 用PIL快速校验所有图能否被解码 python3 - PY import os from PIL import Image bad_files [] total 0 for root, dirs, files in os.walk(./datasets/rice_cls): for fn in files: if fn.lower().endswith((.jpg, .jpeg, .png)): total 1 fp os.path.join(root, fn) try: img Image.open(fp) img.verify() except Exception as e: bad_files.append((fp, str(e))) print(扫描图片总数:, total) print(坏图数量:, len(bad_files)) for fp, err in bad_files[:20]: print(fp, err) PY这里用verify()而不是直接load()因为verify只做文件结构完整性校验速度更快。5000张图的扫描通常在几秒内完成。坏图直接删除即可不用修复。对类别均衡来说5000张图均分到4个类就是每类1250张但真实数据往往存在长尾。若某个类不足200张训练时建议给该类一个稍高的采样权重或者用数据增强临时扩类。对于YOLO11cls常见且可靠的增强手段是hsv_h、hsv_s、hsv_v。对水稻叶病虫害这类颜色敏感任务hsv增强参数不建议调太大稻瘟病和健康叶的区分点往往就在叶色、病斑颜色上过度调色会让模型学到错误的颜色映射。3. 用YOLO11cls一键训练脚本跑通本地最小闭环3.1 一键训练脚本的必备组成其实只有三块所谓一键训练脚本本质上就是“环境检查 数据完整性校验 启动训练”。真正训练那行命令Ultralytics已经封装好了脚本的价值在于把前面容易出错的部分钉死。常见做法是把脚本写成bash让团队成员无需了解Python也能直接跑。#!/bin/bash # train_rice_cls.sh - YOLO11cls 训练入口 set -e cd $(dirname $0) # 1. 检查Python环境 python3 -c import ultralytics; print(ultralytics, ultralytics.__version__) || { echo [错误] 缺少 ultralytics执行: pip install ultralytics exit 1 } # 2. 检查数据集目录 if [ ! -d datasets/rice_cls/train ]; then echo [错误] 数据集目录缺失 exit 1 fi # 3. 启动训练参数集中在这里 python3 - PY from ultralytics import YOLO model YOLO(yolo11s-cls.pt) model.train( datarice_cls.yaml, epochs50, imgsz224, batch32, device0, workers4, seed42, lr00.01, augmentTrue, projectruns/rice_cls, nameexp1, patience10 ) PYset -e保证脚本任何一步失败就立即退出不会带着残缺数据集往下跑。cd $(dirname $0)让脚本可以从任意路径启动这是多人协作时最省事的写法。训练参数里epochs50适合5000张图的中小数据集imgsz224是分类任务的默认有效值既不损失叶片纹理特征又比imgsz640快一倍以上。batch32常见于8GB显存如果显存更大可以调到64精度提升不明显但训练更稳。device0指定第一张显卡CPU机器改成devicecpu。lr00.01是分类任务常见的初始学习率数据集小时用0.005更稳。patience10表示10个epoch没有改善就提前停止能避免无效消耗算力。3.2 YOLO11cls模型权重选择s还是n还是mYOLO11cls提供n、s、m、l、x五个尺度体现在文件名上是yolo11n-cls.pt、yolo11s-cls.pt这样。5000张图属于小型数据集用l或x这类大模型几乎必然过拟合训练时间还长。我一般建议先用s起步如果精度不够再切m而n作为快速验证用。原因是s在224分辨率下对叶片病斑这类细粒度特征已经具备足够的表征能力而n的参数量更小在类别间外观差异较小时容易欠拟合。# 快速对比不同尺度模型的参数量与推理速度 from ultralytics import YOLO for size in [n, s]: model YOLO(fyolo11{size}-cls.pt) results model.predict(datasets/rice_cls/val/稻瘟病/IMG_0001.jpg, imgsz224) print(fyolo11{size}-cls top1: {results[0].probs.top1})第一次运行上面这段代码ultralytics会自动下载对应权重。常见做法是提前单独下载或让脚本首次运行联网拉取离线环境需要手动拷贝.pt文件到工程目录。3.3 训练过程中会产生的关键文件看懂它们才算真跑通训练启动后不要只盯着进度条。runs/rice_cls/exp1/目录下会持续生成results.csv、weights/best.pt和weights/last.pt。results.csv里按epoch记录train loss、val loss、top1 accuracy、top5 accuracy等关键指标。检查训练是否正常时我一般直接看summary。# 查看训练结果摘要 cat runs/rice_cls/exp1/results.csv | column -t -s, | head -5一个正常收敛的训练过程val loss在前20个epoch应该持续下降top1 accuracy逐步上升。如果在第5个epoch左右val loss就开始反弹而train loss还在降说明过拟合已经出现这时应该停止训练而不是等epochs跑满。4. 训练曲线的读法、过拟合处理和YOLO11cls常见报错排查4.1 从results.csv里判断水稻叶病虫害分类是否收敛训练过程里最容易误判的是“train loss越低越好”。实际上train loss降到接近0但val loss抬升是典型的过拟合信号说明模型把训练集的背景、光照等环境噪声也学会了。对叶片病虫害图来说同一病害在不同光照、不同拍摄角度下外观差异很大模型如果只看训练集的颜色分布验证时换个光线就会掉点。判断收敛的正确方式是每隔5个epoch对比train loss和val loss的差距。差距小于15%说明泛化正常差距持续扩大就要立刻动用增强或早停。patience10已经是常用的早停阈值如果想要更保守就用15。# 读取results.csv并绘制loss曲线帮助决定是否早停 import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/rice_cls/exp1/results.csv) plt.plot(df[epoch], df[train/loss], labeltrain loss) plt.plot(df[epoch], df[val/loss], labelval loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.savefig(loss_curve.png, dpi150)上面的脚本用pandas读取Ultralytics写出的csv绘制两条loss曲线。train/loss和val/loss的具体列名可能因YOLO11版本不同稍有差别如果不匹配先打印列名print(df.columns)确认。绘图后如果val loss在第30个epoch后趋于水平或微弱上升说明已经收敛继续训练只会增加过拟合风险。4.2 过拟合的水稻叶数据集专用解法增强与类别权重两级调参数据集只有5000张时过拟合可以从两个层面解决。第一层是数据增强第二层是类别平衡。model.train( datarice_cls.yaml, epochs50, imgsz224, batch32, hsv_h0.01, hsv_s0.1, hsv_v0.1, degrees15, fliplr0.5, mosaic0.0, mixup0.0, )与检测不同的是分类任务不能开mosaic。原因是YOLO11cls的mosaic会把四张图拼接成一张类别标签变成四选一等于人为引入错误标注。水分充足时叶片纹理和病斑特征才是分类关键fliplr开0.5是安全的水平翻转不会改变叶片病害类别。degrees15只做小角度旋转因为水稻叶片有方向性超过30度的旋转会让模型看到大量现实中不存在的姿态。hsv三个参数都调小保留叶色的真实性。如果某个类别样本量明显偏少第二种做法是加权采样。Ultralytics支持在yaml里给类别配置权重但更简洁的做法是在训练前检查类别分布对不足200张的类别做离线增强。# 统计训练集每类图片数量 python3 - PY import os from collections import Counter cnt Counter() for root, dirs, files in os.walk(datasets/rice_cls/train): cls_name os.path.basename(root) if files: cnt[cls_name] len(files) for name, num in cnt.most_common(): print(f{name}: {num}张) PY统计结果出来后如果某个类别的图片数不足其他类别的30%建议重点考虑收集更多数据或者对该类别做亮度、对比度小幅调整后另存副本。对分类任务来说复制粘贴生成完全相同的图片没有任何信息增益必须做增强后再入训练集否则只是延长训练时间。4.3 一键训练脚本最容易踩的三个报错第一个报错是AssertionError: train/val datasets not found。原因是yaml里train和val写成了绝对路径但脚本里cd到了别的目录。解决方法是统一用相对路径并确认datasets/rice_cls/train和datasets/rice_cls/val真实存在。第二个报错是RuntimeError: DataLoader worker (pid(s) XXXXX) exited unexpectedly。出现这个报错时一般不是代码问题而是系统资源不足或者图片格式异常。把workers4改成workers2同时确认数据集里没有超过10000×10000像素的超大图。水稻叶近拍图偶尔会有4000万像素原图训练前统一缩放过会稳定很多。# 批量压缩超大图片到最长边1600 import os from PIL import Image for root, dirs, files in os.walk(datasets/rice_cls): for fn in files: if fn.lower().endswith(.jpg): fp os.path.join(root, fn) img Image.open(fp).convert(RGB) w, h img.size if max(w, h) 1600: ratio 1600 / max(w, h) img img.resize((int(w * ratio), int(h * ratio)), Image.LANCZOS) img.save(fp, quality95, subsampling1) print(resized:, fp, (w, h), -, img.size)第三个报错是CUDA out of memory。5000张图、224分辨率、batch32通常只需要4GB左右显存如果爆显存多半是某个进程占用了显存没释放。先用nvidia-smi查看占用再按需把batch降到16或把workers降到2。批量减小后模型精度不会有明显变化只是训练速度变慢属于最稳的退路。5. 用训练好的YOLO11cls权重做批量推理与验证以及一个图像预处理技巧训练完成后best.pt就是可供实际使用的权重。验证它是否可用最直接的方式是跑一遍测试集。from ultralytics import YOLO model YOLO(runs/rice_cls/exp1/weights/best.pt) metrics model.val(datarice_cls.yaml, splittest) print(测试集 top1:, metrics.top1) print(测试集 top5:, metrics.top5) model.confusion_matrix跑验证时注意splittest必须显式声明Ultralytics默认验证集是val。测试集的重合度结果是判断模型能否上线的最终依据。如果top1在85%以上对于4类水稻叶病虫害分类已经可以用于日常筛查70%到85%之间则需要重新审视易混类别到底出现在哪里常见的是稻瘟病与褐斑病颜色接近导致误判。为了看清混淆出现在哪两类之间可以直接打印混淆矩阵或按类别输出分类报告from ultralytics.utils.metrics import ConfusionMatrix import torch results model.val(datarice_cls.yaml, splittest) cm ConfusionMatrix(model.model) cm.process(torch.tensor(results.pred_classes).cpu(), torch.tensor(results.true_classes).cpu()) print(cm.matrix)矩阵中非对角线的高值位置就是要重点观察的易混类。这类错误依靠调参很难根除合理手段是回到数据集层面把这两个类别中外观差异大的样本重新审视一遍看是否存在标注错误。最后提供一个预测阶段实用的图像预处理技巧。训练时如果用了imgsz224推理时用更大的图未必有正面收益因为模型已经在224分辨率下收敛。常见做法是保持相同的imgsz值完成整个链路。在线部署时需要每秒处理大量图片常见做法是导出为ONNX再跑而不是直接在Python里加载PyTorch模型。# 导出为ONNX供C或推理服务器使用 yolo classify export modelruns/rice_cls/exp1/weights/best.pt formatonnx imgsz224导出后的best.onnx可以直接用ONNX Runtime加载推理速度比原始PyTorch权重提升明显。如果导出时报错缺少onnx包执行pip install onnx onnxruntime即可。优先选择onnx而不是openvino的原因是可以保持跨平台可部署能力。后续每次采集新数据后把新图按相同规范并入datasets/rice_cls并重跑一遍训练脚本复制到相应类别的文件夹里即可校验与训练流程不需要做任何改动。本文还有配套的精品资源点击获取