📢 公告:OpenCV 系列文章重構完成(75%)。專案實作篇仍在製作中,完成時間未定,敬請期待!→ 查看文章索引

Like Share Discussion Bookmark Smile

J.J. Huang   2026-04-10   Python OpenCV 07.物件偵測與辨識篇   瀏覽次數:次   DMCA.com Protection Status

Python | OpenCV YOLOv8 訓練結果分析

📚 前言

在上一篇 YOLOv8 訓練進階設定 中,我們完成了模型訓練。
這一篇介紹如何 解讀訓練結果,判斷模型是否訓練良好,以及找出需要改進的方向。

YOLOv8 在訓練結束後會自動產生大量的圖表和檔案。學會看懂這些資訊,你才能知道:

  • 模型目前表現如何?
  • 是否有過擬合?
  • 哪個類別學得不好?
  • 還需要繼續訓練還是需要補資料?

🗃️ 訓練結果目錄結構

前一篇 train_full.py 跑完後,結果儲存在 runs/detect/custom_detector/(對應 name="custom_detector")。若目錄不存在,請先確認訓練是否正常跑完。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
runs/detect/custom_detector/
├── weights/
│ ├── best.pt ← 驗證 mAP 最高的模型(用於部署)
│ ├── last.pt ← 最後一個 epoch 的模型(用於繼續訓練)
│ └── epoch*.pt ← 中間訓練過程的權重(可刪除以節省空間)
├── results.csv ← 每個 epoch 的詳細數值(loss、mAP 等)
├── results.png ← 訓練曲線圖(Loss + Metrics)
├── confusion_matrix.png ← 混淆矩陣
├── confusion_matrix_normalized.png
├── BoxPR_curve.png ← Box Precision-Recall 曲線
├── BoxF1_curve.png ← Box F1-Confidence 曲線
├── BoxP_curve.png ← Box Precision-Confidence 曲線
├── BoxR_curve.png ← Box Recall-Confidence 曲線
├── val_batch0_labels.jpg ← 驗證集真實標籤視覺化
├── val_batch0_pred.jpg ← 驗證集模型預測視覺化
├── labels.jpg ← 其他標籤圖(通常是訓練或額外視覺化)
├── train_batch0.jpg ← 訓練批次圖(可選保留)
├── train_batch1.jpg
├── train_batch2.jpg
└── args.yaml ← 本次訓練使用的所有超參數

最需要關注的三個檔案:

  • best.pt → 拿來部署的模型
  • results.png → 一眼看懂訓練趨勢
  • confusion_matrix.png → 看哪個類別容易搞錯

💡 best.pt 是部署時使用的模型,不要用 last.pt 做推論,因為最後一個 epoch 不一定是最好的。

🔎 Loss 曲線怎麼看?(results.png)

results.png 中包含三種 Loss 的訓練與驗證曲線:

Loss 名稱 說明
box_loss 邊界框座標的回歸損失,越低代表邊界框越準
cls_loss 類別分類損失,越低代表類別辨識越準
dfl_loss Distribution Focal Loss,邊界框分布損失(YOLOv8 特有)

正常的訓練曲線應該是:

  • train/box_losstrain/cls_losstrain/dfl_loss 持續穩定下降
  • val/box_lossval/cls_lossval/dfl_loss 同步下降,並趨於平穩

異常情況判斷:

現象 可能原因 解法
train loss 下降但 val loss 上升 過擬合 增加資料、提高 weight_decay、降低 epochs
train/val loss 都不下降 學習率太小或資料有問題 提高 lr0,重新確認標籤格式
Loss 震盪劇烈 學習率太大或 batch 太小 降低 lr0,增加 batch
Loss 為 NaN 標籤座標超出 0~1 範圍 重新確認標籤格式


圖:results.png 訓練曲線圖,包含各項 Loss 與 mAP 指標的每個 epoch 變化

🔎 mAP 指標怎麼看?

mAP(mean Average Precision)是物件偵測最重要的評估指標,有三個地方可以看到:

  1. 訓練時的終端機輸出:每個 epoch 結束後會印出當前的 mAP50 與 mAP50-95
  2. results.png:訓練結束後自動產生,包含完整的 mAP 曲線圖,在 runs/detect/custom_detector/
  3. results.csv:每個 epoch 的詳細數值,可用程式讀取(見本篇下方的範例)

各指標的意義:

指標 說明
mAP50 IoU 閾值 = 0.5 時的 mAP,只要邊界框重疊超過 50% 就算正確,是最常用的指標
mAP50-95 IoU 閾值從 0.5 到 0.95 的平均 mAP,要求更嚴格的邊界框定位精度,通常比 mAP50 低很多
Precision 模型預測出的框中,有多少比例是真的有物件(誤報率低)
Recall 實際存在的物件中,有多少比例被模型找到了(漏報率低)

mAP50 一般參考標準:

mAP50 範圍 評估等級
< 0.40 較差,需要大幅改善資料或標註
0.40 ~ 0.60 普通,可以接受但還有進步空間
0.60 ~ 0.75 良好
> 0.75 優秀

💡 自訂資料集的 mAP 沒有絕對標準,最重要的是「是否滿足應用需求」。例如安全監控對 Recall 要求高(不能漏報),商品辨識則對 Precision 要求高(不能誤報)。


圖:終端機輸出、results.png、results.csv,包含各項 Loss 與 mAP 指標的每個 epoch 變化

🔎 混淆矩陣怎麼看?

YOLOv8 會產生兩張混淆矩陣圖:

  • confusion_matrix.png:顯示實際的預測數量
  • confusion_matrix_normalized.png推薦查看(每個類別的預測比例,0~1)

重點看 confusion_matrix_normalized.png

  • 對角線顏色越深(接近 1.0):該類別辨識越準確
  • 非對角線有明顯顏色:模型常把 A 類別誤認為 B 類別(這就是最需要改進的地方)
  • background 那一行/列
    • 右邊的 background FP:模型誤檢(把背景當成物件)
    • 下方的 background FN:模型漏檢(沒找到實際存在的物件)

看這張圖可以快速找出「哪個類別最容易搞錯」,然後針對性地補充該類別的資料或改善標註品質。


圖:confusion_matrix_normalized.png 範例,對角線顏色越接近 1.0 代表該類別分類越準確,非對角線的顏色代表容易混淆的類別

💻 用程式讀取訓練結果

本節需要額外安裝 pandasmatplotlib

1
pip install pandas matplotlib
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# analyze_results.py
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("runs/detect/custom_detector/results.csv")
df.columns = df.columns.str.strip() # 去除欄位名稱的空白

print(df.columns.tolist()) # 查看所有欄位名稱
print(df.tail(5)) # 查看最後 5 個 epoch 的數值

# 找出最佳 epoch
best_epoch = df["metrics/mAP50(B)"].idxmax()
print(f"\n最佳 epoch:{best_epoch + 1}")
print(f"最佳 mAP50:{df['metrics/mAP50(B)'].max():.4f}")
print(f"最佳 mAP50-95:{df['metrics/mAP50-95(B)'].max():.4f}")

# 繪製 mAP 曲線
plt.figure(figsize=(10, 4))
plt.plot(df["metrics/mAP50(B)"], label="mAP50")
plt.plot(df["metrics/mAP50-95(B)"], label="mAP50-95")
plt.xlabel("Epoch")
plt.ylabel("mAP")
plt.legend()
plt.title("mAP Training Curve")
plt.savefig("mAP_curve.png")
plt.show()


圖:讀取 results.csv 找出最佳 epoch 並繪製 mAP50 與 mAP50-95 的訓練曲線圖

💻 執行驗證取得詳細報告

訓練完成後,可單獨對驗證集執行評估取得更詳細的結果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# evaluate.py
import torch
from ultralytics import YOLO
import multiprocessing # 加上這行

if __name__ == '__main__':
# 解決 Windows multiprocessing 錯誤
multiprocessing.freeze_support()

# 載入模型
model = YOLO("runs/detect/custom_detector/weights/best.pt")

# 執行驗證(強制關閉多進程,避免 Windows 問題)
metrics = model.val(
data="data.yaml",
device=0 if torch.cuda.is_available() else "cpu",
workers=0, # ← 關鍵!設成 0 比較穩定
batch=16, # 可根據你的顯卡調整(太大也會出問題)
imgsz=640, # 如果你訓練時用其他尺寸,可以指定
plots=True # 想產生 confusion_matrix 等圖片就開啟
)

# 印出指標
print(f"mAP50: {metrics.box.map50:.4f}")
print(f"mAP50-95: {metrics.box.map:.4f}")
print(f"Precision:{metrics.box.mp:.4f}")
print(f"Recall: {metrics.box.mr:.4f}")

print("\n各類別 AP50:")
for i, (name, ap) in enumerate(zip(metrics.names.values(), metrics.box.ap50)):
print(f" {name}: {ap:.4f}")


圖:載入最佳模型對驗證集執行評估,輸出 mAP50、mAP50-95、Precision、Recall 及各類別 AP50

🔎 val_batch 視覺化

val_batch0_labels.jpgval_batch0_pred.jpg 是驗證集第一批次的對照圖:

  • Labels:實際標註的邊界框
  • Pred:模型預測的邊界框

直接比較這兩張圖,能快速判斷模型的偵測品質與定位精度。

💡 本範例說明:這裡使用的標籤是以預標籤(Pre-labeling)方式自動生成,並未使用 LabelImg 逐一手動修正,因此 Labels 圖中可以看到部分標記有誤(例如邊界框位置不準或類別標錯)。這也說明了標註品質對訓練結果的影響——如果 Labels 本身就有錯,模型學到的也會是錯誤的邊界框位置,進而拉低 mAP。


圖:val_batch0_labels.jpg — 驗證集實際標註的邊界框(因使用預標籤且未手動修正,部分標記有誤)


圖:val_batch0_pred.jpg — 模型預測的邊界框,與上圖對照判斷偵測品質

⚠️ 注意事項

  • mAP 低不一定代表模型差:如果資料量少、類別困難、或標註品質差,mAP 自然偏低,先確認資料品質。
  • best.ptlast.pt 的差異best.pt 是 mAP 最高的 epoch,不一定是最後一個 epoch。建議以 best.pt 部署。
  • Early Stopping 後的 last.pt:若訓練因 Early Stopping 提早結束,last.pt 是停止時的狀態,不一定是最好的,還是要用 best.pt

🎯 結語

學會解讀訓練結果,才能有效判斷模型是否需要更多資料、更長訓練時間,或調整超參數。
下一步是 YOLOv8 推論與匯出,把訓練好的模型實際應用在圖片、影片或即時攝影機上。

📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。

註:以上參考了
Ultralytics YOLOv8 官方文件 — Val
Ultralytics YOLOv8 官方文件 — Train
Mean Average Precision — 物件偵測評估指標說明