習(xí)的花卉識(shí)別課程設(shè)計(jì)實(shí)戰(zhàn))
簡(jiǎn)介基于Python深度學(xué)習(xí)的花卉識(shí)別課程設(shè)計(jì)源碼專注于利用卷積神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)花卉圖像的自動(dòng)分類與識(shí)別可作為計(jì)算機(jī)視覺方向課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)參考也適合初學(xué)者入門圖像識(shí)別實(shí)戰(zhàn)。壓縮包內(nèi)共四十九個(gè)文件整體容量約三點(diǎn)三六兆字節(jié)內(nèi)部以花卉圖像數(shù)據(jù)、程序源碼、訓(xùn)練測(cè)試日志及說明文檔為主其中包含二十八張不同品種的花卉圖片涵蓋菊花等多個(gè)類別。代碼部分提供兩套深度學(xué)習(xí)模型實(shí)現(xiàn)一套采用預(yù)訓(xùn)練權(quán)重進(jìn)行遷移學(xué)習(xí)一套為自定義卷積神經(jīng)網(wǎng)絡(luò)并配有數(shù)據(jù)讀取、數(shù)據(jù)集劃分、模型測(cè)試等模塊幫助學(xué)習(xí)者快速掌握從圖像預(yù)處理到模型訓(xùn)練與評(píng)估的完整流程。項(xiàng)目還保留模型關(guān)注區(qū)域熱圖以及訓(xùn)練測(cè)試日志可直觀觀察模型關(guān)注特征并追蹤損失與準(zhǔn)確率變化同時(shí)附帶忽略規(guī)則文件、使用說明文本等目錄結(jié)構(gòu)清晰便于復(fù)現(xiàn)與二次開發(fā)。已有三百六十三人學(xué)習(xí)下載適合想要系統(tǒng)掌握卷積神經(jīng)網(wǎng)絡(luò)與遷移學(xué)習(xí)圖像分類、快速搭建完整花卉識(shí)別項(xiàng)目的開發(fā)者參考。1. 課程設(shè)計(jì)選花卉識(shí)別為什么它是深度學(xué)習(xí)的“最佳練手題”如果你正在為Python深度學(xué)習(xí)課程設(shè)計(jì)發(fā)愁花卉識(shí)別幾乎是所有選題里性價(jià)比最高的一個(gè)數(shù)據(jù)集好找、任務(wù)直觀、模型效果容易可視化而且它同時(shí)覆蓋了圖像分類、數(shù)據(jù)增強(qiáng)、遷移學(xué)習(xí)和模型部署這幾塊硬骨頭。很多人的第一個(gè)深度學(xué)習(xí)項(xiàng)目就是從“把一張花照片分成菊花、玫瑰、蒲公英”開始的。做這樣一個(gè)基于Python深度學(xué)習(xí)的花卉識(shí)別課程設(shè)計(jì)源碼項(xiàng)目你真正要交付的不只是一段能跑通的代碼而是一套“數(shù)據(jù)怎么處理、模型怎么選、參數(shù)怎么調(diào)、結(jié)果怎么解釋”的完整思路——這也是答辯時(shí)老師真正關(guān)心的東西。這篇筆記我按自己做課程設(shè)計(jì)帶組員時(shí)的習(xí)慣從torchvision自帶的花卉數(shù)據(jù)集講起把從數(shù)據(jù)預(yù)處理到模型訓(xùn)練的完整鏈路拆開最后把最容易翻車的幾個(gè)點(diǎn)和驗(yàn)證技巧也一并交代清楚。2. 數(shù)據(jù)集與預(yù)處理先解決“喂什么”的問題再談模型2.1 用torchvision自帶數(shù)據(jù)集跑通最小流程花卉識(shí)別的公開數(shù)據(jù)集很多但做課程設(shè)計(jì)我強(qiáng)烈建議先用torchvision.datasets里自帶的花卉數(shù)據(jù)集跑通全流程。原因很現(xiàn)實(shí)它不需要你額外去下載、解壓、手工劃分目錄API直接返回已經(jīng)分好類的圖像和標(biāo)簽?zāi)軒湍惆选皵?shù)據(jù)集的問題”和“模型的問題”分開排查起來省一半的力氣。import torchvision from torchvision import transforms from torch.utils.data import DataLoader 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]) ]) train_data torchvision.datasets.Flowers102( root./data, splittrain, downloadTrue, transformtransform ) train_loader DataLoader(train_data, batch_size32, shuffleTrue, num_workers4)這段代碼會(huì)從torchvision自動(dòng)下載Flowers102數(shù)據(jù)集——102個(gè)類別的花卉圖片每個(gè)類別在訓(xùn)練集里有10張、驗(yàn)證集里有10張測(cè)試集里數(shù)量不等。這里的預(yù)處理管線Resize((224, 224))是配合ImageNet預(yù)訓(xùn)練模型的固定輸入尺寸Normalize用ImageNet的均值和標(biāo)準(zhǔn)差這兩項(xiàng)是遷移學(xué)習(xí)場(chǎng)景下的標(biāo)準(zhǔn)做法不是隨便選的。參數(shù)說明batch_size在課程設(shè)計(jì)里設(shè)32或64都合適顯存不夠就降到16num_workers取決于你的CPU核心數(shù)Windows下設(shè)成2~4就足夠了設(shè)太高反而容易在數(shù)據(jù)加載時(shí)報(bào)錯(cuò)這個(gè)坑后面細(xì)說。splittrain和splittest會(huì)分別拿到訓(xùn)練集和驗(yàn)證集不需要自己再劃分。2.2 自制數(shù)據(jù)集目錄結(jié)構(gòu)與標(biāo)簽編碼如果你不想用現(xiàn)成的Flowers102想自己拍照片或者從網(wǎng)上收集花卉圖片那目錄結(jié)構(gòu)建議直接按ImageFolder的規(guī)范來組織這樣torchvision.datasets.ImageFolder能直接讀取少寫一堆自定義Dataset的代碼# 目錄結(jié)構(gòu)data/train/rose/*.jpg, data/train/sunflower/*.jpg # 目錄結(jié)構(gòu)data/val/rose/*.jpg, data/val/sunflower/*.jpg from torchvision.datasets import ImageFolder train_dataset ImageFolder(root./data/train, transformtransform) val_dataset ImageFolder(root./data/val, transformtransform) print(train_dataset.class_to_idx) # 打印類別名到索引的映射這里有個(gè)細(xì)節(jié)值得關(guān)注每個(gè)類別的訓(xùn)練圖片數(shù)量最好控制在幾十張到兩三百張之間太少模型學(xué)不到類內(nèi)差異太多對(duì)課程設(shè)計(jì)來說訓(xùn)練時(shí)間不劃算。另外采集圖片時(shí)盡量讓同一類花有不同背景、不同角度、不同光照的樣本否則模型很容易學(xué)會(huì)“識(shí)別背景”而不是“識(shí)別花”——這是個(gè)玄學(xué)問題但根源在數(shù)據(jù)不在模型。預(yù)處理這一步的關(guān)鍵結(jié)論是不管用什么數(shù)據(jù)源預(yù)處理都不該只做一個(gè)Resize加ToTensor至少要加上RandomHorizontalFlip或RandomRotation做數(shù)據(jù)增強(qiáng)。訓(xùn)練集和驗(yàn)證集的transform要分開寫驗(yàn)證集不能做隨機(jī)增強(qiáng)否則評(píng)估指標(biāo)會(huì)失真。3. 模型選型與訓(xùn)練ResNet是底線微調(diào)參數(shù)決定上限3.1 為什么課程設(shè)計(jì)首選ResNet而不是自己搭CNN很多人一開始會(huì)想自己搭一個(gè)幾層的卷積神經(jīng)網(wǎng)絡(luò)覺得這樣“更像自己做的”。我的建議是如果你不想在答辯時(shí)被問到“為什么你的模型過擬合這么嚴(yán)重”而答不上來那就直接用torchvision里預(yù)訓(xùn)練的ResNet18做遷移學(xué)習(xí)。理由有三個(gè)ResNet18只有約1100萬參數(shù)訓(xùn)練速度和顯存占用都友好CPU也能跑推理——這很關(guān)鍵因?yàn)楹芏嗾n程設(shè)計(jì)最終是在沒有GPU的機(jī)器上演示的。預(yù)訓(xùn)練權(quán)重是在ImageNet上學(xué)到的已經(jīng)內(nèi)置了大量通用視覺特征邊緣、紋理、形狀你的花卉數(shù)據(jù)集只需要微調(diào)最后幾層就能取得不錯(cuò)的效果。ResNet的殘差結(jié)構(gòu)在答辯時(shí)是一個(gè)很好的“技術(shù)亮點(diǎn)”你可以清楚地解釋這個(gè)結(jié)構(gòu)如何解決網(wǎng)絡(luò)退化問題比手寫CNN更容易講出深度。import torchvision.models as models import torch.nn as nn model models.resnet18(weightsmodels.ResNet18_Weights.IMAGENET1K_V1) num_ftrs model.fc.in_features model.fc nn.Linear(num_ftrs, 102) # 102對(duì)應(yīng)Flowers102的類別數(shù) # 凍結(jié)前幾層只微調(diào)最后一層 for param in model.parameters(): param.requires_grad False for param in model.fc.parameters(): param.requires_grad True device torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device)這段代碼的關(guān)鍵操作有兩處一是model.fc nn.Linear(num_ftrs, 102)把全連接層的輸出維度改成你的類別數(shù)二是通過requires_grad控制只訓(xùn)練最后一層。第一個(gè)操作是通用的分類頭替換模式第二個(gè)操作則是控制在多大程度上“借用”預(yù)訓(xùn)練知識(shí)。如果只訓(xùn)練最后一層且數(shù)據(jù)量少就幾乎不會(huì)過擬合但模型上限也低如果解凍更多層并加大學(xué)習(xí)率模型上限高但風(fēng)險(xiǎn)也高。3.2 訓(xùn)練腳本的完整結(jié)構(gòu)與兩個(gè)必調(diào)的損失函數(shù)參數(shù)訓(xùn)練循環(huán)看起來簡(jiǎn)單但課程設(shè)計(jì)翻車率高往往是因?yàn)槿鄙俸?jiǎn)單的檢查點(diǎn)、沒有合理使用損失函數(shù)的參數(shù)或者監(jiān)控了錯(cuò)誤的指標(biāo)。下面這段代碼是我平時(shí)帶項(xiàng)目時(shí)給組員的模板包含了“保存最佳模型”和“打印每個(gè)epoch的分類準(zhǔn)確率”這兩個(gè)關(guān)鍵能力import torch import torch.nn as nn import torch.optim as optim criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.fc.parameters(), lr1e-3) best_acc 0.0 epochs 15 for epoch in range(epochs): 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() # 驗(yàn)證階段 model.eval() correct, total 0, 0 with torch.no_grad(): for images, labels in val_loader: images, labels images.to(device), labels.to(device) outputs model(images) _, predicted torch.max(outputs.data, dim1) total labels.size(0) correct (predicted labels).sum().item() acc 100 * correct / total print(fEpoch {epoch1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}, Val Acc: {acc:.2f}%) if acc best_acc: best_acc acc torch.save(model.state_dict(), best_flower_model.pth)這里有一個(gè)新手常犯的錯(cuò)在驗(yàn)證階段忘了加model.eval()和with torch.no_grad()。前者會(huì)關(guān)掉Dropout和BatchNorm的隨機(jī)行為后者會(huì)停止構(gòu)建計(jì)算圖并大幅減少顯存占用。不加這兩行驗(yàn)證指標(biāo)是不準(zhǔn)確的。另一個(gè)隱蔽的問題是total labels.size(0)它統(tǒng)計(jì)的是所有batch的樣本總和而不是只取最后那個(gè)不完整batch的數(shù)量——不過DataLoader默認(rèn)drop_lastFalse所以寫成labels.size(0)就對(duì)了。CrossEntropyLoss在PyTorch里默認(rèn)已經(jīng)把LogSoftmax和NLLLoss合并了所以模型最后一層直接輸出原始logits就行不要再手動(dòng)加Softmax。如果要處理類別不均衡的數(shù)據(jù)集可以在CrossEntropyLoss里傳weight參數(shù)——以各個(gè)類別的樣本數(shù)倒數(shù)計(jì)算這是處理數(shù)據(jù)不均衡時(shí)最直接有效的做法。3.3 學(xué)習(xí)率和優(yōu)化器課程設(shè)計(jì)場(chǎng)景下的調(diào)整思路訓(xùn)練時(shí)你會(huì)經(jīng)常遇到一個(gè)現(xiàn)象loss在降低但準(zhǔn)確率上不去或者驗(yàn)證集準(zhǔn)確率忽高忽低。這時(shí)候調(diào)整學(xué)習(xí)率是第一步。常見的做法是先用1e-3的Adam跑幾個(gè)epoch如果loss下降太慢就調(diào)大到1e-2如果loss震蕩就調(diào)小到1e-4。# 學(xué)習(xí)率衰減每5個(gè)epoch衰減到原來的0.1倍 scheduler optim.lr_scheduler.StepLR(optimizer, step_size5, gamma0.1) # 在訓(xùn)練循環(huán)每輪結(jié)束后調(diào)用 scheduler.step()Adam已經(jīng)內(nèi)置了一階動(dòng)量和二階動(dòng)量所以它對(duì)學(xué)習(xí)率不像SGD那么敏感。但如果用了ImageNet預(yù)訓(xùn)練模型做完整微調(diào)SGD配momentum的收斂效果往往比Adam更穩(wěn)——這是一個(gè)“熱身”階段學(xué)習(xí)率從1e-4開始動(dòng)量0.9訓(xùn)練曲線會(huì)平滑很多。課程設(shè)計(jì)時(shí)間如果緊張Adam配上StepLR是最省心的組合。4. 避坑花卉識(shí)別課程設(shè)計(jì)最常見的6個(gè)翻車現(xiàn)場(chǎng)4.1 Flowers102數(shù)據(jù)集標(biāo)簽與類名不匹配現(xiàn)象模型訓(xùn)練準(zhǔn)確率很高但用測(cè)試圖片推理時(shí)的輸出結(jié)果和真實(shí)花名對(duì)不上。原因torchvision.datasets.Flowers102返回的是整數(shù)標(biāo)簽從0到101這些索引和數(shù)據(jù)集自帶的labels.txt文件是嚴(yán)格對(duì)應(yīng)的但和你從網(wǎng)上看到的類別名稱列表不一定一致。花卉名在Flowers102的官方標(biāo)注里是拉丁文比如“n04356074”這樣的WordNet ID如果你自行映射到中文花名很容易錯(cuò)位。解決直接使用dataset._labels或者下載官方label文件做一次映射表。比較保險(xiǎn)的做法是訓(xùn)練完就保存一份idx_to_name.json推理時(shí)從該文件讀取類別名不要每次手工指定列表。4.2 Windows下num_workers設(shè)置過高導(dǎo)致程序卡死或反復(fù)重啟現(xiàn)象代碼在for images, labels in train_loader:處停住不動(dòng)或每個(gè)epoch剛開始就報(bào)BrokenPipeError。原因Windows下多進(jìn)程數(shù)據(jù)加載和Linux行為不同當(dāng)num_workers大于0時(shí)如果代碼不是寫在if __name__ __main__保護(hù)塊里或者num_workers超過了CPU核心數(shù)就可能出現(xiàn)子進(jìn)程崩潰。解決把訓(xùn)練代碼放進(jìn)if __name__ __main__:下或者將num_workers直接設(shè)為0。課程設(shè)計(jì)階段的數(shù)據(jù)量并不大num_workers0的加載速度完全可以接受這是最省心的方案。4.3 驗(yàn)證集準(zhǔn)確率很高但單張圖片推理效果很差現(xiàn)象訓(xùn)練時(shí)在驗(yàn)證集上達(dá)到90%以上準(zhǔn)確率但拿一張手機(jī)拍的花去預(yù)測(cè)結(jié)果是錯(cuò)的。原因驗(yàn)證集圖像經(jīng)過了和你訓(xùn)練集一致的Resize(224, 224)和Normalize但你在推理時(shí)會(huì)忘記做同樣的預(yù)處理或用了不同的尺寸。這是最典型的“黑匣子”場(chǎng)景——模型本身沒問題問題是輸入管線的格式不一致。解決推理代碼和數(shù)據(jù)加載代碼復(fù)用同一個(gè)預(yù)處理函數(shù)。單獨(dú)定義一個(gè)get_transform()函數(shù)訓(xùn)練、驗(yàn)證、推理各環(huán)節(jié)都調(diào)用它不要在推理時(shí)重新寫一遍transform。4.4 訓(xùn)練loss不下降準(zhǔn)確率一直在1%左右現(xiàn)象第一個(gè)epoch后loss基本不變準(zhǔn)確率遠(yuǎn)低于類別數(shù)的倒數(shù)例如102類時(shí)約1%。原因最常見的是標(biāo)簽錯(cuò)位。比如用了ImageFolder但類別目錄和實(shí)際圖像不對(duì)應(yīng)或者數(shù)據(jù)集里部分圖片損壞導(dǎo)致自動(dòng)跳過。另一個(gè)原因是學(xué)習(xí)率過大導(dǎo)致loss直接nan。解決先用極小的學(xué)習(xí)率1e-5跑一個(gè)epoch確認(rèn)loss確實(shí)在下降再調(diào)回正常學(xué)習(xí)率。然后逐個(gè)檢查train_dataset.class_to_idx的映射挑幾張圖打印標(biāo)簽和圖像路徑確認(rèn)一致性。4.5 顯存不足CUDA out of memory現(xiàn)象訓(xùn)練第二個(gè)epoch時(shí)報(bào)CUDA out of memory。原因batch_size過大是主因但很多人忽略的是驗(yàn)證階段也占顯存——如果代碼加了torch.no_grad()但沒加model.eval()BatchNorm層仍然可能累積額外狀態(tài)。解決先把batch_size減半或者減少num_workers驗(yàn)證階段務(wù)必同時(shí)配合model.eval()和torch.no_grad()。如果還在爆就把輸入尺寸從224降到160——但注意這會(huì)改變預(yù)訓(xùn)練模型的輸入分布準(zhǔn)確性會(huì)有輕微下降。4.6 保存的模型加載后結(jié)果不一樣現(xiàn)象訓(xùn)練時(shí)指標(biāo)正常但重新加載.pth后推理結(jié)果明顯不對(duì)。原因加載模型時(shí)用了不同的類數(shù)量或者使用了不同的模型結(jié)構(gòu)。例如訓(xùn)練時(shí)是resnet18(num_classes102)加載時(shí)卻默認(rèn)了resnet18(num_classes1000)——因?yàn)閠orchvision默認(rèn)輸出維度是1000加載權(quán)重時(shí)不會(huì)報(bào)錯(cuò)但最后一層對(duì)不上。解決保存模型時(shí)同時(shí)保存模型結(jié)構(gòu)和超參數(shù)至少保存類別數(shù)torch.save({ model_state_dict: model.state_dict(), num_classes: 102, transform: transform }, flower_model_checkpoint.pth)加載時(shí)從checkpoint里讀取num_classes來重建模型結(jié)構(gòu)這樣就不會(huì)出現(xiàn)維度錯(cuò)位。5. 從課程設(shè)計(jì)到真正可用推理腳本、界面與指標(biāo)驗(yàn)證5.1 寫一個(gè)能接受單張圖片的推理腳本課程設(shè)計(jì)交到這一步很多同學(xué)認(rèn)為訓(xùn)練出模型就算結(jié)束了但答辯時(shí)老師最常問的一句話是“你這個(gè)模型實(shí)際用起來什么樣”所以一個(gè)能接收單張圖片并輸出“預(yù)測(cè)類別置信度”的腳本比多訓(xùn)練10個(gè)epoch都重要。推理腳本我習(xí)慣的做法如下import torch from PIL import Image import torchvision.transforms as transforms from torchvision import models 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]) ]) def load_model(checkpoint_path, num_classes102): model models.resnet18(weightsNone) model.fc torch.nn.Linear(model.fc.in_features, num_classes) checkpoint torch.load(checkpoint_path, map_locationcpu) model.load_state_dict(checkpoint[model_state_dict]) model.eval() return model def predict(image_path, model, idx_to_name): img Image.open(image_path).convert(RGB) img_tensor transform(img).unsqueeze(0) with torch.no_grad(): outputs model(img_tensor) probabilities torch.nn.functional.softmax(outputs[0], dim0) top_prob, top_idx torch.max(probabilities, dim0) return idx_to_name[top_idx.item()], top_prob.item() if __name__ __main__: model load_model(best_flower_model.pth) name, prob predict(test_rose.jpg, model, idx_to_name) print(f預(yù)測(cè)結(jié)果: {name}, 置信度: {prob:.2%})加上map_locationcpu意味著這個(gè)腳本即使在演示機(jī)器上只有CPU也能正常工作同時(shí)Image.open后接.convert(RGB)能避免某些灰度圖或RGBA圖在預(yù)處理時(shí)報(bào)通道數(shù)錯(cuò)誤。置信度輸出是所有課程設(shè)計(jì)演示中展現(xiàn)專業(yè)度的最好手段展示的可信度明顯高于只輸出類別名。5.2 用混淆矩陣驗(yàn)證模型的真實(shí)盲區(qū)準(zhǔn)確率是一個(gè)過于籠統(tǒng)的指標(biāo)。對(duì)花卉識(shí)別這個(gè)小數(shù)據(jù)集任務(wù)來說準(zhǔn)確率達(dá)到92%并不能證明模型“會(huì)認(rèn)花”可能只是繞開了某些容易混淆的類別。我習(xí)慣的做法是輸出一張混淆矩陣圖把它貼到課程設(shè)計(jì)報(bào)告里作為結(jié)果分析部分的核心證據(jù)。import matplotlib.pyplot as plt import numpy as np from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay all_labels, all_preds [], [] with torch.no_grad(): for images, labels in val_loader: images images.to(device) outputs model(images) _, predicted torch.max(outputs.cpu(), dim1) all_labels.extend(labels.numpy()) all_preds.extend(predicted.numpy()) cm confusion_matrix(all_labels, all_preds) disp ConfusionMatrixDisplay(confusion_matrixcm) disp.plot(cmapBlues) plt.savefig(confusion_matrix.png, dpi150)混淆矩陣能一眼看出來哪些類別互相打架比如向日葵和蒲公英如果經(jīng)?;煜f明兩者的顏色和紋理特征在模型看來沒有足夠的區(qū)分度——這時(shí)可以增加這類別的訓(xùn)練樣本量或者查一下是不是數(shù)據(jù)增強(qiáng)把花色、背景過度扭曲了。這里的一個(gè)關(guān)鍵技巧confusion_matrix的輸入必須是CPU上的NumPy數(shù)組很多人在all_labels.extend(labels)時(shí)忘了labels還在GPU上結(jié)果直接報(bào)錯(cuò)。5.3 后續(xù)值得做的兩個(gè)方向Gradio部署和細(xì)粒度分類如果要讓這個(gè)課程設(shè)計(jì)更出彩我強(qiáng)烈建議用Gradio把模型包裝成一個(gè)網(wǎng)頁應(yīng)用拖一張圖進(jìn)去就能看到識(shí)別結(jié)果和置信度。這是目前最討巧的展示手段——代碼量不到二十行且效果直觀。課程設(shè)計(jì)答辯時(shí)能把模型跑在網(wǎng)頁上的人基本上不會(huì)再被追問任何實(shí)現(xiàn)細(xì)節(jié)。另一個(gè)方向是細(xì)粒度花卉識(shí)別。常見的Flowers102已經(jīng)是一個(gè)難度不低的細(xì)粒度識(shí)別任務(wù)但如果你的數(shù)據(jù)是自己收集的、類別之間外觀差異更小時(shí)可以嘗試引入注意力機(jī)制模塊比如SE Block或者CBAM加到ResNet的每個(gè)殘差塊后面。這個(gè)改動(dòng)會(huì)顯著提升相似花朵的區(qū)分度還能給你的答辯增加一個(gè)“為了提升性能做了什么設(shè)計(jì)”的技術(shù)亮點(diǎn)。不過要注意加了注意力之后顯存占用上升約10%到15%訓(xùn)練時(shí)間也會(huì)變長(zhǎng)課程設(shè)計(jì)階段把精力放在可視化驗(yàn)證上更值得。最后說個(gè)我自己帶過的真實(shí)教訓(xùn)有一個(gè)組在答辯前一天還在大量調(diào)參想把準(zhǔn)確率從91%再推到95%以上結(jié)果答辯當(dāng)天模型過擬合在訓(xùn)練集上——這其實(shí)也是很多課程設(shè)計(jì)的通病。課程設(shè)計(jì)不是論文你的目標(biāo)是在有限時(shí)間內(nèi)展示“完整鏈路合理指標(biāo)可解釋的結(jié)果”而不是刷極限數(shù)字。把推理腳本、混淆矩陣和幾組對(duì)比實(shí)驗(yàn)的截圖準(zhǔn)備好比多跑50個(gè)epoch有價(jià)值得多。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取