? YOLO獲取COCO指標(3):驗證(Val) 啟用 COCO API 評估(自動輸出AP指標)| 發論文必看! | Ultralytics | 小白友好
文章目錄
- 一、問題定位
- 二、原理分析
- 三、解決方案與實踐案例
- 步驟 1: 觸發 COCO JSON 保存
- 步驟 2: 確保 `self.is_coco` 條件滿足 (或理解其影響)
- 步驟 3: 確保 Ground Truth JSON 文件路徑正確
- 步驟 4: (關鍵) 調整自定義數據集的類別映射
- 步驟 5: (可選) 調整圖像 ID 處理
- 四、總結與展望
- 參考文獻:
重要說明: 本篇博客內容基于 YOLOv12 進行演示,但其核心原理和配置方法適用于所有基于 Ultralytics 框架開發的 YOLO 版本。在應用代碼修改時,請注意核對你所使用的具體 Ultralytics 庫版本中的文件路徑和代碼行號。
一、問題定位
在使用 Ultralytics YOLO 框架訓練自定義目標檢測數據集后,開發者通常希望在驗證(Validation)階段就能直接獲取業界標準的 COCO 評估指標(尤其是 mAP)。然而,直接調用 model.val()
方法,即使數據集標注已轉換為 COCO 格式,也未必能自動觸發 COCO API 進行評估并輸出結果。本文旨在解決這一問題,詳細闡述如何通過正確配置和少量代碼調整,在 model.val()
過程中無縫集成 COCO API 評估。
二、原理分析
Ultralytics YOLO 的 ultralytics/models/yolo/detect/val.py
腳本內置了使用 pycocotools
(官方 COCO API) 進行評估的邏輯。該邏輯的觸發和正確執行依賴于以下幾個關鍵條件:
- 觸發評估: 需要顯式告知
model.val()
保存預測結果為 COCO JSON 格式,這是調用 COCO API 的前提。 - 數據集識別: 腳本需要判斷當前驗證的數據集是否為“COCO 類型”,以便加載對應的 COCO 格式 Ground Truth 標注文件。這通常基于數據集配置文件 (
.yaml
) 中的路徑約定。 - 標注文件定位: 腳本需要根據約定的目錄結構找到 COCO 格式的 Ground Truth JSON 文件 (如
instances_val2017.json
)。 - 類別映射 (Class Mapping): 對于標準 COCO 數據集,代碼默認會應用一個從 COCO 80 類到 COCO 91 類的映射。對于自定義數據集,這個映射通常是不必要的,甚至是有害的。
- 圖像 ID 匹配: COCO API 評估時需要匹配預測結果和 Ground Truth 中的圖像 ID。默認實現可能假設圖像文件名是符合 COCO 規范的數字 ID。
當使用自定義數據集時,即使標注格式符合 COCO 標準,上述第 2、3、4、5 點的默認邏輯可能與用戶的實際設置或數據情況不符,導致 COCO API 評估流程中斷或出錯。
三、解決方案與實踐案例
以下步驟詳細說明了如何在調用 model.val()
時成功啟用 COCO API 評估。
步驟 1: 觸發 COCO JSON 保存
在調用 model.val()
方法時,必須將參數 save_json
設置為 True
。這會指示框架將模型的預測結果保存為 COCO 評估工具所需的 JSON 文件格式。
# --- 代碼示例:調用 model.val() 并啟用 save_json ---from ultralytics import YOLO # 導入 YOLO 類# 加載模型
model = YOLO('path/to/your/best.pt') # 模型路徑# 調用驗證方法
metrics = model.val(# ... 其他訓練參數 ...save_json=True, # 關鍵:設置為 True 以便后續調用 COCO API# ... 其他訓練參數 ...
)
步驟 2: 確保 self.is_coco
條件滿足 (或理解其影響)
在 ultralytics/models/yolo/detect/val.py
文件中,有一個 self.is_coco
標志位,它的設置決定了是否按 COCO 模式加載標注和執行評估。(注意:以下代碼路徑和行號基于文檔提供的特定版本,請參考你使用的 Ultralytics 版本)
- 代碼位置 (僅供參考,請核對你的版本):
ultralytics/models/yolo/detect/val.py
L71 附近
# --- val.py 中 is_coco 的判斷邏輯示例 (僅供理解) ---
# self.is_coco 通常基于 YAML 文件中 'val' 字段的路徑字符串判斷
# 它期望路徑中包含 "coco" 并且以特定的文件名結尾 (如 val2017.txt)
self.is_coco = (isinstance(val, str) # val 是 YAML 中 'val' 鍵對應的值and "coco" in val # 路徑字符串需包含 "coco"# 并且以 /val2017.txt 或 /test-dev2017.txt 結尾and (val.endswith(f"{os.sep}val2017.txt") or val.endswith(f"{os.sep}test-dev2017.txt"))
)
-
配置建議: 為了滿足這個條件,你需要在你的數據集配置文件 (
.yaml
) 中,將val
指向一個符合上述約定的路徑。-
示例 YAML (
PCB_COCO.yaml
) 配置:path: E:/project/YOLOv12/dataset/PCB_DATASET # 數據集根目錄 train: train.txt # 訓練集索引文件 (相對于 path) # 關鍵:val 路徑需要滿足 is_coco 的判斷邏輯 # 例如,創建一個名為 coco 的子目錄,并在其中放置 val2017.txt val: coco/val2017.txt # 驗證集索引文件 (相對于 path) test: # 測試集 (可選)names: # 你的類別名稱列表0: class_01: class_1# ...
-
文件結構建議 (對應 YAML):
E:/project/YOLOv12/dataset/PCB_DATASET/ ├── coco/ │ └── val2017.txt # 里面是驗證集圖片路徑列表 ├── train.txt └── # ... 其他文件和目錄 (如 images, labels, annotations)
-
步驟 3: 確保 Ground Truth JSON 文件路徑正確
val.py
會根據 self.data["path"]
(即 YAML 文件中的 path
) 和 self.is_coco
的狀態來構建 Ground Truth JSON 文件的預期路徑。
- 代碼位置 (僅供參考):
ultralytics/models/yolo/detect/val.py
L301 附近
# --- val.py 中 anno_json 的路徑構建邏輯示例 ---
# 如果 is_coco 為 True,則期望的 JSON 文件是 'instances_val2017.json'
# 如果是 LVIS 數據集,則是 lvis_v1_{split}.json
anno_json = (self.data["path"] # 來自 YAML 的 'path'/ "annotations" # 固定的 'annotations' 子目錄/ ("instances_val2017.json" if self.is_coco else f"lvis_v1_{self.args.split}.json")
)
- 配置建議: 確保你的 COCO 格式標注 JSON 文件(包含所有驗證集圖片的 Ground Truth)放置在
<數據集根目錄>/annotations/instances_val2017.json
。
示例路徑:E:/project/YOLOv12/dataset/PCB_DATASET/annotations/instances_val2017.json
步驟 4: (關鍵) 調整自定義數據集的類別映射
對于自定義數據集,默認的 COCO 80 到 91 類映射 (coco80_to_coco91_class()
) 是不適用的。需要注釋掉這行代碼,讓 self.class_map
使用從 1 開始的連續整數,對應你模型 names
列表中的類別。
- 代碼位置 (僅供參考):
ultralytics/models/yolo/detect/val.py
L77 附近
# --- val.py 中 class_map 的修改 ---
# 原代碼 (需要注釋掉或修改條件)
# self.class_map = converter.coco80_to_coco91_class() if self.is_coco else list(range(1, len(model.names) + 1))# 修改后:無論 is_coco 如何,都使用模型自身的類別數生成從 1 開始的映射
# (注意:COCO API 的類別 ID 通常從 1 開始)
self.class_map = list(range(1, len(model.names) + 1)) # 直接使用模型類別生成映射
- 修改說明: 這個修改確保了評估時使用的類別 ID 與你的模型和標注文件中的類別 ID 一致(假設你的 COCO JSON 中類別 ID 也是從 1 開始,如果不是,則需要相應調整這里的映射或你的 JSON 文件)。
步驟 5: (可選) 調整圖像 ID 處理
默認實現可能假設驗證集圖片的文件名是數字 (如 000000123456.jpg
),并以此作為 COCO API 評估時的圖像 ID。如果你的文件名不是這種格式,可能會導致匹配失敗。在這種情況下,需要注釋掉相關代碼。
- 代碼位置 (僅供參考):
ultralytics/models/yolo/detect/val.py
L325 附近
# --- val.py 中 imgIds 的處理 (如果需要修改) ---
# 如果你的驗證集圖片文件名不是純數字 ID (如 'img_001.jpg'),
# 下面這行代碼可能會出錯或導致 ID 不匹配,可以考慮注釋掉
# val.params.imgIds = [int(Path(x).stem) for x in self.dataloader.dataset.im_files]
- 修改說明: 注釋掉此行后,評估時可能會依賴于 COCO JSON 文件中提供的圖像 ID。確保你的
predictions.json
和instances_val2017.json
中的image_id
能夠對應上。
四、總結與展望
通過以上配置和代碼調整(主要是 save_json=True
參數,滿足 is_coco
的路徑約定,確保 anno_json
路徑正確,以及為自定義數據集修改 class_map
),你可以在 Ultralytics YOLO 的 model.val()
流程中成功啟用 COCO API,自動計算并獲取標準的 mAP 等評估指標。
關鍵要點回顧:
- 調用
model.val()
時設置save_json=True
。 - 確保數據集 YAML 文件中的
val
路徑符合is_coco
判斷約定(或理解其邏輯并適配)。 - 確保 Ground Truth COCO JSON 文件位于
path/annotations/instances_val2017.json
。 - 對于自定義數據集,務必修改
val.py
中的self.class_map
邏輯,避免錯誤的 COCO 類別映射。 - 根據需要,可能要注釋掉
val.params.imgIds
的默認生成邏輯。
參考文獻:
- Ultralytics YOLO 官方文檔:
model.val()
API 文檔: https://docs.ultralytics.com/modes/val/ (請查找對應版本的文檔)- 數據集配置 (
.yaml
) 文檔: https://docs.ultralytics.com/datasets/
- COCO Dataset 官網: https://cocodataset.org/#detection-eval (了解 COCO 評估指標定義)
pycocotools
GitHub Repository: https://github.com/cocodataset/cocoapi (COCO API 官方庫)