:從數(shù)據(jù)處理到訓(xùn)練調(diào)參全攻略)
簡介卷積神經(jīng)網(wǎng)絡(luò)CNN是深度學(xué)習(xí)圖像分類任務(wù)的核心技術(shù)通過卷積核自動提取從邊緣到語義的層級特征省去了傳統(tǒng)手工特征設(shè)計的繁瑣。圖像分類作為AI入門經(jīng)典場景其技術(shù)價值在于讓模型從數(shù)據(jù)中自主習(xí)得判別能力而數(shù)據(jù)增強和遷移學(xué)習(xí)則是提升小樣本數(shù)據(jù)集泛化性能的關(guān)鍵手段。在實際工程中花卉圖像識別常被用于課程設(shè)計、畢業(yè)設(shè)計乃至農(nóng)業(yè)智能化應(yīng)用需經(jīng)歷數(shù)據(jù)預(yù)處理、模型搭建、訓(xùn)練調(diào)參與性能評估的完整流程。本文以基于CNN的花卉圖像分類項目為例從數(shù)據(jù)集組織、增強策略、網(wǎng)絡(luò)結(jié)構(gòu)選擇到訓(xùn)練細節(jié)系統(tǒng)梳理了從零構(gòu)建一個可靠分類模型的實踐要點與常見陷阱幫助讀者真正理解深度學(xué)習(xí)全流程的工程邏輯。 花卉圖像分類這個題目可以說是深度學(xué)習(xí)入門和畢設(shè)課設(shè)里的常青樹。我接觸過不少拿它做課題的同學(xué)也幫人審過相關(guān)的代碼和論文一個很深的感受是這個題目乍一看不難網(wǎng)上能搜到的現(xiàn)成代碼也一大堆但真要從數(shù)據(jù)處理、模型搭建、訓(xùn)練調(diào)參一路走通再整理成一篇能通過答辯的項目里面其實藏著不少容易忽略的細節(jié)。這篇就專門聊一聊基于CNN的花卉圖像分類項目從零開始做需要經(jīng)歷哪些環(huán)節(jié)每一環(huán)節(jié)的核心邏輯是什么以及有哪些我實際踩過或者幫別人排查過的坑。之所以這個題目適合畢設(shè)或者課設(shè)是因為它麻雀雖小五臟俱全。CNN卷積神經(jīng)網(wǎng)絡(luò)、圖像預(yù)處理、數(shù)據(jù)增強、模型訓(xùn)練、性能評估這些深度學(xué)習(xí)的基本功都能在一個項目里完整覆蓋到。而且花卉圖像本身類間差異明顯、背景相對可控對初學(xué)者來說模型收斂難度適中做出效果的概率遠高于那些需要大量調(diào)參的復(fù)雜任務(wù)。正因為如此它非常適合用來驗證你是否真正理解了深度學(xué)習(xí)的全流程而不只是會調(diào)庫跑通一個Demo。1. 從選題到方案設(shè)計這個項目到底在解決什么問題先別急著寫代碼。我見過不少同學(xué)一上來就打開Jupyter Notebook先加載一遍數(shù)據(jù)集跑一個LeNet看到準確率有80%就覺得完事了。結(jié)果到了寫畢業(yè)論文或者課程報告的時候發(fā)現(xiàn)自己根本講不清楚為什么要用CNN、數(shù)據(jù)為什么要這么處理、準確率到80%算好還是不好。所以第一步把項目的邏輯鏈條理清楚?;ɑ軋D像分類的本質(zhì)是一個圖像識別任務(wù)輸入是一張包含某種花卉的圖片輸出是該圖片屬于哪個類別。這個任務(wù)看起來簡單但背后有一個很關(guān)鍵的問題花卉圖片的拍攝條件高度不統(tǒng)一。同樣是玫瑰花有的圖片是特寫有的圖片包含大量綠色背景有的光線偏暗有的花在畫面中只占很小一塊區(qū)域。如果用傳統(tǒng)的圖像處理方法比如提取顏色直方圖、紋理特征再喂給SVM你會發(fā)現(xiàn)特征設(shè)計本身就非常痛苦而且泛化能力很差。CNN卷積神經(jīng)網(wǎng)絡(luò)之所以在這場競賽中勝出核心在于它通過卷積核自動學(xué)習(xí)圖像特征從低級邊緣、顏色塊到中級的紋理、形狀片段再到高級的語義部件層層抽象最后用全連接層把特征映射到具體的類別上。也就是說我們不需要手工設(shè)計特征了模型自己從數(shù)據(jù)里學(xué)。這也是深度學(xué)習(xí)相對傳統(tǒng)機器學(xué)習(xí)最本質(zhì)的差異。從這個題目出發(fā)方案設(shè)計通常要考慮三件事數(shù)據(jù)集規(guī)模和質(zhì)量、網(wǎng)絡(luò)結(jié)構(gòu)的復(fù)雜程度、訓(xùn)練策略的可行性。對本科畢設(shè)或課程設(shè)計來說合理的方案不是追求SOTAstate-of-the-art性能而是在可控的算力條件下把整個深度學(xué)習(xí)pipeline走通并對實驗結(jié)果有合理的分析和解釋。所以后面所有步驟都要圍繞“可解釋、可復(fù)現(xiàn)、可擴展”這三個關(guān)鍵詞來做。2. 數(shù)據(jù)集這一關(guān)數(shù)據(jù)怎么選、怎么分、怎么增強2.1 公開數(shù)據(jù)集還是自建數(shù)據(jù)集花卉分類最常用的公開數(shù)據(jù)集是Oxford 102 Flowers和17 Category Flower Dataset。102類花卉包含大約8000多張圖片每類40到258張不等類別數(shù)量多、圖片分辨率高17類花則更小巧適合快速跑通流程。我做項目一般優(yōu)先推薦這兩個因為它們是學(xué)術(shù)界常用benchmark相關(guān)領(lǐng)域的論文都可以引用做畢設(shè)的時候文獻綜述那部分也好寫。如果不想用公開數(shù)據(jù)集自建數(shù)據(jù)集的流程也很簡單到一些圖片素材網(wǎng)站上按類別下載圖片人工篩選出清晰、主體明確、沒有水印遮擋的圖片然后按類別建立文件夾。這里有個容易被忽略的點自建數(shù)據(jù)集一定要控制類別的均衡性盡量讓每一類圖片數(shù)量差不多。不然模型會在樣本量大的類別上嚴重過擬合而樣本量小的類別幾乎學(xué)不到有效特征。2.2 文件夾結(jié)構(gòu)是最省心的數(shù)據(jù)組織方式PyTorch的torchvision.datasets.ImageFolder接口可以直接根據(jù)文件夾結(jié)構(gòu)生成數(shù)據(jù)集這比手寫一個Dataset類要省事得多。標準結(jié)構(gòu)是這樣的flower_data/ train/ rose/ rose_001.jpg rose_002.jpg sunflower/ sunflower_001.jpg ... val/ rose/ rose_001.jpg sunflower/ sunflower_001.jpg ...訓(xùn)練集和驗證集分離是必須的而且分離操作要在任何預(yù)處理之前完成。千萬不要先把所有圖片統(tǒng)一讀入內(nèi)存再隨機打亂劃分那樣很容易造成數(shù)據(jù)泄漏——某些圖片的副本同時出現(xiàn)在訓(xùn)練集和驗證集中導(dǎo)致驗證集準確率虛高答辯時被老師一問就露餡。2.3 數(shù)據(jù)增強小數(shù)據(jù)集救星花卉圖像分類經(jīng)常面臨一個問題數(shù)據(jù)集不夠大。Oxford 102每類平均只有80張圖直接訓(xùn)練很容易過擬合訓(xùn)練集準確率接近100%驗證集卻卡在70%上下。這時候最有效的辦法就是數(shù)據(jù)增強。所謂數(shù)據(jù)增強是在不改變圖片語義標簽的前提下對原始圖片做一系列隨機變換讓模型每輪訓(xùn)練看到的樣本都有細微差異相當(dāng)于免費擴充了數(shù)據(jù)集。我常用的增強組合如下from torchvision import transforms train_transforms transforms.Compose([ transforms.RandomResizedCrop(224, scale(0.6, 1.0)), transforms.RandomHorizontalFlip(), transforms.RandomRotation(15), transforms.ColorJitter(brightness0.2, contrast0.2, saturation0.2), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) val_transforms transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])這里有幾個細節(jié)值得注意。RandomResizedCrop隨機裁剪圖片的一部分并縮放到固定尺寸這能模擬花朵在畫面中位置和大小不同的情況RandomHorizontalFlip和RandomRotation模擬拍攝角度變化ColorJitter調(diào)整亮度、對比度和飽和度模擬不同光線條件。這些變換加在一起模型見過的“不同照片”數(shù)量就大大增加了。驗證集則不能做隨機增強只能用Resize加CenterCrop保證每次驗證時輸入是確定的這樣準確率指標才有可比性。數(shù)據(jù)增強是訓(xùn)練集專屬操作驗證集和測試集永遠只用確定性變換。2.4 一個容易翻車的數(shù)據(jù)劃分細節(jié)使用ImageFolder時默認的類別順序是按文件夾名稱排序的比如daisy是0dandelion是1。這個順序會直接映射到模型輸出的類別索引上。所以一定要在訓(xùn)練前把類別名稱和索引的對應(yīng)關(guān)系保存下來后面做預(yù)測時才能把索引還原成中文或英文花名。我見過有人訓(xùn)練的時候順手打亂了文件夾列表結(jié)果類別順序變了測試時預(yù)測結(jié)果全亂套找了一晚上bug才發(fā)現(xiàn)問題出在這里。3. 模型搭建手寫一個能解釋清楚的CNN還是遷移學(xué)習(xí)3.1 為什么從零手寫一個簡單CNN是值得的畢設(shè)答辯時老師經(jīng)常會問一個問題“你能說說這個網(wǎng)絡(luò)結(jié)構(gòu)為什么這么設(shè)計嗎”如果用的是ResNet50預(yù)訓(xùn)練模型你大概率只能說“這個是經(jīng)典結(jié)構(gòu)效果好”。這當(dāng)然也是一種回答但如果你的課題重點在于理解CNN本身而不是比拼性能那自己設(shè)計并實現(xiàn)一個結(jié)構(gòu)簡單的CNN反而更容易講出深度。我推薦的做法是以VGG或者ResNet的思路為參考搭建一個包含3到4個卷積塊的小型CNN。每個卷積塊由卷積層、批歸一化BatchNorm、ReLU激活函數(shù)和最大池化組成。這種設(shè)計思路清晰每一步都能解釋清楚卷積層用于提取局部特征隨著層數(shù)加深特征圖從邊緣紋理過渡到花瓣、花蕊等語義部件BatchNorm用于穩(wěn)定訓(xùn)練過程緩解梯度消失或梯度爆炸問題ReLU提供非線性表達能力最大池化降低特征圖尺寸減小計算量同時保留主要的激活響應(yīng)。下面是一個結(jié)構(gòu)參考輸入是224×224的RGB圖片輸出是類別數(shù)import torch.nn as nn class SimpleCNN(nn.Module): def __init__(self, num_classes102): super(SimpleCNN, self).__init__() self.features nn.Sequential( nn.Conv2d(3, 32, kernel_size3, padding1), nn.BatchNorm2d(32), nn.ReLU(inplaceTrue), nn.MaxPool2d(2, 2), nn.Conv2d(32, 64, kernel_size3, padding1), nn.BatchNorm2d(64), nn.ReLU(inplaceTrue), nn.MaxPool2d(2, 2), nn.Conv2d(64, 128, kernel_size3, padding1), nn.BatchNorm2d(128), nn.ReLU(inplaceTrue), nn.MaxPool2d(2, 2), nn.Conv2d(128, 256, kernel_size3, padding1), nn.BatchNorm2d(256), nn.ReLU(inplaceTrue), nn.MaxPool2d(2, 2), ) self.classifier nn.Sequential( nn.AdaptiveAvgPool2d((1, 1)), nn.Flatten(), nn.Dropout(0.5), nn.Linear(256, num_classes) ) def forward(self, x): x self.features(x) x self.classifier(x) return x這個網(wǎng)絡(luò)會把224×224的輸入逐步降采樣到14×14最后通過全局平均池化得到一個256維的特征向量再經(jīng)過Dropout和全連接層輸出類別得分。3.2 遷移學(xué)習(xí)讓效果上一個臺階的捷徑如果你的目標是刷高準確率或者發(fā)現(xiàn)自訓(xùn)練的小網(wǎng)絡(luò)一直卡在某個準確率上不去那就果斷切換到遷移學(xué)習(xí)。用ImageNet上預(yù)訓(xùn)練好的ResNet18或ResNet50作為骨干網(wǎng)絡(luò)凍結(jié)前面大部分層的參數(shù)只訓(xùn)練最后的全連接分類層通??梢园褱蚀_率從80%以下提升到90%以上。遷移學(xué)習(xí)也不是簡單替換模型就完事有兩個細節(jié)至關(guān)重要。第一預(yù)訓(xùn)練模型的輸入規(guī)范是ImageNet的均值和標準差所以數(shù)據(jù)預(yù)處理那部分必須用Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225])這正好就是我上面代碼里寫的那組參數(shù)。第二替換最后一層全連接時要讓新層的輸出維度等于你的花卉類別數(shù)比如102類就是102。舊層的權(quán)重參數(shù)要丟棄因為ImageNet的1000類輸出對你的任務(wù)沒有任何意義。import torchvision.models as models model models.resnet18(pretrainedTrue) num_ftrs model.fc.in_features model.fc nn.Linear(num_ftrs, num_classes)3.3 防止過擬合的幾板斧不管用自建CNN還是遷移學(xué)習(xí)過擬合都是繞不開的問題。判斷過擬合最直接的標準是訓(xùn)練集準確率達到95%以上驗證集準確率卻明顯低一截兩者差距越來越大。常用的對策有三個Dropout、權(quán)重衰減weight decay和數(shù)據(jù)增強。上面模型里的Dropout就是干這個用的訓(xùn)練時在優(yōu)化器中設(shè)置weight_decay1e-4對大的權(quán)重做懲罰再配合前面說的數(shù)據(jù)增強三管齊下基本能壓住大多數(shù)小數(shù)據(jù)集上的過擬合問題。BatchNorm雖然主要是為穩(wěn)定訓(xùn)練引入的但它本身也有一點正則化效果。所以你會發(fā)現(xiàn)加了BatchNorm之后同等條件下模型的泛化能力會比單純用卷積加激活更好一些。4. 訓(xùn)練流程與調(diào)參讓網(wǎng)絡(luò)真正“學(xué)進去”4.1 損失函數(shù)、優(yōu)化器和學(xué)習(xí)率的選擇圖像分類的標配是交叉熵損失CrossEntropyLoss配合隨機梯度下降SGD或者Adam優(yōu)化器。交叉熵把網(wǎng)絡(luò)輸出的原始得分logits轉(zhuǎn)成概率分布再和真實標簽的one-hot分布計算差異它的梯度形式對多分類任務(wù)來說非常友好。有兩個調(diào)參經(jīng)驗值得單獨說。一是遷移學(xué)習(xí)時優(yōu)化器要分層設(shè)置學(xué)習(xí)率骨干網(wǎng)絡(luò)的學(xué)習(xí)率小一些比如0.001新替換的全連接層學(xué)習(xí)率可以大一些比如0.01。因為預(yù)訓(xùn)練權(quán)重已經(jīng)收斂到比較好的位置大步長更新容易把學(xué)到的特征破壞掉而新層是從頭訓(xùn)練的需要更大的步長才能快速收斂。二是如果發(fā)現(xiàn)loss在訓(xùn)練初期就劇烈震蕩不下降首要懷疑學(xué)習(xí)率過大試著把學(xué)習(xí)率除以10看看變化。4.2 訓(xùn)練主循環(huán)中容易被忽略的四個細節(jié)模型訓(xùn)練的主循環(huán)寫法網(wǎng)上比比皆是但有幾個細節(jié)我每次都要強調(diào)因為都是實際踩過的坑第一訓(xùn)練/驗證模式切換。訓(xùn)練前要調(diào)用model.train()讓Dropout和BatchNorm進入訓(xùn)練模式驗證前要調(diào)用model.eval()關(guān)閉Dropout并用全局統(tǒng)計量做BatchNorm歸一化。忘掉這一步的最典型癥狀是訓(xùn)練表現(xiàn)正常驗證時結(jié)果時好時壞或者完全不可復(fù)現(xiàn)。第二梯度清零。每個batch開始前必須optimizer.zero_grad()否則梯度會累加到上一輪導(dǎo)致參數(shù)更新方向完全錯誤。第三梯度計算關(guān)閉。驗證階段用with torch.no_grad():包裹能顯著降低顯存占用和計算開銷還可以避免誤操作產(chǎn)生梯度。第四模型和數(shù)據(jù)的設(shè)備一致性。模型和數(shù)據(jù)要么都在GPU上要么都在CPU上混放會直接報錯。用device torch.device(cuda if torch.cuda.is_available() else cpu)統(tǒng)一管理即可。4.3 訓(xùn)練循環(huán)的參考寫法def train_one_epoch(model, dataloader, criterion, optimizer, device): model.train() running_loss 0.0 correct 0 total 0 for inputs, labels in dataloader: inputs, labels inputs.to(device), labels.to(device) optimizer.zero_grad() outputs model(inputs) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() * inputs.size(0) _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() epoch_loss running_loss / total epoch_acc correct / total return epoch_loss, epoch_acc驗證階段的代碼把model.train()換成model.eval()把optimizer.zero_grad()、loss.backward()、optimizer.step()這三行去掉再用torch.no_grad()包住整個循環(huán)即可。驗證損失和準確率都算出來之后可以順便做一件事如果驗證準確率比當(dāng)前歷史最優(yōu)值高就把模型參數(shù)保存下來。這樣訓(xùn)練結(jié)束后拿到的是整個訓(xùn)練過程中表現(xiàn)最好的模型而不是最后一輪的模型。4.4 學(xué)習(xí)率調(diào)度和早停機制訓(xùn)練迭代次數(shù)設(shè)多少很多初學(xué)者喜歡拍腦袋設(shè)一個固定值比如50輪。實際訓(xùn)練時我發(fā)現(xiàn)更好的做法是觀察loss曲線動態(tài)判斷。這里我習(xí)慣用兩步走先用一個比較大的學(xué)習(xí)率跑10輪左右觀察loss下降趨勢等loss下降變緩時用學(xué)習(xí)率調(diào)度器或者手動把學(xué)習(xí)率除以10再繼續(xù)訓(xùn)練。PyTorch里常用ReduceLROnPlateau它會在驗證loss連續(xù)若干個epoch不再下降時自動降低學(xué)習(xí)率scheduler torch.optim.lr_scheduler.ReduceLROnPlateau( optimizer, modemin, factor0.5, patience5 ) # 每個epoch結(jié)束后 scheduler.step(val_loss)早停機制則是設(shè)置一個耐心值比如連續(xù)10個epoch驗證準確率不提升就停止訓(xùn)練并加載歷史最佳模型。這兩個機制組合使用可以避免訓(xùn)練時間過長、也避免過擬合到訓(xùn)練集上。我一般把總epoch上限設(shè)成50到80配合早停絕大多數(shù)情況能在30輪以內(nèi)拿到最佳模型。5. 評估與可視化除了準確率答辯還要看這些5.1 混淆矩陣和分類報告準確率是一個過于宏觀的指標。如果你的數(shù)據(jù)集中某些類別數(shù)量偏多模型只要把多的那幾類學(xué)好準確率數(shù)字就能很好看但對少數(shù)類的分類能力可能很差。所以評估階段一定要畫出混淆矩陣并計算每一類的精確率precision、召回率recall和F1分數(shù)?;煜仃嚳梢灾庇^地看出哪些類別容易被模型混淆。比如我在做102類花卉分類時就發(fā)現(xiàn)繡球花和丁香花經(jīng)?;ハ嗾J錯因為它們的花瓣顏色和形態(tài)確實接近而且公開數(shù)據(jù)集中這兩類圖片的拍攝角度差異比較大。這個分析結(jié)果放在論文里是很寶貴的實驗內(nèi)容能體現(xiàn)你做了深入思考而不只是貼了一張訓(xùn)練曲線。計算分類報告用sklearn的classification_report即可傳入測試集預(yù)測結(jié)果和真實標簽。注意要用索引映射回類別名再輸出否則光看第47類是誰還得回去翻映射表非常麻煩。5.2 預(yù)測結(jié)果可視化除了數(shù)值指標把模型預(yù)測結(jié)果以圖片形式展示出來對答辯演示特別有幫助。選擇驗證集中若干張圖片分別打印真實標簽、預(yù)測標簽和預(yù)測置信度排成網(wǎng)格可視化。置信度可以用softmax概率的最大值來表示它能直觀展示模型對預(yù)測的確定程度。這段代碼的關(guān)鍵在于從網(wǎng)絡(luò)輸出logits到置信度之間要過一次softmax而且torchvision.utils.make_grid得到的圖像張量在顯示時要記得反標準化把之前Normalize減去的均值加回去、除以的方差乘回去再轉(zhuǎn)成numpy格式并調(diào)整通道順序為HWC。5.3 訓(xùn)練曲線繪制訓(xùn)練曲線是另一個必備圖。橫軸是epoch縱軸分別是loss和accuracy兩條線分別對應(yīng)訓(xùn)練集和驗證集。從loss曲線可以判斷模型是否有過擬合訓(xùn)練loss持續(xù)下降而驗證loss在某一輪之后不降反升就是過擬合的直接信號。從accuracy曲線可以判斷訓(xùn)練是否收斂曲線趨于平緩且沒有繼續(xù)上升趨勢時說明可以停止訓(xùn)練了。畫圖工具用matplotlib就夠了關(guān)鍵是把每次epoch的train_loss、val_loss、train_acc、val_acc都記錄下來。這里有個小技巧記錄時用Python列表保存訓(xùn)練完后一次性畫圖不要每個epoch都保存一張圖效率低還會產(chǎn)生大量無用文件。6. 從“能跑通”到“能答辯”項目包裝與擴展方向6.1 做成一個可交互的Demo如果課設(shè)答辯有現(xiàn)場演示環(huán)節(jié)強烈建議做一個簡單的圖形界面或Web應(yīng)用把訓(xùn)練好的模型封裝起來讓用戶上傳一張花卉圖片界面直接返回分類結(jié)果和置信度。這種直觀的demo比貼一段代碼解釋半天要有說服力得多。實現(xiàn)方式可以用gradio幾行代碼就能搭建一個網(wǎng)頁版上傳接口部署成本極低。也可以寫一個基于Tkinter的桌面小工具。這個環(huán)節(jié)不需要做得多華麗核心是展示“我訓(xùn)練的模型能夠?qū)φ鎸嵼斎胱鐾评怼边@已經(jīng)是完整工程能力的體現(xiàn)了。6.2 值得寫在論文里的擴展方向如果想給項目加分或者論文需要“未來展望”的內(nèi)容可以考慮下面幾個方向。加上注意力機制讓模型在分類時更關(guān)注花朵區(qū)域而不是背景用卷積神經(jīng)網(wǎng)絡(luò)配合LSTM或Transformer做序列特征融合做模型剪枝和量化把模型壓縮到可以在移動端運行。這些都是研究熱點而且基于現(xiàn)有代碼改造起來并不算復(fù)雜。不過我要提醒一句任何擴展都要在你的baseline模型的結(jié)果上做對比實驗證明擴展確實帶來了效果提升。很多同學(xué)擴展方向選得很好但沒有做對比實驗最后答辯時被問到“你加的注意力機制到底帶來了多少提升”就答不上來了。6.3 我的一些個人經(jīng)驗最后分享一個我在多個課程項目里用到的習(xí)慣固定隨機種子。在代碼最前面設(shè)置torch.manual_seed(0)、random.seed(0)、numpy.random.seed(0)并盡量保證數(shù)據(jù)加載的順序是確定的。深度學(xué)習(xí)中很多“這次效果好、下次效果差”的詭異情況都是隨機性引起的。固定種子不花錢但能讓你的實驗可復(fù)現(xiàn)寫報告時數(shù)字也穩(wěn)得住這是任何嚴謹項目的基本功。另外訓(xùn)練得到的模型文件、日志文件、數(shù)據(jù)集劃分記錄一定要歸檔好。目錄命名帶上日期和模型結(jié)構(gòu)信息比如resnet18_0501_lr0.001。不然做對比實驗時你可能會遇到“咦這個效果最好的模型是哪次訓(xùn)練來的”這種尷尬。歸檔習(xí)慣好的項目不僅能幫你節(jié)省時間在答辯展示時也會讓老師覺得你做事規(guī)范。這個題目本身不難難的是把每一步都做扎實、做能講清楚。從數(shù)據(jù)準備到模型設(shè)計再到訓(xùn)練評估每一步都值得花心思去理解背后的原理。希望這篇內(nèi)容能幫你少走彎路。本文還有配套的精品資源點擊獲取