:從數(shù)據(jù)標(biāo)注到實時部署全流程解析)
簡介一套完整的基于YOLO的犬類情緒識別項目包主要面向深度學(xué)習(xí)初學(xué)者和圖像分類實戰(zhàn)開發(fā)者尤其適合作為畢業(yè)設(shè)計、課程設(shè)計或期末大作業(yè)的參考項目。項目覆蓋從數(shù)據(jù)準(zhǔn)備、模型訓(xùn)練到測試評估與結(jié)果可視化的全流程能幫助使用者理解目標(biāo)檢測與動物情緒分類的落地方式適用于教學(xué)演示、項目匯報和算法對比實驗。壓縮包共72個文件約60.25MB其中以jpg/jpeg/png圖像樣本和結(jié)果圖為多數(shù)配合py訓(xùn)練與測試腳本、md說明文檔、依賴文件及gif演示結(jié)果目錄中另有模型目錄、輸出結(jié)果目錄和評估圖表包含P曲線、R曲線、PR曲線、F1曲線、混淆矩陣等便于直接查看模型效果。已有56人瀏覽學(xué)習(xí)。通過源碼、樣例圖片、訓(xùn)練后的模型與說明文檔使用者可復(fù)現(xiàn)犬類情緒識別實驗也可替換數(shù)據(jù)集進(jìn)行遷移訓(xùn)練節(jié)省從零搭建代碼與調(diào)參的時間是兼具教學(xué)參考和實際應(yīng)用價值的完整資料。1. 犬類情緒識別一個 YOLO 就能帶走的課程設(shè)計項目如果你正在為畢業(yè)設(shè)計或期末大作業(yè)發(fā)愁想找一個“深度學(xué)習(xí) 圖像識別”方向、能落地演示又能寫進(jìn)簡歷的項目基于 YOLO 的犬類情緒識別是個很務(wù)實的選擇。它能對狗的臉部表情和姿態(tài)做實時分類區(qū)分開心、焦慮、憤怒、悲傷、平靜這幾類典型情緒狀態(tài)覆蓋從數(shù)據(jù)標(biāo)注、模型訓(xùn)練到攝像頭推理的完整流程。這套資源最大的價值不是“識別有多準(zhǔn)”而是把深度學(xué)習(xí)中目標(biāo)檢測落地的完整鏈路都串起來了數(shù)據(jù)怎么清洗、VOC 標(biāo)注怎么轉(zhuǎn) YOLO 格式、訓(xùn)練參數(shù)怎么調(diào)、攝像頭實時推理怎么接、模型怎么導(dǎo)出部署。對新手來說它是一份能跟到最后的完整代碼包對已經(jīng)有基礎(chǔ)的人來說它也能當(dāng)成一個快速出結(jié)果的基線工程省掉從零搭環(huán)境的時間。我拆這個項目時最直觀的感受是真正的功夫不在訓(xùn)練那一步而在數(shù)據(jù)整理和參數(shù)調(diào)試上。下面按我自己的復(fù)現(xiàn)路徑往下走每個環(huán)節(jié)都給到可直接抄的代碼和參數(shù)。2. 數(shù)據(jù)先行整理、標(biāo)注轉(zhuǎn)換與五分類標(biāo)簽的落地方法2.1 數(shù)據(jù)從哪來構(gòu)建與清洗犬類情緒識別本質(zhì)上是一個目標(biāo)檢測任務(wù)輸入是包含犬只的圖片輸出是檢測框加上情緒類別。情緒識別比普通品種識別更難因為同類情緒在不同犬種上的表現(xiàn)差異很大哈士奇和柯基的“開心臉”完全是兩個畫風(fēng)。因此數(shù)據(jù)集的構(gòu)成直接影響模型能不能收斂。資源里自帶的原始圖片多為網(wǎng)圖、公開寵物數(shù)據(jù)集和少量自拍素材的混合體第一件要做的事是清洗。常見做法是把這三類圖片按“犬只朝向正面或側(cè)面 45 度以內(nèi)、臉部占比大于 1/4、單張圖只有一只狗、無大面積遮擋”的標(biāo)準(zhǔn)篩一遍。我一般會用一個簡單的腳本統(tǒng)計每張圖的尺寸和通道把損壞的、灰度異常的、分辨率低于 300px 的圖直接剔除。import os from PIL import Image src_dir raw_images valid_dir cleaned_images os.makedirs(valid_dir, exist_okTrue) min_side 300 removed [] for name in os.listdir(src_dir): path os.path.join(src_dir, name) try: img Image.open(path) img.verify() # 檢查文件是否損壞 w, h img.size if w min_side or h min_side: removed.append((name, too small)) continue if img.mode L: removed.append((name, grayscale)) continue img Image.open(path).convert(RGB) img.save(os.path.join(valid_dir, name)) except Exception as e: removed.append((name, str(e))) print(fremoved {len(removed)} files: {removed[:10]})img.verify()只做完整性校驗不開圖速度很快img.mode L是灰度圖過濾因為訓(xùn)練時顏色信息對情緒識別有貢獻(xiàn)灰度圖會引入分布偏移。這里把篩掉的圖片名打印出來便于回頭補數(shù)據(jù)時排查。清洗后大約能留下 70%80% 的圖片。這一步不能省臟數(shù)據(jù)進(jìn)訓(xùn)練集后面所有指標(biāo)都會變得奇怪。2.2 標(biāo)注格式轉(zhuǎn)換VOC 轉(zhuǎn) YOLO清洗完成后要處理的是標(biāo)注格式。資源包里原始標(biāo)注是 XMLVOC 格式而 YOLO 訓(xùn)練需要的是每個圖片對應(yīng)一個 txt每行寫“類別_id x_center y_center width height”坐標(biāo)全部歸一化到 0 到 1 之間。# convert_voc_to_yolo.py import xml.etree.ElementTree as ET import os # 類別順序必須與 data.yaml 中完全一致 CLASSES [angry, anxious, calm, happy, sad] def voc_to_yolo(xml_path, out_txt_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text.strip().lower() if cls_name not in CLASSES: continue box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h box_w (xmax - xmin) / w box_h (ymax - ymin) / h cls_id CLASSES.index(cls_name) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(out_txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) xml_dir annotations/voc txt_dir annotations/yolo os.makedirs(txt_dir, exist_okTrue) for xml_name in os.listdir(xml_dir): if not xml_name.endswith(.xml): continue stem os.path.splitext(xml_name)[0] voc_to_yolo(os.path.join(xml_dir, xml_name), os.path.join(txt_dir, stem .txt))寬度和高度必須從size標(biāo)簽里取不能自己用 PIL 再算一次。有些手機照片帶 EXIF 旋轉(zhuǎn)信息直接讀圖得到的寬高會被方向信息干擾標(biāo)注會整體偏移。歸一化坐標(biāo)讓不同分辨率的圖片在訓(xùn)練時能統(tǒng)一到同一個尺度這也是 YOLO 系列一直用這種方式的原因。轉(zhuǎn)換完成后抽查幾份 txt如果出現(xiàn) x_center 大于 1 或小于 0 的情況說明標(biāo)注框越界需要回到原 XML 修正。2.3 數(shù)據(jù)劃分與類別均衡分類項目的數(shù)據(jù)劃分不能只用隨機切分尤其是情緒識別這類天然不均衡的數(shù)據(jù)集。狗的表情里“開心”和“平靜”的樣本遠(yuǎn)多于“焦慮”和“憤怒”如果按原始比例切分驗證集里憤怒樣本可能只有個位數(shù)模型全猜平靜也能拿到高準(zhǔn)確率這會讓指標(biāo)失真。import os import random from collections import Counter from shutil import copy2 image_dir cleaned_images label_dir annotations/yolo train_dir dataset/images/train val_dir dataset/images/val train_label_dir dataset/labels/train val_label_dir dataset/labels/val for d in [train_dir, val_dir, train_label_dir, val_label_dir]: os.makedirs(d, exist_okTrue) label_files [f for f in os.listdir(label_dir) if f.endswith(.txt)] random.seed(42) # 統(tǒng)計每個類別的樣本框數(shù)量按框數(shù)而不是圖片數(shù)分配 cls_counter Counter() for lf in label_files: with open(os.path.join(label_dir, lf), r, encodingutf-8) as f: for line in f: cls_id int(line.split()[0]) cls_counter[cls_id] 1 print(class distribution:, dict(cls_counter)) train_ratio 0.85 train_files [] val_files [] # 分層采樣保證每個類別在驗證集中都有足夠樣本 for cls_id in range(len(CLASSES)): cls_files [ lf for lf in label_files if any(int(line.split()[0]) cls_id for line in open(os.path.join(label_dir, lf), r, encodingutf-8)) ] random.shuffle(cls_files) split_idx int(len(cls_files) * train_ratio) train_files.extend(cls_files[:split_idx]) val_files.extend(cls_files[split_idx:]) for f in train_files: copy2(os.path.join(image_dir, f.replace(.txt, .jpg)), train_dir) copy2(os.path.join(label_dir, f), train_label_dir) for f in val_files: copy2(os.path.join(image_dir, f.replace(.txt, .jpg)), val_dir) copy2(os.path.join(label_dir, f), val_label_dir)這里用了分層采樣先把包含某個類別的圖片單獨拎出來再按比例抽取確?!皯嵟边@類長尾類別不會在驗證集里消失。訓(xùn)練集比例取 0.85如果數(shù)據(jù)總量少于 1000 張可以提高到 0.9。這里有一個常見的翻車點按圖片數(shù)切分看似沒問題但一張圖里可能同時有兩只狗、兩個情緒框按圖片數(shù)切分會讓驗證集和訓(xùn)練集出現(xiàn)內(nèi)容重疊所以我按標(biāo)簽文件數(shù)來切并且只關(guān)心標(biāo)簽里出現(xiàn)過的類別。劃分完成后數(shù)據(jù)集目錄結(jié)構(gòu)就是標(biāo)準(zhǔn)的 YOLO 布局dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/最后寫一個data.yaml這是訓(xùn)練時唯一要指定的數(shù)據(jù)集配置文件類別列表順序必須與上一步的 CLASSES 完全一致。path: dataset train: images/train val: images/val names: 0: angry 1: anxious 2: calm 3: happy 4: sad3. 訓(xùn)練自己的識別模型環(huán)境、參數(shù)配置與損失函數(shù)解讀3.1 環(huán)境搭建與預(yù)訓(xùn)練權(quán)重訓(xùn)練環(huán)境是第一個攔路虎網(wǎng)上搜“YOLO 環(huán)境配置”能看到的坑基本都集中在 CUDA 和 torch 版本不匹配上。資源包里的代碼基于 YOLOv8ultralytics 框架Python 版本 3.8 到 3.10 都能跑我建議用 3.10。# 創(chuàng)建虛擬環(huán)境避免污染系統(tǒng) Python conda create -n yolo python3.10 -y conda activate yolo # 安裝 PyTorch先確認(rèn)本機 CUDA 版本再選擇對應(yīng)命令 pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 # 安裝 ultralytics pip install ultralytics8.0.100這里不要直接pip install ultralytics了事鎖版本很有必要。YOLOv8 的 API 在 8.0.x 之后有過一些調(diào)整資源代碼是在這個版本下調(diào)試過的升到 8.2 以上有些接口簽名會變新手照抄代碼可能跑不通。安裝完成后用yolo predict sourcehttps://ultralytics.com/images/bus.jpg驗證環(huán)境能出結(jié)果說明環(huán)境正常。預(yù)訓(xùn)練權(quán)重建議用yolov8s.pt而不是yolov8n.pt。雖然 nano 模型更小、訓(xùn)練更快但情緒特征嘴角弧度、耳朵位置非常細(xì)微nano 的淺層特征表達(dá)力不夠最終 mAP 會比 s 低 5 到 8 個點。如果顯卡顯存低于 6G再退回到y(tǒng)olov8n.pt。3.2 訓(xùn)練命令與超參數(shù)設(shè)置訓(xùn)練命令看起來簡單真正決定結(jié)果的是參數(shù)。下面是我在這套資源上調(diào)通的一組基線參數(shù)。yolo train \ modelyolov8s.pt \ datadog_emotion.yaml \ epochs100 \ imgsz640 \ batch16 \ device0 \ patience30 \ optimizerAdamW \ lr00.001 \ lrf0.01 \ mosaic1.0 \ fliplr0.5 \ scale0.3 \ projectruns/detect \ namedog_emotion_train逐個說參數(shù)含義。epochs100對于這個規(guī)模的數(shù)據(jù)集夠用太多會過擬合太少不收斂imgsz640是訓(xùn)練輸入分辨率如果顯卡允許改成 768 對情緒識別有明顯幫助因為臉部關(guān)鍵特征在低分辨率下容易糊掉batch16由顯存決定顯存 8G 用 1612G 以上可以到 32patience30表示連續(xù) 30 個 epoch 驗證集指標(biāo)沒有提升就提前停止這是防止時間浪費的保險絲optimizerAdamW比默認(rèn)的 SGD 收斂更快尤其適合遷移學(xué)習(xí)場景。mosaic1.0是馬賽克增強把四張圖拼成一張訓(xùn)練對小目標(biāo)檢測非常有效但如果訓(xùn)練集里單張圖只有一只狗mosaic 過強會在早期造成“半個頭”的幻覺訓(xùn)練初期 loss 可能不降反升。真遇到這種情況把mosaic0.5跑幾個 epoch后期再調(diào)到 1.0 也行。訓(xùn)練過程中重點看兩行輸出box_loss和cls_loss。box_loss 是檢測框回歸誤差cls_loss 是分類誤差。情緒識別的難點在 cls_loss 上如果訓(xùn)練了十幾輪 cls_loss 還在 1.5 以上先想到的是數(shù)據(jù)問題而不是模型問題。3.3 損失函數(shù)與訓(xùn)練曲線怎么看YOLOv8 的損失由三部分構(gòu)成分類損失BCE 變體、框回歸損失CIoU、分布式焦點損失DFL。DFL 是 YOLOv8 相對 v5 的新增項它把邊界框的四個邊當(dāng)成分布來回歸而不是直接預(yù)測數(shù)值這提升了小目標(biāo)的定位精度代價是訓(xùn)練時對學(xué)習(xí)率更敏感。我習(xí)慣每 10 個 epoch 停下來看一下results.png里的曲線。有幾個異常信號需要記住train/box_loss快速下降但val/box_loss震蕩上升這是過擬合的早期信號立即加大weight_decay或降低epochscls_loss在訓(xùn)練初期就在 0.3 以下說明類別分布嚴(yán)重不均衡模型在走捷徑優(yōu)先學(xué)容易的類別訓(xùn)練開始就出現(xiàn)nanloss幾乎可以肯定是學(xué)習(xí)率過大或某張圖的標(biāo)注框坐標(biāo)異常比如寬高為 0去檢查數(shù)據(jù)集比調(diào)參更有用。訓(xùn)練結(jié)束后在runs/detect/dog_emotion_train/目錄下會生成best.pt和last.pt后續(xù)推理用best.pt。這個目錄還包含confusion_matrix.png它比 loss 曲線更能說明問題——如果對角線很亮但某個類別的列全黑那就是典型的長尾漏檢。4. 推理與部署從單張圖片到實時攝像頭識別4.1 單圖推理腳本訓(xùn)練完模型后的第一件事是用它跑幾張訓(xùn)練集之外的圖片驗證基本效果。下面這段腳本可以直接復(fù)制使用。# inference_image.py from ultralytics import YOLO model YOLO(runs/detect/dog_emotion_train/weights/best.pt) results model.predict( sourcetest_images, conf0.35, iou0.45, imgsz640, saveTrue, save_txtTrue, device0 ) for r in results: boxes r.boxes if boxes is not None: for box in boxes: cls_id int(box.cls[0].item()) conf float(box.conf[0].item()) print(fclass{model.names[cls_id]} confidence{conf:.3f})conf0.35是置信度閾值低于這個值的檢測框會被丟棄。情緒識別的置信度普遍比普通目標(biāo)檢測低因為狗臉角度變化大設(shè) 0.35 到 0.4 是一個平衡點。iou0.45是 NMS 交并比閾值值越小抑制越強同一只狗被框兩次的場景可以調(diào)到 0.5。打印類別名和置信度有助于快速定位哪些圖片誤檢嚴(yán)重。4.2 攝像頭實時檢測課程設(shè)計答辯現(xiàn)場用攝像頭實時演示效果遠(yuǎn)比靜態(tài)圖片震撼。這里給一個接 OpenCV 的實時推理版本。# inference_webcam.py import cv2 from ultralytics import YOLO model YOLO(runs/detect/dog_emotion_train/weights/best.pt) cap cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) while True: ret, frame cap.read() if not ret: break results model.predict(frame, imgsz640, conf0.4, device0, verboseFalse) annotated_frame results[0].plot() fps cap.get(cv2.CAP_PROP_FPS) cv2.putText(annotated_frame, fFPS: {fps:.0f}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow(Dog Emotion Recognition, annotated_frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()實時推理時我把imgsz從 640 降到 416這不是為了精度而是為了幀率。攝像頭場景下運動模糊已經(jīng)讓細(xì)小情緒特征不可靠640 的輸入會拖慢推理速度反而導(dǎo)致畫面卡頓。這里有個隱藏問題results[0].plot()會在原圖上繪制檢測框和標(biāo)簽但如果檢測到多個框且類別置信度不高畫面上的字會非常多答辯時反而顯得 demo 雜亂可以只在畫面上畫置信度高于 0.5 的框。4.3 模型導(dǎo)出與邊緣部署訓(xùn)練好的 PyTorch 權(quán)重不能直接跑在手機上或者 Jetson 這類邊緣設(shè)備上需要導(dǎo)出成 ONNX 或 TensorRT 格式。yolo export modelruns/detect/dog_emotion_train/weights/best.pt formatonnx imgsz640 opset12 yolo export modelruns/detect/dog_emotion_train/weights/best.pt formatengine device0 halfTrueONNX 導(dǎo)出的關(guān)鍵是opset版本設(shè)成 12 兼容性最好新版 PyTorch 默認(rèn)的 opset 17 在部分老設(shè)備推理引擎上會報不支持的算子。TensorRT 導(dǎo)出前先確認(rèn)本機 CUDA 版本和 TensorRT 版本匹配否則引擎構(gòu)建到一半會報顯存問題。halfTrue開啟 FP16 精度推理速度提升明顯但精度有輕微損失情緒識別這個任務(wù)影響不大。如果在樹莓派或者 RK3588 這類設(shè)備上部署ONNX 格式是更穩(wěn)妥的選擇配合 RKNN-Toolkit 轉(zhuǎn)換工具可以做硬件加速。這方面的行話叫“邊緣部署監(jiān)控誤檢率高”核心原因是邊緣設(shè)備上為了性能往往會降低輸入分辨率而情緒特征恰恰依賴細(xì)節(jié)所以部署時的輸入分辨率不要小于 512。5. 常見問題與避坑訓(xùn)練不收斂、BN 崩潰與誤檢排查5.1 訓(xùn)練階段BN 崩潰、過擬合與損失異常現(xiàn)象一訓(xùn)練到第 20 個 epoch 左右loss 突然變成nan控制臺開始刷紅色警告模型權(quán)重?zé)o法保存。這大概率是訓(xùn)練中 BN 崩潰BatchNorm blowup。產(chǎn)生原因通常是學(xué)習(xí)率設(shè)置過高加上早期批次數(shù)據(jù)里某些標(biāo)注框異常導(dǎo)致某一層的統(tǒng)計量爆炸。解決方法是先把lr0降到 0.0005同時把batch設(shè)成 8 或 16 的倍數(shù)確保每個批次里的樣本數(shù)足夠讓 BN 統(tǒng)計量穩(wěn)定。另一個常見做法是在yolo train命令里加cacheTrue把數(shù)據(jù)緩存到內(nèi)存減少讀取抖動帶來的輸入異?!,F(xiàn)象二訓(xùn)練集精度升到 95% 以上驗證集 mAP 卻只有 50%而且還在往下掉。這是典型的過擬合在小數(shù)據(jù)集上非常普遍尤其是清洗后圖片數(shù)少于 800 張時。對策不止一個我建議按順序操作先加weight_decay0.0005再把mosaic關(guān)掉或降到 0.3然后嘗試用yolov8s-cls.pt的分類預(yù)訓(xùn)練權(quán)重做遷移初始化。注意這不是玄學(xué)是超參數(shù)和數(shù)據(jù)規(guī)模不匹配的必然結(jié)果。現(xiàn)象三val/cls_loss曲線一路平坦怎么調(diào)參都下不去。先檢查你的data.yaml里類別順序是否和訓(xùn)練標(biāo)簽的 class_id 對應(yīng)。我見過不止一次因為 CLASSES 列表順序變了導(dǎo)致模型把“開心”學(xué)成了“焦慮”的慘案。模型沒毛病是標(biāo)簽語義對不上。5.2 推理階段誤檢、漏檢與混淆矩陣異?,F(xiàn)象四視頻里對著墻壁或地板也會框出一個小方框置信度還不低打上了某個情緒類別。原因是背景過擬合。如果訓(xùn)練集里大量圖片的背景都是室內(nèi)地板或狗窩模型會把紋理特征當(dāng)成判斷依據(jù)。解決方式是做數(shù)據(jù)增強加hsv_h0.5 hsv_s0.5 hsv_v0.5隨機改變色調(diào)飽和度降低顏色紋理對分類的依賴再用translate0.1讓目標(biāo)在畫面里移動破壞固定的位置關(guān)聯(lián)。推理時把conf調(diào)高到 0.5 也能過濾一部分背景誤檢?,F(xiàn)象五confusion_matrix.png里所有類別的橫排總和明顯大于縱排總和甚至出現(xiàn)奇怪的對角線。搜過“YOLO 混淆矩陣總合不唯一”的應(yīng)該都知道目標(biāo)檢測的混淆矩陣計算邏輯與圖像分類不同它按預(yù)測框是否與真實框匹配來計數(shù)一個真實框可能被多個預(yù)測框命中一個預(yù)測框也可能對應(yīng)多個類別得分??椿煜仃嚂r不要追求行和列相等重點看每個類別是否在對角線上有足夠高的值。某一行除對角格外還有高響應(yīng)說明模型在類別間混淆優(yōu)先補區(qū)分這兩個類別的數(shù)據(jù)比調(diào)參更有效。6. 進(jìn)階注意力機制改進(jìn)與 TensorBoard 驗證習(xí)慣6.1 給 YOLOv8 加一個輕量注意力模塊如果完成基礎(chǔ)版本之后還有余力給模型加一個 SESqueeze-and-Excitation注意力模塊是性價比很高的改進(jìn)方向。犬類情緒識別依賴的耳朵位置、嘴角弧度這些細(xì)小特征注意力機制能讓特征提取網(wǎng)絡(luò)更關(guān)注這些區(qū)域同時計算開銷非常小。# common.py 中添加的 SE 模塊 import torch import torch.nn as nn class SEBlock(nn.Module): def __init__(self, channels, reduction16): super(SEBlock, self).__init__() self.avg_pool nn.AdaptiveAvgPool2d(1) self.fc nn.Sequential( nn.Linear(channels, channels // reduction, biasFalse), nn.ReLU(inplaceTrue), nn.Linear(channels // reduction, channels, biasFalse), nn.Sigmoid() ) def forward(self, x): b, c, _, _ x.size() y self.avg_pool(x).view(b, c) y self.fc(y).view(b, c, 1, 1) return x * y.expand_as(x)這個模塊通過全局平均池化把每個通道壓縮成一個值再用兩層全連接學(xué)習(xí)通道間的關(guān)系最后用 Sigmoid 產(chǎn)生 0 到 1 的通道權(quán)重乘回原特征圖。reduction16控制中間層壓縮比值越大參數(shù)越少但信息損失也越多。修改完模型結(jié)構(gòu)后訓(xùn)練命令不變只是在yaml配置里替換對應(yīng)層的模塊名。6.2 用 TensorBoard 對比改進(jìn)前后的訓(xùn)練曲線改進(jìn)是否有效不能靠感覺。ultralytics 框架自帶 TensorBoard 支持但需要先安裝依賴再啟用。pip install tensorboard tensorboard --logdir runs/detect打開http://localhost:6006就能同時看到基線模型和注意力改進(jìn)模型的 loss 曲線。我通常會對比兩組指標(biāo)val/cls_loss和mAP0.5:0.95。如果加了注意力模塊后cls_loss更低但box_loss略高這是正常的注意力機制本質(zhì)上是犧牲一部分定位精度換取分類精度在情緒識別這個任務(wù)上是劃算的。對比訓(xùn)練時還有個習(xí)慣值得養(yǎng)成用固定的random_seed42讓兩次訓(xùn)練的數(shù)據(jù)增強順序一致。如果不固定種子兩次訓(xùn)練的提升可能是隨機性造成的那就失去了對比的意義。這個資源我前后拆了三遍第一遍踩在數(shù)據(jù)清洗上第二遍死在 BN 崩潰第三遍才把訓(xùn)練跑順。從那以后我每次做目標(biāo)檢測項目都會強制自己先寫一個數(shù)據(jù)分布統(tǒng)計腳本再進(jìn)訓(xùn)練環(huán)節(jié)。模型可以迭代數(shù)據(jù)問題不能靠模型硬扛。完整的標(biāo)簽轉(zhuǎn)換腳本、分層采樣代碼和訓(xùn)練配置都在資源包里希望幫到你。本文還有配套的精品資源點擊獲取