害分類數(shù)據(jù)集與YOLO11cls圖像分類實(shí)戰(zhàn):從數(shù)據(jù)體檢到訓(xùn)練調(diào)優(yōu))
簡(jiǎn)介水稻葉病蟲(chóng)害分類數(shù)據(jù)集資源包以PDF文檔形式交付主要面向農(nóng)業(yè)圖像分類與YOLO11cls算法訓(xùn)練場(chǎng)景適合需要真實(shí)場(chǎng)景數(shù)據(jù)支撐的開(kāi)發(fā)者或農(nóng)業(yè)AI研究者使用。內(nèi)容涵蓋15000張水稻葉片圖像覆蓋細(xì)菌性葉枯病、褐斑病、健康葉片、葉瘟病、葉鞘腐病、穗頸瘟、稻飛虱、紋枯病等10個(gè)類別每個(gè)類別均有獨(dú)立文件夾標(biāo)注結(jié)構(gòu)規(guī)范可直接用于YOLO分類流程訓(xùn)練。由于原始圖片體量較大資源包以1個(gè)PDF文件交付大小2.32MB文檔內(nèi)附數(shù)據(jù)集詳細(xì)介紹、類別說(shuō)明、目錄組織方式及網(wǎng)盤獲取鏈接方便按需下載原始圖片。已有318人學(xué)習(xí)瀏覽除分類數(shù)據(jù)外還附贈(zèng)YOLO11cls一鍵訓(xùn)練腳本及博主訓(xùn)練結(jié)果日志可作為基準(zhǔn)結(jié)果參考幫助快速上手訓(xùn)練、驗(yàn)證模型效果節(jié)省數(shù)據(jù)整理與環(huán)境配置時(shí)間。1. 水稻葉病蟲(chóng)害分類數(shù)據(jù)集 YOLO11cls為什么我把這事押在“圖像分類”而不是“檢測(cè)”上下午接到需求給植保無(wú)人機(jī)做水稻葉病蟲(chóng)害識(shí)別手上只有一批整理好的照片沒(méi)有逐張畫(huà)框的標(biāo)注。如果硬上檢測(cè)模型光是目標(biāo)框標(biāo)注就能拖垮整個(gè)排期。水稻葉病蟲(chóng)害分類數(shù)據(jù)集的正確打開(kāi)方式是先把“這片葉子有沒(méi)有病、是什么病”用圖像分類解決15000張圖按類別文件夾歸好再配一套 YOLO11cls 一鍵訓(xùn)練腳本當(dāng)天就能出一個(gè)可復(fù)現(xiàn)的基線模型。這套方案適合三類人做農(nóng)學(xué)畢設(shè)的學(xué)生、給植保團(tuán)隊(duì)做 POC 的算法工程師、以及手里有大量無(wú)標(biāo)注田間照片但不想花錢標(biāo)框的從業(yè)者。分類任務(wù)不追求“病斑在第幾片葉”只輸出整體概率分布對(duì)巡田拍照的場(chǎng)景反而是更穩(wěn)的切入點(diǎn)。2. 水稻葉病蟲(chóng)害數(shù)據(jù)集先做“體檢”再談?dòng)?xùn)練15000張圖不是越多越好拿到一份“整理好”的數(shù)據(jù)集第一件要做的事不是立刻訓(xùn)練而是把類目結(jié)構(gòu)、數(shù)量分布、圖片質(zhì)量全部過(guò)一遍。絕大多數(shù)翻車現(xiàn)場(chǎng)都發(fā)生在跳過(guò)這一步的時(shí)候訓(xùn)練跑到一半發(fā)現(xiàn)某個(gè)類全是模糊圖或者驗(yàn)證集和訓(xùn)練集有重復(fù)圖片準(zhǔn)確率虛高得離譜。2.1 類目文件夾該怎么排train/val 劃分的常見(jiàn)做法數(shù)據(jù)集既然已經(jīng)按“對(duì)應(yīng)分類文件夾整理”那我一般不會(huì)再去動(dòng)它的原始目錄而是另建一個(gè)干凈的數(shù)據(jù)根目錄用軟鏈接或復(fù)制腳本把原始圖片按 8:1:1 拆成訓(xùn)練、驗(yàn)證、測(cè)試三份。拆分的單位是“類”不是“圖片”否則某類圖片會(huì)隨機(jī)漏進(jìn)驗(yàn)證集導(dǎo)致訓(xùn)練時(shí)少學(xué)了這類特征。常見(jiàn)的水稻葉病蟲(chóng)害類目不會(huì)太細(xì)以稻瘟病葉瘟、稻白葉枯病、胡麻葉斑病、細(xì)菌性條斑病、稻曲病、健康葉為主。類目太少模型學(xué)不到區(qū)分度類目太多單類樣本不夠分15000 張圖對(duì)應(yīng) 5 到 10 個(gè)類是相對(duì)舒服的區(qū)間。目錄結(jié)構(gòu)我一般這樣排data/ricecls/ ├── train/ │ ├── rice_blast/ # 稻瘟病葉瘟 │ ├── bacterial_blight/ # 稻白葉枯病 │ ├── brown_spot/ # 胡麻葉斑病 │ ├── bacterial_stripe/ # 細(xì)菌性條斑病 │ ├── rice_kernel_smut/ # 稻曲病 │ └── healthy/ # 健康葉 ├── val/ │ └── ...與 train 同名子目錄 └── test/ └── ...與 train 同名子目錄這個(gè)結(jié)構(gòu)就是 ImageNet 風(fēng)格YOLO11cls 原生支持不需要額外寫(xiě) label 文件。很多從 YOLOv5、YOLOv8 遷移過(guò)來(lái)的同學(xué)會(huì)習(xí)慣性地先寫(xiě) data.yaml實(shí)際上分類任務(wù)根本不需要 yaml類名直接從子目錄名讀取。網(wǎng)上搜“yolov8 訓(xùn)練自己的數(shù)據(jù)集”時(shí)絕大多數(shù)教程講的是檢測(cè)任務(wù)檢測(cè)才需要 yaml 標(biāo)注框路徑分類鏈路完全不同這個(gè)區(qū)別先記住。劃分腳本可以這樣寫(xiě)按類分層抽樣保證每個(gè)類在三份子集中的比例一致import random import shutil from pathlib import Path random.seed(42) src_root Path(原始分類文件夾) # 已經(jīng)按類歸好的圖 dst_root Path(data/ricecls) ratios {train: 0.8, val: 0.1, test: 0.1} for cls_dir in src_root.iterdir(): if not cls_dir.is_dir(): continue imgs list(cls_dir.glob(*.jpg)) list(cls_dir.glob(*.png)) random.shuffle(imgs) n len(imgs) # 按比例切成三段 n_train int(n * ratios[train]) n_val int(n * ratios[val]) splits imgs[:n_train], imgs[n_train:n_trainn_val], imgs[n_trainn_val:] for split_name, split_imgs in zip(ratios.keys(), splits): out_dir dst_root / split_name / cls_dir.name out_dir.mkdir(parentsTrue, exist_okTrue) for img_path in split_imgs: # 復(fù)制而不是移動(dòng)原始數(shù)據(jù)始終留一份后悔藥 shutil.copy2(img_path, out_dir / img_path.name) print(f{cls_dir.name}: {split_name} - {len(split_imgs)})這段腳本的精髓在shutil.copy2復(fù)制而不是移動(dòng)源數(shù)據(jù)保留劃分錯(cuò)了還有后悔藥。random.seed(42)固定隨機(jī)種子保證每次執(zhí)行劃分結(jié)果一致模型對(duì)比時(shí)不會(huì)因?yàn)閿?shù)據(jù)劃分不同而說(shuō)不清是誰(shuí)的功勞。另外我在 glob 時(shí)同時(shí)接了 jpg 和 png但沒(méi)處理大寫(xiě)后綴如果原始文件夾里有.JPGglob 會(huì)漏掉建議在腳本里加上img_path.suffix.lower()的判斷把后綴統(tǒng)一轉(zhuǎn)小寫(xiě)再做匹配。2.2 數(shù)據(jù)體檢腳本查數(shù)量、查損壞、查模糊、查重復(fù)劃分完成之后接下來(lái)的體檢項(xiàng)目是四件事每個(gè)類到底有多少?gòu)垐D、有沒(méi)有打不開(kāi)的損壞文件、有沒(méi)有低分辨率或模糊到無(wú)法辨認(rèn)的圖、訓(xùn)練集和驗(yàn)證集之間有沒(méi)有重復(fù)圖。最后一項(xiàng)很多人忽略但重復(fù)圖混進(jìn)驗(yàn)證集造成的準(zhǔn)確率虛高是最典型的“自己騙自己”。下面是一段更直白的體檢腳本貼在訓(xùn)練之前跑一遍from PIL import Image from pathlib import Path import numpy as np from collections import defaultdict root Path(data/ricecls) stats defaultdict(lambda: {count: 0, broken: 0, blurry: 0, small: 0}) for split in [train, val, test]: for cls_dir in (root / split).iterdir(): if not cls_dir.is_dir(): continue for img_path in cls_dir.glob(*.*): key f{split}/{cls_dir.name} stats[key][count] 1 try: img Image.open(img_path) img.verify() # 只檢查文件完整性不加載全部像素 w, h Image.open(img_path).size except Exception: stats[key][broken] 1 continue if min(w, h) 224: # 低于 YOLO11 默認(rèn)輸入尺寸 stats[key][small] 1 # 用 Laplacian 方差判斷模糊度低于閾值視為模糊 gray np.array(Image.open(img_path).convert(L).resize((224, 224))) lap np.abs(np.diff(gray.astype(np.float32), axis0)) \ np.abs(np.diff(gray.astype(np.float32), axis1)) blur_score float(np.mean(lap)) if blur_score 20: stats[key][blurry] 1 for k, v in sorted(stats.items()): print(f{k}: count{v[count]} broken{v[broken]} small{v[small]} blurry{v[blurry]})這里要說(shuō)明幾個(gè)細(xì)節(jié)。img.verify()只讀文件頭不會(huì)把整張圖加載進(jìn)內(nèi)存體檢 15000 張圖也就幾十秒的事。模糊度的計(jì)算沒(méi)有用 OpenCV 的 Laplacian 算子而是直接對(duì)灰度圖做差分效果等價(jià)但少一次依賴安裝閾值 20 是我憑經(jīng)驗(yàn)拍的值如果原始照片本身偏柔光這個(gè)閾值要往下調(diào)到 10 附近否則會(huì)誤殺大量正常圖。判斷完體檢結(jié)果后我會(huì)把 blurry 和 broken 的文件單獨(dú)移到一個(gè)quarantine/目錄不刪除等人工確認(rèn)后再清理。除了這些我還會(huì)順手統(tǒng)計(jì)每個(gè)類的平均尺寸和寬高比。如果數(shù)據(jù)集中有大量寬高比超過(guò) 2:1 的橫幅照片而訓(xùn)練時(shí)用的是正方形輸入YOLO11cls 默認(rèn)的 resize 會(huì)把長(zhǎng)邊壓扁葉片紋理細(xì)節(jié)直接丟失。對(duì)這種圖我一般先做個(gè)中心裁剪或按長(zhǎng)邊補(bǔ)齊而不是直接丟給模型。2.3 類別不均衡怎么處理先別急著上采樣體檢報(bào)告出來(lái)后最常見(jiàn)的壞消息是某個(gè)病類別只有 60 張圖而健康葉有 6000 張。第一反應(yīng)是過(guò)采樣復(fù)制這能解決“數(shù)量”問(wèn)題但解決不了“多樣性”問(wèn)題——60 張圖復(fù)制 20 遍模型記住的是同一批葉子。我的順序是先合并語(yǔ)義相近的細(xì)分類比如把“稻瘟病急性型”和“稻瘟病慢性型”合并成“稻瘟病”看類目數(shù)是否維持在一個(gè)合理范圍。如果合并后仍然是長(zhǎng)尾分布再做離線數(shù)據(jù)增強(qiáng)旋轉(zhuǎn)、翻轉(zhuǎn)、亮度擾動(dòng)可以給少數(shù)類補(bǔ)充變化最后才是用 class_weight 或者干脆接受現(xiàn)實(shí)把少數(shù)類的任務(wù)目標(biāo)從“分類”降級(jí)為“異常檢測(cè)”只判有病沒(méi)病。公開(kāi)數(shù)據(jù)集如 PlantDoc 這類植物病害集可以拿來(lái)做預(yù)訓(xùn)練或補(bǔ)充樣本但要小心域差異PlantDoc 的葉片背景和拍攝角度跟無(wú)人機(jī)巡田照片差別很大直接混訓(xùn)會(huì)拖低真實(shí)場(chǎng)景的準(zhǔn)確率。用這些外部數(shù)據(jù)做先驗(yàn)、在自己的 15000 張圖上微調(diào)是更穩(wěn)的用法。3. YOLO11cls 選型與數(shù)據(jù)適配為什么選它目錄怎么接3.1 cls 分支和 det 分支的差異分類不是檢測(cè)的簡(jiǎn)化版YOLO 系列從 YOLOv8 開(kāi)始就同時(shí)提供檢測(cè)、分割、姿態(tài)、分類四條任務(wù)分支YOLO11cls 是延續(xù)這個(gè)設(shè)計(jì)的最新分類分支。很多人以為 cls 是 det 去掉了框訓(xùn)練會(huì)簡(jiǎn)單很多這個(gè)理解不準(zhǔn)確。檢測(cè)任務(wù)的優(yōu)化目標(biāo)是“框的位置 框內(nèi)類別”分類任務(wù)的優(yōu)化目標(biāo)是“整張圖屬于哪個(gè)類”前者要求模型關(guān)注局部區(qū)域后者要求模型理解全局紋理特征。水稻葉病蟲(chóng)害分類里稻瘟病和胡麻葉斑病在視覺(jué)上都是“葉片上有斑點(diǎn)”區(qū)別在于斑點(diǎn)的分布密度、邊緣形狀和顏色梯度這些特征需要模型在全局范圍內(nèi)做對(duì)比跟檢測(cè)模型在框內(nèi)做判別根本不是一回事。YOLO11cls 的優(yōu)勢(shì)在于它復(fù)用了一整套訓(xùn)練工程能力自動(dòng)混合精度、早停、學(xué)習(xí)率調(diào)度、結(jié)果可視化、ONNX/TFLite 導(dǎo)出這些從 YOLOv8 時(shí)代就驗(yàn)證過(guò)的能力讓 15000 張圖的訓(xùn)練變得非常省心。模型權(quán)重按體積分為 n/s/m/l/x 五檔水稻葉這種背景相對(duì)單一的圖像分類任務(wù)n 檔往往就夠先跑通再考慮換更大的模型。3.2 用腳本把任意圖片目錄接進(jìn) YOLO11clsYOLO11cls 讀取數(shù)據(jù)的邏輯是你把根目錄傳給它它自動(dòng)掃描根目錄下的子文件夾名稱作為類名然后在每個(gè)類文件夾里讀取圖片。也就是說(shuō)只要你把數(shù)據(jù)集整理成前文那種 train/val/test 結(jié)構(gòu)就能直接開(kāi)訓(xùn)不需要任何 label 文件。這一點(diǎn)和 YOLOv8 訓(xùn)練自己的數(shù)據(jù)集檢測(cè)時(shí)必寫(xiě) data.yaml 的流程完全不同最容易帶偏人。為了讓“任意圖片目錄”都能一鍵接入我會(huì)先跑一段目錄自檢腳本把不符合規(guī)范的子目錄在訓(xùn)練前暴露出來(lái)from pathlib import Path root Path(data/ricecls) for split in [train, val]: split_path root / split if not split_path.exists(): raise SystemExit(f缺少 {split} 目錄) for cls_path in split_path.iterdir(): if not cls_path.is_dir(): # 類目錄下混入了文件YOLO 會(huì)跳過(guò)它導(dǎo)致該類完全沒(méi)訓(xùn)練 print(f[警告] {split}/{cls_path.name} 不是文件夾) continue img_count sum(1 for p in cls_path.glob(*.*)) if img_count 0: print(f[警告] {split}/{cls_path.name} 是空目錄) elif img_count 50: print(f[注意] {split}/{cls_path.name} 只有 {img_count} 張容易欠擬合)這段腳本不做修復(fù)只做提醒因?yàn)樾迯?fù)邏輯改名、移動(dòng)、刪空目錄因數(shù)據(jù)而異強(qiáng)行自動(dòng)化反而可能把原始數(shù)據(jù)弄壞。跑完之后確認(rèn)類和目錄名沒(méi)有中文或特殊空格我一般統(tǒng)一換成小寫(xiě)英文加下劃線。類名會(huì)被 YOLO 寫(xiě)進(jìn)labels.txt作為輸出的可讀名稱中文類名在 Linux 上訓(xùn)練沒(méi)問(wèn)題但導(dǎo)出模型后在 Windows 工業(yè)機(jī)上做推理時(shí)控制臺(tái)編碼不統(tǒng)一容易輸出亂碼到時(shí)候排查半天才發(fā)現(xiàn)是編碼問(wèn)題。這個(gè)坑后面還會(huì)細(xì)說(shuō)。3.3 環(huán)境準(zhǔn)備一條命令裝完但版本要對(duì)齊YOLO11cls 的訓(xùn)練環(huán)境不復(fù)雜一條pip install ultralytics就能裝齊但有兩個(gè)前置條件容易忽略PyTorch 版本和 CUDA 版本要匹配且 Ultralytics 包版本不能太老。我的建議是新建一個(gè)干凈的 conda 環(huán)境Python 3.10 或 3.11 都行先安裝 PyTorch 再裝 Ultralytics順序別反。conda create -n ricecls python3.11 -y conda activate ricecls pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics python -c from ultralytics import YOLO; print(YOLO(yolo11n-cls.pt))最后一行如果能在屏幕上打印出模型結(jié)構(gòu)說(shuō)明安裝成功。首次運(yùn)行會(huì)聯(lián)網(wǎng)下載yolo11n-cls.pt預(yù)訓(xùn)練權(quán)重大概 5MB 左右如果公司內(nèi)網(wǎng)限制外網(wǎng)提前手動(dòng)下載放到當(dāng)前目錄就行。CPU 也能訓(xùn)練但 15000 張圖 224 分辨率下CPU 一個(gè) epoch 可能要跑十幾分鐘而一張普通消費(fèi)級(jí)顯卡只要 1 到 2 分鐘。沒(méi)有 GPU 的情況下先把 imgsz 降到 160、epochs 減到 30 試通流程比硬等一個(gè)完整訓(xùn)練要?jiǎng)澦愕枚唷?. YOLO11cls 一鍵訓(xùn)練腳本從命令行到 5 個(gè)必調(diào)參數(shù)4.1 腳本主干把數(shù)據(jù)集路徑、模型參數(shù)和訓(xùn)練配置串起來(lái)“一鍵訓(xùn)練腳本”的“一鍵”不是指跑一個(gè)黑盒命令而是指把數(shù)據(jù)路徑檢查、模型選擇、訓(xùn)練參數(shù)、結(jié)果輸出串成一條可重復(fù)執(zhí)行的流水線。我寫(xiě)的腳本長(zhǎng)這樣改動(dòng)最小、可讀性最高# train_rice_cls.py from ultralytics import YOLO from pathlib import Path def main(data_root./data/ricecls, model_sizen, epochs60, imgsz224, batch16): data_root Path(data_root) # 訓(xùn)練前先做存在性檢查避免訓(xùn)練到一半才發(fā)現(xiàn)路徑寫(xiě)錯(cuò) for split in [train, val]: if not (data_root / split).exists(): raise FileNotFoundError(f{data_root / split} 不存在請(qǐng)先完成第 2 章的數(shù)據(jù)劃分) # 按型號(hào)選預(yù)訓(xùn)練權(quán)重 weight_map {n: yolo11n-cls.pt, s: yolo11s-cls.pt, m: yolo11m-cls.pt} model YOLO(weight_map[model_size]) # 訓(xùn)練參數(shù)集中管理便于后面網(wǎng)格搜索 results model.train( datastr(data_root), epochsepochs, imgszimgsz, batchbatch, patience15, # 15 個(gè) epoch 沒(méi)有改善就早停 lr00.01, # 初始學(xué)習(xí)率SGD/AdamW 下語(yǔ)義不同 optimizerauto, # 讓框架自動(dòng)選優(yōu)化器 seed42, workers4, # Windows 下若報(bào)錯(cuò)改成 0 projectruns/ricecls, # 所有輸出集中到一個(gè)項(xiàng)目目錄 namefyolo11{model_size}-{imgsz}, exist_okTrue, # 重復(fù)跑同名實(shí)驗(yàn)時(shí)覆蓋不額外加后綴 ) if __name__ __main__: import argparse parser argparse.ArgumentParser() parser.add_argument(--data, default./data/ricecls) parser.add_argument(--model, defaultn, choices[n, s, m]) parser.add_argument(--epochs, typeint, default60) parser.add_argument(--imgsz, typeint, default224) parser.add_argument(--batch, typeint, default16) args parser.parse_args() main(args.data, args.model, args.epochs, args.imgsz, args.batch)這里每個(gè)參數(shù)背后都有取舍。patience15讓模型在驗(yàn)證集準(zhǔn)確率連續(xù) 15 個(gè) epoch 不漲時(shí)自動(dòng)停止避免最后一個(gè) epoch 從頭跑到尾的無(wú)效等待。exist_okTrue是最容易被忽略的Ultralytics 默認(rèn)會(huì)在重名實(shí)驗(yàn)名后面加_2后綴如果你用 crontab 或循環(huán)腳本自動(dòng)化跑實(shí)驗(yàn)積累的臨時(shí)目錄會(huì)越來(lái)越多顯存排查時(shí)根本分不清哪個(gè)是哪個(gè)。設(shè)為True后重復(fù)運(yùn)行會(huì)覆蓋同名目錄保持輸出整潔。4.2 5 個(gè)必調(diào)參數(shù)epochs、imgsz、batch、lr0、patience很多人拿到訓(xùn)練腳本第一反應(yīng)是把 epochs 拉到 300覺(jué)得練得越多越準(zhǔn)。這個(gè)思路在水稻葉病蟲(chóng)害分類任務(wù)上不成立。15000 張圖的規(guī)模60 到 80 個(gè) epoch 已經(jīng)足夠模型收斂再多就會(huì)開(kāi)始背訓(xùn)練集。我給一組參考值基于個(gè)人經(jīng)驗(yàn)適用于葉片特寫(xiě)占主體的數(shù)據(jù)參數(shù)推薦值范圍說(shuō)明epochs50 - 80配合早停使用看 val 曲線決定是否延長(zhǎng)imgsz224 起步可試 320224 是速度和精度的平衡點(diǎn)320 更穩(wěn)但顯存占用翻倍batch16 - 32小顯存從 8 起步n 模型 16 大約占用 6G 顯存lr00.01auto 優(yōu)化器下適用改用 AdamW 時(shí)降到 0.001patience10 - 20越大越耐心越小越早停建議 15imgsz的坑最隱蔽。很多人以為它只是輸入分辨率其實(shí)它還決定了訓(xùn)練時(shí)的隨機(jī)裁剪尺度。YOLO11cls 會(huì)把輸入圖隨機(jī)縮放后裁剪到imgsz如果原始圖片短邊只有 300 像素而你設(shè)了 640 的imgsz模型看到的是被強(qiáng)行放大的模糊圖特征反而學(xué)得更差。對(duì)于 15000 張圖的葉片數(shù)據(jù)224 夠用想提精度先加augmentTrue讓模型看更多變換而不是一味抬高分辨率。batch的設(shè)置不只受顯存影響還受類別均衡度影響如果你的數(shù)據(jù)集有少數(shù)類batch 太小會(huì)導(dǎo)致每個(gè) batch 里根本沒(méi)有少數(shù)類的樣本梯度更新方向完全被多數(shù)類主導(dǎo)這時(shí)候要把 batch 盡量調(diào)大讓每個(gè) batch 盡可能覆蓋更多類。4.3 訓(xùn)練完看什么結(jié)果文件的內(nèi)容與驗(yàn)證命令訓(xùn)練結(jié)束后腳本會(huì)在runs/ricecls/yolo11n-224/下生成一系列產(chǎn)物重點(diǎn)看四個(gè)東西weights/best.pt是驗(yàn)證集上表現(xiàn)最好的權(quán)重last.pt是最后一個(gè) epoch 的權(quán)重results.csv記錄了每個(gè) epoch 的指標(biāo)曲線confusion_matrix.png是多分類混淆矩陣圖。best.pt和last.pt的區(qū)別必須說(shuō)清如果早停被觸發(fā)last.pt 停在最后一個(gè) epoch而 best.pt 停在 val acc 峰值處很多人的部署模型用的是 last.pt結(jié)果準(zhǔn)確率比訓(xùn)練時(shí)低一大截就是這個(gè)原因。驗(yàn)證命令也由同一個(gè)腳本流程串起來(lái)yolo classify val modelruns/ricecls/yolo11n-224/weights/best.pt data./data/ricecls imgsz224 batch16跑完會(huì)輸出 val acc top1 和 top5 兩個(gè)指標(biāo)。top1 就是要重點(diǎn)盯的它代表“模型對(duì)一張水稻葉圖片給出的最高概率類別恰好是真實(shí)類別”的比例。如果 top1 在驗(yàn)證集上有 85% 以上這個(gè)模型已經(jīng)具備基本的巡田篩查能力如果只有 60%別急著調(diào)參先回頭把第 5 章的排查清單過(guò)一遍大概率是數(shù)據(jù)問(wèn)題而不是模型問(wèn)題。5. 訓(xùn)練與排查分類準(zhǔn)確率上不去的 4 類常見(jiàn)翻車現(xiàn)場(chǎng)這一章寫(xiě)的是我踩過(guò)或幫別人排過(guò)的最常見(jiàn)的坑。每條按“現(xiàn)象、原因、解決”三件套展開(kāi)你對(duì)照自己的日志就能定位問(wèn)題。5.1 某一類準(zhǔn)確率塌方其他類都正?,F(xiàn)象混淆矩陣圖上某一個(gè)類別的對(duì)角線數(shù)值特別低被錯(cuò)誤地分到另一個(gè)視覺(jué)相似的類里。比如胡麻葉斑病被大量預(yù)測(cè)成稻瘟病。原因兩類視覺(jué)特征重疊且其中一類樣本數(shù)量少。胡麻葉斑病的斑點(diǎn)小而密稻瘟病葉瘟的斑點(diǎn)呈梭形但在低分辨率或光照不均的照片上二者差異被抹平。解決先看這個(gè)類的樣本數(shù)是否明顯低于均值如果是回到第 2.3 節(jié)做合并或過(guò)采樣如果數(shù)量正常則問(wèn)題出在類本身的視覺(jué)區(qū)分度這時(shí)可以查一下這兩個(gè)類對(duì)應(yīng)的訓(xùn)練圖片看看是不是標(biāo)注本身把接近的圖片分錯(cuò)了。我遇到過(guò)一次真實(shí)情況是“細(xì)菌性條斑病”和“稻白葉枯病”在早期癥狀上幾乎無(wú)法肉眼區(qū)分人工標(biāo)注的一致性都只有 80%模型再努力也就到瓶頸。這時(shí)候最好的解決是合并成一個(gè)大類“細(xì)菌性葉部病害”把任務(wù)重新定義為四分類而不是硬扛五分類。5.2 訓(xùn)練 loss 一直在降但驗(yàn)證集準(zhǔn)確率漲到某個(gè)點(diǎn)后開(kāi)始掉現(xiàn)象終端輸出的 train loss 曲線非常漂亮持續(xù)下降但 val acc 到 85% 附近就停住再往后開(kāi)始緩慢下跌。把 results.csv 拉出來(lái)畫(huà)曲線能看到明顯的 gap 拉大。原因過(guò)擬合。模型開(kāi)始記住訓(xùn)練集里的背景紋理、光照條件甚至拍攝設(shè)備的 EXIF 特征在沒(méi)見(jiàn)過(guò)的驗(yàn)證圖上自然吃癟。解決先把 epochs 交給早停處理確認(rèn) patience 生效然后加大weight_decay從默認(rèn)的 0.0005 提到 0.001再檢查訓(xùn)練時(shí)是否正確開(kāi)了augmentTrue如果為了追求“訓(xùn)練速度”關(guān)掉了增強(qiáng)過(guò)擬合提前出現(xiàn)是必然結(jié)果。這里要特別注意調(diào)參時(shí)一次只動(dòng)一個(gè)變量。我見(jiàn)過(guò)把 weight_decay、epochs、augment 三個(gè)同時(shí)改掉結(jié)果模型精度反而下降都不知道是哪個(gè)改動(dòng)導(dǎo)致的。5.3 CUDA out of memory 或訓(xùn)練非常慢現(xiàn)象訓(xùn)練在第一個(gè) epoch 跑到一半直接報(bào)CUDA out of memory或者全程 GPU 利用率只有 40% 但顯存已被占滿。原因batch 和 imgsz 乘積超過(guò)顯存容量workers 設(shè)得太高導(dǎo)致 CPU 預(yù)處理跟不上GPU 頻繁等待。解決按顯存減半調(diào)整。batch 從 16 減到 8imgsz從 224 減到 160二者對(duì)顯存的影響是乘法關(guān)系改一個(gè)不夠就兩個(gè)一起改。再不行換yolo11n-cls.pt是最小的分類權(quán)重。workers4在 Windows 上經(jīng)常因?yàn)槎噙M(jìn)程數(shù)據(jù)加載報(bào)錯(cuò)改成workers0可以繞過(guò)去代價(jià)是每個(gè) epoch 的數(shù)據(jù)加載時(shí)間變長(zhǎng)但至少不報(bào)錯(cuò)。另外檢查一下是不是同時(shí)開(kāi)著其他占顯存的進(jìn)程nvidia-smi看一眼我至少兩次發(fā)現(xiàn)是隔壁同事的訓(xùn)練任務(wù)占著顯存。5.4 訓(xùn)練集上指標(biāo)很好一到無(wú)人機(jī)實(shí)拍照片就崩現(xiàn)象驗(yàn)證集準(zhǔn)確率 88%把模型部署到無(wú)人機(jī)拍攝的畫(huà)面里對(duì)畫(huà)面中心裁剪出的葉片圖預(yù)測(cè)準(zhǔn)確率跌到 60% 以下。原因域差異。訓(xùn)練照片是近景特寫(xiě)葉片大、背景干凈無(wú)人機(jī)照片是俯拍葉片小、背景有泥土和水面反光模型的注意力被背景干擾。如果數(shù)據(jù)集里有大量近景特寫(xiě)YOLO11cls 學(xué)到的可能不完全是葉片紋理而是“背景健康的深色斑點(diǎn)有病的”這種捷徑。解決訓(xùn)練前對(duì)圖片做隨機(jī)背景替換增強(qiáng)把葉片從原圖中摳出來(lái)貼到泥土、水面、水泥地等不同背景上或者在推理端先做 patch 裁剪把無(wú)人機(jī)大圖切成 224 的塊再用模型逐塊分類。推理端的 patch 滑動(dòng)步長(zhǎng)設(shè)為寬度的 50%可以做重疊覆蓋減少漏檢。這一步是 POC 走向落地的必經(jīng)之路越早發(fā)現(xiàn)越省錢。5.5 訓(xùn)練中斷了想續(xù)上結(jié)果但不記得參數(shù)了現(xiàn)象訓(xùn)練到第 37 個(gè) epoch 時(shí)斷電或手動(dòng) CtrlC重跑完整腳本則前 37 個(gè) epoch 白費(fèi)。原因沒(méi)有使用斷點(diǎn)恢復(fù)機(jī)制Ultralytics 的resume參數(shù)沒(méi)有啟用。解決在訓(xùn)練腳本里預(yù)留resumeTrue的入口讓它自動(dòng)從runs/ricecls/yolo11n-224/weights/last.pt續(xù)訓(xùn)。注意 resume 只認(rèn)last.pt不認(rèn)best.pt這是框架的行為不要改動(dòng)。續(xù)訓(xùn)前先檢查last.pt文件的大小如果只有幾百字節(jié)說(shuō)明在 epoch 中途中斷且沒(méi)有來(lái)得及寫(xiě)入 checkpoint這種情況沒(méi)有后悔藥只能重新跑所以我的習(xí)慣是給訓(xùn)練命令加nohup或screen兜底防止終端關(guān)閉導(dǎo)致進(jìn)程被殺。6. 從跑通到能用混淆矩陣、誤判圖與分類閾值調(diào)優(yōu)模型跑通只是起點(diǎn)。我每次訓(xùn)練完的第一步不是看 acc而是打開(kāi)confusion_matrix.png找出對(duì)角線之外哪兩塊顏色最深——它們才是真正決定這個(gè)模型能否上田間的關(guān)鍵。誤判最多的一對(duì)類決定了你的類目設(shè)計(jì)是否合理。比如胡麻葉斑和稻瘟病怎么都分不開(kāi)合并類目比瘋狂調(diào)參更實(shí)用。第二步是導(dǎo)出誤判圖。用 best.pt 對(duì)驗(yàn)證集做一次批量預(yù)測(cè)把預(yù)測(cè)錯(cuò)誤的圖片按“真實(shí)類別-預(yù)測(cè)類別”分組存到本地目錄人眼快速掃一遍。這一步能發(fā)現(xiàn)很多指標(biāo)看不到的問(wèn)題某類誤判圖全是模糊照片說(shuō)明數(shù)據(jù)質(zhì)量拖了后腿某類誤判圖是清晨背光拍攝的暗圖說(shuō)明訓(xùn)練集里缺少低光照樣本需要在數(shù)據(jù)層面補(bǔ)。第三步是調(diào)整分類閾值。YOLO11cls 輸出的probs.top1conf不是校準(zhǔn)過(guò)的概率直接把最大值作為置信度容易給低質(zhì)量圖一個(gè)虛高的分?jǐn)?shù)。我的做法是在推理腳本里設(shè)置一個(gè) 0.7 的閾值低于這個(gè)值統(tǒng)一歸類為“待人工復(fù)核”寧可讓無(wú)人機(jī)多拍幾張也不要讓錯(cuò)誤判斷混進(jìn)病害統(tǒng)計(jì)報(bào)表。閾值定多少取決于你對(duì)漏報(bào)和誤報(bào)的容忍度病害篩查場(chǎng)景下我傾向保守。部署到邊緣設(shè)備時(shí)用model.export(formatonnx)轉(zhuǎn)成 ONNX再按目標(biāo)平臺(tái)量化成 int8 TFLite推理延遲能從幾十毫秒降到個(gè)位數(shù)毫秒。我習(xí)慣在交付前把整條鏈路做成一個(gè) test 腳本輸入 50 張訓(xùn)練中沒(méi)見(jiàn)過(guò)的實(shí)拍圖輸出每張圖的類名、置信度和標(biāo)注判斷人工核對(duì)一遍再?zèng)Q定是否工程化。這個(gè)習(xí)慣幫我擋掉過(guò)至少三次“驗(yàn)證集 90% 但現(xiàn)場(chǎng)零可用”的尷尬。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取