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