作物病蟲害識別系統(tǒng):從數(shù)據(jù)集到部署的完整實戰(zhàn)指南)
簡介這是一套面向高校計算機、人工智能與智慧農(nóng)業(yè)方向?qū)W生的畢業(yè)設計完整資料圍繞深度學習在常見農(nóng)作物病蟲害識別中的應用展開適合需要完成高分畢設或系統(tǒng)學習圖像分類實戰(zhàn)的讀者。壓縮包共281個文件約522.63MB包含14個Python源碼文件、8個Vue前端文件與7個JavaScript腳本構(gòu)成可運行的識別系統(tǒng)另有107個txt說明、83張jpg與34張png圖像樣本、6份pdf及3份caj參考文獻、3份docx論文文檔覆蓋數(shù)據(jù)、代碼與寫作全流程。資源已獲導師指導并通過內(nèi)含論文各章節(jié)內(nèi)容從緒論、國內(nèi)外研究現(xiàn)狀、數(shù)據(jù)收集與視覺顯著性處理到卷積神經(jīng)網(wǎng)絡原理、Inception-V3與MobileNet-V2模型對比均有涉及可幫助讀者理解從數(shù)據(jù)獲取、負樣本構(gòu)建到模型訓練與部署的完整鏈路。目前已有2897人學習下載適合作為畢設參考與深度學習項目練手素材。1. 從一張黃瓜葉片的照片說起這套病蟲害識別系統(tǒng)到底能做什么去年夏天一個做溫室種植的朋友發(fā)來一張照片黃瓜葉片上布滿黃褐色斑點邊緣還帶著一圈黃暈。他問我這是什么病我盯著看了半天只敢說“可能是霜霉病也可能是靶斑病”因為這兩種病害在早期葉片上的表現(xiàn)實在太像了。后來把照片發(fā)給農(nóng)科院的朋友人家用顯微鏡一看確診是靶斑病。這件事讓我意識到農(nóng)作物病蟲害識別這件事靠人眼和經(jīng)驗在常見病害上還能湊合一旦遇到相似癥狀或者早期感染翻車概率非常高?;谏疃葘W習的常見農(nóng)作物病蟲害識別系統(tǒng)要解決的就是這個問題給一張葉片或者植株的照片模型告訴你這大概率是什么病、置信度多少、建議怎么處理。它適合三類人一是做畢業(yè)設計的學生需要一個有完整源碼、教程和論文框架的課題二是想入門深度學習但不知道拿什么數(shù)據(jù)集練手的開發(fā)者農(nóng)業(yè)圖像分類是一個數(shù)據(jù)相對干凈、類別明確、落地場景清晰的方向三是做智慧農(nóng)業(yè)相關產(chǎn)品的工程師需要快速驗證一個識別模塊能不能嵌入到現(xiàn)有的巡檢或者監(jiān)測流程里。這套系統(tǒng)的核心鏈路其實不復雜采集圖像、預處理、用 CNN 或者 Transformer 類模型做分類、輸出結(jié)果。但真正做起來坑集中在數(shù)據(jù)集的類別不平衡、田間光照和背景干擾、模型在移動端或者邊緣設備上的部署效率這幾個地方。下面我會按“數(shù)據(jù)怎么準備、模型怎么選、代碼怎么寫、坑怎么避”的順序把一套可復現(xiàn)的方案講清楚。2. 數(shù)據(jù)集選型與預處理從 PlantVillage 到田間實拍圖的鴻溝2.1 為什么 PlantVillage 是起點但不是終點做農(nóng)業(yè)病蟲害識別繞不開 PlantVillage 這個數(shù)據(jù)集。它包含約 5 萬多張葉片圖像覆蓋 14 種作物、26 種病害背景大多是實驗室條件下的純色背景葉片居中、光照均勻。對于剛?cè)腴T深度學習的人來說這個數(shù)據(jù)集非常友好因為它的類別標注清晰圖像質(zhì)量穩(wěn)定訓練一個 ResNet 或者 MobileNet準確率很容易沖到 95% 以上。但這里有一個血淚經(jīng)驗在 PlantVillage 上跑到 99% 準確率的模型拿到田間實拍圖上準確率可能直接掉到 60% 以下。原因很簡單田間圖像有復雜的背景、不均勻的光照、葉片遮擋、不同生長階段的外觀變化。所以我的做法是用 PlantVillage 做預訓練或者基線驗證然后必須用自己采集的田間圖像做微調(diào)。如果拿不到田間數(shù)據(jù)至少要做數(shù)據(jù)增強模擬光照變化、旋轉(zhuǎn)、裁剪、噪聲。常見做法是先把 PlantVillage 按 8:1:1 劃分訓練集、驗證集、測試集保證每個類別在三個集合中的比例一致。如果某個類別的樣本數(shù)太少比如少于 200 張就要考慮過采樣或者用數(shù)據(jù)增強擴充。2.2 用 Python 腳本完成數(shù)據(jù)劃分與增強下面這段代碼做三件事讀取 PlantVillage 的目錄結(jié)構(gòu)、按類別分層劃分數(shù)據(jù)集、對訓練集做實時增強。代碼依賴torchvision和splitfolders安裝命令是pip install torchvision splitfolders。import splitfolders from torchvision import transforms from torch.utils.data import DataLoader from torchvision.datasets import ImageFolder # 第一步分層劃分數(shù)據(jù)集保證每個類別在訓練/驗證/測試中的比例一致 # input_path 是原始數(shù)據(jù)目錄結(jié)構(gòu)為 root/類別名/圖片.jpg splitfolders.ratio( inputPlantVillage/raw, outputPlantVillage/split, seed42, ratio(0.8, 0.1, 0.1), # 訓練:驗證:測試 group_prefixNone ) # 第二步定義訓練集和驗證集的預處理流程 # 訓練集用較強的增強驗證集只做 resize 和歸一化 train_transform transforms.Compose([ transforms.Resize((224, 224)), # 統(tǒng)一輸入尺寸適配 ResNet/MobileNet transforms.RandomHorizontalFlip(p0.5), # 水平翻轉(zhuǎn)模擬不同拍攝角度 transforms.RandomRotation(15), # 小角度旋轉(zhuǎn)模擬葉片朝向變化 transforms.ColorJitter( # 模擬田間光照變化 brightness0.2, contrast0.2, saturation0.2, hue0.05 ), transforms.ToTensor(), transforms.Normalize( # ImageNet 均值方差遷移學習常用 mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225] ) ]) val_transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize( mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225] ) ]) # 第三步構(gòu)建 Dataset 和 DataLoader train_dataset ImageFolder(PlantVillage/split/train, transformtrain_transform) val_dataset ImageFolder(PlantVillage/split/val, transformval_transform) train_loader DataLoader(train_dataset, batch_size32, shuffleTrue, num_workers4) val_loader DataLoader(val_dataset, batch_size32, shuffleFalse, num_workers4) print(f訓練集類別數(shù): {len(train_dataset.classes)}) print(f訓練集樣本數(shù): {len(train_dataset)}) print(f驗證集樣本數(shù): {len(val_dataset)})這段代碼的關鍵參數(shù)有三個。ratio(0.8, 0.1, 0.1)是劃分比例如果數(shù)據(jù)集本身很小可以改成 7:1.5:1.5給驗證集多一點樣本。Resize((224, 224))是輸入尺寸ResNet50 和 MobileNetV3 都支持這個尺寸如果要用 EfficientNet-B4可以改成 380。ColorJitter里的 brightness 和 contrast 不要設太大0.2 左右就夠了設太大反而會讓模型學到錯誤的顏色關聯(lián)。注意劃分數(shù)據(jù)集之前一定要檢查每個類別的樣本數(shù)。如果某個類別少于 100 張分層劃分后測試集可能只有不到 10 張評估結(jié)果波動會很大。這種情況建議先做數(shù)據(jù)增強擴充或者用類別權(quán)重來緩解不平衡。2.3 田間圖像預處理的三個額外步驟如果你手頭有田間實拍圖預處理流程要加三步。第一步是背景分割用簡單的顏色閾值或者 GrabCut 把葉片區(qū)域摳出來減少土壤、天空、地膜的干擾。第二步是光照歸一化用 CLAHE限制對比度自適應直方圖均衡把過曝或者欠曝的圖像拉回來。第三步是尺寸篩選把分辨率低于 300x300 的圖像剔除因為放大后細節(jié)丟失嚴重模型學不到有效特征。這三步不需要每一步都做到完美但至少要做背景分割和光照歸一化。我試過直接拿原圖訓練模型在驗證集上的準確率比做了背景分割的版本低了 8 個百分點原因就是模型把背景里的土壤顏色當成了分類依據(jù)。3. 模型選型CNN、Transformer 還是輕量級網(wǎng)絡3.1 ResNet50、MobileNetV3、ViT 的取舍邏輯選模型這件事沒有絕對的最優(yōu)解只有適不適合你的場景。如果你的目標是畢業(yè)設計需要跑出一個好看的準確率同時論文里能畫出清晰的對比實驗ResNet50 是最穩(wěn)妥的選擇。它的結(jié)構(gòu)經(jīng)典預訓練權(quán)重容易獲取在 PlantVillage 上微調(diào)幾十個 epoch 就能收斂。缺點是參數(shù)量大推理速度在 CPU 上偏慢。如果你要做移動端或者邊緣設備部署比如把模型塞進樹莓派或者安卓手機里MobileNetV3 或者 EfficientNet-Lite 更合適。MobileNetV3-Small 的參數(shù)量只有 2.5M 左右在驍龍 865 上單張推理時間可以壓到 20ms 以內(nèi)。代價是準確率會比 ResNet50 低 2 到 4 個百分點具體低多少取決于你的數(shù)據(jù)集難度。ViTVision Transformer這兩年在圖像分類上很火但它對數(shù)據(jù)量的要求比 CNN 高得多。PlantVillage 只有 5 萬多張圖直接從頭訓練 ViT 很容易過擬合。常見做法是用在 ImageNet 上預訓練過的 ViT-B/16然后凍結(jié)前幾個 block只微調(diào)后面的層。如果論文里想體現(xiàn)“前沿性”可以加一組 ViT 的對比實驗但主力模型還是建議用 CNN。下面這張表是我在同一個數(shù)據(jù)集上跑出來的對比結(jié)果硬件是單卡 RTX 3060輸入尺寸 224x224訓練 30 個 epoch。模型參數(shù)量驗證集準確率單張推理時間CPU模型大小ResNet5025.6M96.8%85ms98MBMobileNetV3-Small2.5M93.2%18ms10MBEfficientNet-B05.3M95.1%32ms21MBViT-B/1686M94.5%210ms330MB從表里能看出來ResNet50 的準確率最高但 MobileNetV3 的性價比最好。如果你的畢業(yè)設計需要部署演示用 MobileNetV3 做前端ResNet50 做后端對比論文里既有精度分析又有工程落地內(nèi)容會更完整。3.2 用 PyTorch 構(gòu)建遷移學習訓練流程下面這段代碼用 ResNet50 做遷移學習凍結(jié)前面的卷積層只訓練最后的全連接層和部分高層。代碼依賴torch、torchvision安裝命令是pip install torch torchvision。import torch import torch.nn as nn import torch.optim as optim from torchvision import models # 加載預訓練 ResNet50num_classes 改成你的病害類別數(shù) num_classes 26 # PlantVillage 的 26 種病害 model models.resnet50(pretrainedTrue) # 凍結(jié)前 7 個層組只訓練 layer4 和 fc # 這樣做的原因是底層特征邊緣、紋理通用性強不需要重新學 for name, param in model.named_parameters(): if layer4 not in name and fc not in name: param.requires_grad False # 替換最后的全連接層輸出維度改成類別數(shù) model.fc nn.Linear(model.fc.in_features, num_classes) # 定義損失函數(shù)和優(yōu)化器 # CrossEntropyLoss 自帶 softmax不需要在模型里加 criterion nn.CrossEntropyLoss() # 只優(yōu)化需要梯度的參數(shù)學習率設 1e-3 optimizer optim.Adam( filter(lambda p: p.requires_grad, model.parameters()), lr1e-3, weight_decay1e-4 # L2 正則防止過擬合 ) # 學習率調(diào)度每 7 個 epoch 衰減一次 scheduler optim.lr_scheduler.StepLR(optimizer, step_size7, gamma0.1) # 訓練循環(huán) device torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device) for epoch in range(30): model.train() running_loss 0.0 for images, labels in train_loader: images, labels images.to(device), labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() scheduler.step() print(fEpoch {epoch1}, Loss: {running_loss/len(train_loader):.4f})這段代碼里有幾個參數(shù)需要根據(jù)你的實際情況調(diào)整。num_classes必須和你的數(shù)據(jù)集類別數(shù)一致如果做的是自定義數(shù)據(jù)集先統(tǒng)計一下類別數(shù)量。lr1e-3是 Adam 的常用初始學習率如果你解凍了更多層建議降到 1e-4否則容易破壞預訓練權(quán)重。weight_decay1e-4是 L2 正則系數(shù)數(shù)據(jù)集越小這個值可以適當調(diào)大比如 1e-3。提示凍結(jié)層數(shù)不是固定的。如果你的數(shù)據(jù)集和 ImageNet 差異很大比如葉片圖像和自然圖像的顏色分布完全不同可以只凍結(jié)前 3 個層組讓更多層參與訓練。判斷方法是看訓練集和驗證集的準確率差距如果訓練集準確率遠高于驗證集說明模型過擬合需要凍結(jié)更多層或者加正則。3.3 類別不平衡的處理加權(quán)損失與重采樣農(nóng)業(yè)病蟲害數(shù)據(jù)集有一個很現(xiàn)實的問題某些病害的樣本特別多某些特別少。比如 PlantVillage 里健康葉片的樣本數(shù)遠多于某些罕見病害。如果直接訓練模型會傾向于預測樣本多的類別導致稀有病害的召回率很低。常見做法有兩種。第一種是給損失函數(shù)加類別權(quán)重權(quán)重和樣本數(shù)成反比。第二種是用 WeightedRandomSampler 做重采樣讓每個 batch 里稀有類別的樣本被抽到的概率更高。我一般會同時用這兩種方法先重采樣再加權(quán)損失。from torch.utils.data import WeightedRandomSampler import numpy as np # 統(tǒng)計每個類別的樣本數(shù) class_counts np.bincount(train_dataset.targets) class_weights 1.0 / class_counts sample_weights class_weights[train_dataset.targets] # 構(gòu)建 WeightedRandomSampler sampler WeightedRandomSampler( weightssample_weights, num_sampleslen(sample_weights), replacementTrue ) # 重新構(gòu)建 train_loader傳入 sampler train_loader DataLoader( train_dataset, batch_size32, samplersampler, # 注意用了 sampler 就不能再設 shuffleTrue num_workers4 ) # 損失函數(shù)加類別權(quán)重 class_weights_tensor torch.FloatTensor(class_weights).to(device) criterion nn.CrossEntropyLoss(weightclass_weights_tensor)這段代碼的關鍵是class_weights 1.0 / class_counts樣本越少的類別權(quán)重越大。replacementTrue表示有放回抽樣保證每個 epoch 都能抽到稀有類別的樣本。用了 sampler 之后DataLoader 的 shuffle 參數(shù)必須去掉否則會報錯。4. 訓練過程中的避坑與排查從 loss 不下降到過擬合4.1 現(xiàn)象訓練 loss 震蕩不下降驗證準確率卡在 10% 左右原因通常有三個。第一學習率設太大了Adam 的默認學習率是 1e-3但如果你的 batch size 很小比如 8 或者 161e-3 可能導致梯度爆炸。第二數(shù)據(jù)歸一化沒做對比如用了 ImageNet 的均值和方差但你的圖像像素值范圍是 0 到 255 而不是 0 到 1。第三標簽有問題比如類別索引從 1 開始而不是從 0 開始導致 CrossEntropyLoss 計算錯誤。解決方法是先把學習率降到 1e-4 試一下如果 loss 開始下降說明是學習率的問題。然后檢查transforms.ToTensor()是否在Normalize之前ToTensor 會把像素值從 0-255 縮放到 0-1。最后打印幾個 batch 的標簽確認標簽范圍是[0, num_classes-1]。4.2 現(xiàn)象訓練準確率 99%驗證準確率只有 60%這是典型的過擬合。原因可能是模型參數(shù)量太大、訓練數(shù)據(jù)太少、增強不夠強。解決方法是先加數(shù)據(jù)增強比如 RandomResizedCrop、RandAugment然后加 Dropout在全連接層前面加nn.Dropout(0.5)最后用早停驗證集 loss 連續(xù) 5 個 epoch 不下降就停止訓練。我一般會先看訓練集和驗證集的 loss 曲線。如果訓練 loss 持續(xù)下降但驗證 loss 開始上升說明過擬合已經(jīng)發(fā)生了這時候早停比繼續(xù)訓練更劃算。4.3 現(xiàn)象模型在測試集上表現(xiàn)很好但實際拍照識別總是錯原因通常是測試集和實際場景的分布不一致。PlantVillage 的測試集也是實驗室條件和田間實拍圖差異很大。解決方法是在測試集里加入至少 20% 的田間圖像或者用域適應的方法比如在訓練時混合實驗室和田間圖像讓模型學到更魯棒的特征。還有一個容易被忽略的點是圖像尺寸。訓練時用的是 224x224 的居中裁剪但實際拍照時葉片可能不在畫面中央或者只占畫面的一小部分。這種情況需要在預處理階段加目標檢測先把葉片框出來再送進分類模型。4.4 現(xiàn)象GPU 顯存不夠batch size 只能設到 8原因可能是模型太大、輸入尺寸太大、或者沒有用混合精度訓練。解決方法是先用torch.cuda.amp做混合精度顯存占用可以降低 30% 到 40%。然后把輸入尺寸從 224 降到 192 或者 160準確率會掉 1 到 2 個百分點但顯存占用大幅下降。如果還是不夠就用梯度累積把 batch size 設成 8但每 4 個 batch 才更新一次參數(shù)等效于 batch size 32。from torch.cuda.amp import autocast, GradScaler scaler GradScaler() for images, labels in train_loader: images, labels images.to(device), labels.to(device) optimizer.zero_grad() with autocast(): # 混合精度前向傳播 outputs model(images) loss criterion(outputs, labels) scaler.scale(loss).backward() # 縮放梯度 scaler.step(optimizer) scaler.update()混合精度訓練的關鍵是autocast和GradScaler配合使用。autocast自動把部分計算轉(zhuǎn)成 float16GradScaler防止梯度下溢。注意用了混合精度之后學習率可能需要稍微調(diào)大一點因為 float16 的精度損失會讓梯度變小。5. 從源碼到論文畢業(yè)設計里怎么把實驗做扎實5.1 論文框架的四個必備章節(jié)如果你的畢業(yè)設計題目是“基于深度學習的常見農(nóng)作物病蟲害識別系統(tǒng)”論文框架可以按這個結(jié)構(gòu)搭。第一章緒論講研究背景和國內(nèi)外現(xiàn)狀引用幾篇近三年的農(nóng)業(yè)圖像分類論文。第二章相關技術(shù)介紹 CNN、遷移學習、注意力機制的基本原理不用寫太深但要把關鍵概念解釋清楚。第三章系統(tǒng)設計包括數(shù)據(jù)集構(gòu)建、預處理流程、模型結(jié)構(gòu)、訓練策略。第四章實驗與分析這是最核心的部分要有對比實驗、消融實驗、可視化結(jié)果。對比實驗至少要有三組不同模型的對比ResNet vs MobileNet vs ViT、不同預處理方法的對比有無背景分割、有無數(shù)據(jù)增強、不同訓練策略的對比凍結(jié)層數(shù)、學習率調(diào)度。消融實驗可以看某個模塊的貢獻比如加了注意力機制之后準確率提升了多少。可視化結(jié)果包括混淆矩陣、Grad-CAM 熱力圖、部分測試樣本的預測結(jié)果。5.2 用 Grad-CAM 做模型可解釋性分析Grad-CAM 是畢業(yè)設計里很加分的一個點它能告訴你模型在預測時關注了圖像的哪個區(qū)域。如果模型關注的是葉片上的病斑說明它學到了正確的特征如果關注的是背景或者葉片邊緣說明模型可能走了捷徑。from pytorch_grad_cam import GradCAM from pytorch_grad_cam.utils.image import show_cam_on_image import numpy as np # 選擇目標層ResNet50 通常選 layer4 的最后一個 block target_layers [model.layer4[-1]] # 構(gòu)建 GradCAM 對象 cam GradCAM(modelmodel, target_layerstarget_layers) # 取一張測試圖像 input_tensor val_transform(image).unsqueeze(0).to(device) # 生成熱力圖 grayscale_cam cam(input_tensorinput_tensor, targetsNone) grayscale_cam grayscale_cam[0, :] # 疊加到原圖上 visualization show_cam_on_image( np.array(image) / 255.0, grayscale_cam, use_rgbTrue )這段代碼依賴pytorch-grad-cam庫安裝命令是pip install pytorch-grad-cam。target_layers選的是 ResNet50 的最后一個殘差塊這一層的特征圖分辨率是 7x7熱力圖會比較粗糙但語義信息強。如果想要更精細的熱力圖可以選 layer3但語義信息會弱一些。5.3 論文里怎么描述實驗參數(shù)論文里的實驗參數(shù)要寫清楚但不用把代碼全貼上去。我一般會用一個表格列出關鍵配置包括硬件環(huán)境、軟件版本、訓練超參數(shù)、數(shù)據(jù)增強策略。比如配置項值GPUNVIDIA RTX 3060 12GB框架PyTorch 2.0輸入尺寸224x224Batch Size32初始學習率1e-3優(yōu)化器Adam學習率調(diào)度StepLR, step7, gamma0.1訓練輪數(shù)30數(shù)據(jù)增強水平翻轉(zhuǎn)、隨機旋轉(zhuǎn)、顏色抖動這樣寫的好處是審稿老師或者答辯評委能快速判斷你的實驗是否合理也方便別人復現(xiàn)。如果用了預訓練權(quán)重要注明是在 ImageNet 上預訓練的因為這是遷移學習的基本前提。6. 部署與推理優(yōu)化讓模型在樹莓派上跑起來6.1 模型導出為 ONNX 并用 ONNX Runtime 推理訓練完的 PyTorch 模型如果要部署到邊緣設備第一步通常是導出成 ONNX 格式。ONNX 是一個通用的模型交換格式支持多種推理引擎包括 ONNX Runtime、TensorRT、OpenVINO。import torch.onnx # 把模型設為評估模式 model.eval() # 構(gòu)造一個示例輸入 dummy_input torch.randn(1, 3, 224, 224).to(device) # 導出 ONNX torch.onnx.export( model, dummy_input, plant_disease_resnet50.onnx, export_paramsTrue, opset_version11, # ONNX 算子集版本11 兼容性較好 do_constant_foldingTrue, input_names[input], output_names[output], dynamic_axes{ # 動態(tài) batch 維度方便批量推理 input: {0: batch_size}, output: {0: batch_size} } )導出之后用 ONNX Runtime 做推理速度比原生 PyTorch 在 CPU 上快 2 到 3 倍。opset_version11是一個比較穩(wěn)妥的選擇如果部署環(huán)境支持更高的版本可以改成 13 或者 15。dynamic_axes讓模型支持變長 batch推理時可以根據(jù)實際需求調(diào)整。6.2 樹莓派上的推理性能實測我在樹莓派 4B4GB 內(nèi)存上測過幾個模型的推理速度。ResNet50 的 ONNX 模型單張推理時間大約是 450msMobileNetV3-Small 大約是 80msEfficientNet-B0 大約是 150ms。如果要做實時檢測比如每秒處理 5 幀以上MobileNetV3 是唯一能在樹莓派上跑得比較流暢的選擇。優(yōu)化手段有三個。第一用 ONNX Runtime 的量化工具做 INT8 量化模型大小縮小到原來的四分之一推理速度提升 1.5 到 2 倍準確率掉 1 到 2 個百分點。第二把輸入尺寸從 224 降到 160推理時間減少約 40%。第三用多線程推理ONNX Runtime 支持設置intra_op_num_threads樹莓派 4B 有 4 個核心設成 4 可以充分利用 CPU。import onnxruntime as ort # 配置 ONNX Runtime 會話 sess_options ort.SessionOptions() sess_options.intra_op_num_threads 4 # 使用 4 個 CPU 核心 sess_options.graph_optimization_level ort.GraphOptimizationLevel.ORT_ENABLE_ALL session ort.InferenceSession( plant_disease_mobilenetv3.onnx, sess_optionssess_options, providers[CPUExecutionProvider] ) # 推理 input_name session.get_inputs()[0].name output session.run(None, {input_name: input_tensor.numpy()})graph_optimization_level設成ORT_ENABLE_ALL會啟用所有圖優(yōu)化包括算子融合、常量折疊、內(nèi)存復用。intra_op_num_threads設成 4 是因為樹莓派 4B 有 4 個核心設太多反而會因為線程切換導致性能下降。6.3 一個容易被忽略的細節(jié)輸入圖像的預處理要對齊訓練時的預處理和推理時的預處理必須完全一致否則準確率會大幅下降。我踩過一次坑訓練時用了ColorJitter做增強推理時忘了把圖像歸一化到相同的均值和方差結(jié)果模型把健康的葉片預測成了病害。后來在推理代碼里加了一個和驗證集完全一樣的 transform問題才解決。推理時的預處理一般只做 Resize、ToTensor、Normalize不要加隨機翻轉(zhuǎn)或者顏色抖動。如果你在訓練時用了背景分割推理時也要做同樣的背景分割否則模型看到的輸入分布和訓練時不一致。注意如果你的模型是在 PlantVillage 上訓練的部署到田間時一定要先做背景分割。我見過太多模型在實驗室數(shù)據(jù)上表現(xiàn)完美一到田間就翻車根本原因就是背景分布差異太大。6.4 最后說一個我自己的習慣每次訓練完一個模型我不會只看最終的準確率而是會把混淆矩陣打出來看看哪些類別之間容易混淆。比如霜霉病和靶斑病在混淆矩陣里經(jīng)?;ハ嗾`判。這時候我會針對性地補充這兩類病害的樣本或者設計一個二級分類器專門區(qū)分它們。這個習慣幫我省了很多返工的時間也讓論文里的分析更有深度。希望幫到你。本文還有配套的精品資源點擊獲取