如何使用自己的資料集訓練 YOLOX

張家銘
12 min readSep 4, 2021

--

在 2021 年 7 月時曠世科技在 YOLOv3 和 YOLOv5 的基礎下推出了 YOLOX,跟之前的 YOLO 系列最大的不同點就是在 Detection Head 的地方將 Coupled Head 換成 Decoupled Head,簡單來說就是把 Class, Bounding Box, Objectness 切成不同分支來訓練,架構如 圖一 所示:

圖一,Decoupled Head 架構

另外在 label 分配 anchor 並計算 loss 採用了 SimOTA 方法,有興趣可以去看這篇論文:https://arxiv.org/abs/2103.14259

YOLOX 有許多網路架構可以應用在不同場景上,可以分成三大類:

  • 基於 YOLOv3 修改後得到的架構:

YOLOX-Darknet53

  • 基於 YOLOv5 修改後得到的架構:

YOLOX-s, YOLOX-m, YOLOX-l, YOLOX-x

  • 輕量化的架構:

YOLOX-Nano, YOLOX-Tiny

這邊附上各種架構在 coco 資料集上的 mAP

標準的模型:

輕量化的模型:

牛刀小試

Installation

1.安裝 YOLOX

$ git clone https://github.com/Megvii-BaseDetection/YOLOX.git
$ cd YOLOX
$ pip install -U pip && pip install -r requirements.txt
$ pip install -v -e . # or python setup.py develop

2.安裝 pycocotools

$ pip install cython; pip install 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'

Demo

1.下載預訓練模型,這邊用 YOLOX-s 來 demo

$ wget https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_s.pth

更多 weight 檔可以在 官方 github 下載

2.預測

$ python tools/demo.py image -f exps/default/yolox_s.py -c yolox_s.pth --path assets/dog.jpg --conf 0.25 --nms 0.45 --tsize 640 --save_result --device [gpu]

預測結果如 圖二 所示。

  • -f 後面放參數設定的檔案,這邊使用官方的預設參數 exps/default/yolox_s.py
  • -c 後面放預測時使用的 weight 檔,這邊使用官方的預訓練模型 yolox_s.pth
  • --path 後面放你要預測的圖片路徑,也可以放想要預測的資料夾路徑,這邊使用官方提供的照片 assets/dog.jpg
  • --conf 後面放 confidence 的 threshold,這邊使用 0.25
  • --nms 後面放非極大值抑制 (Non-Maximum Suppression) 的 threshold,這邊使用 0.45
  • --tsize 後面放你要將影像 resize 成多大丟進模型裡預測,這邊使用 640
  • --save_result 如果要將預測結果存下來可以加這個
  • --device 要用什麼 device 預測,可選 cpu 或 gpu,這邊使用 gpu
圖二,使用預訓練模型的預測結果

訓練自己的資料集

1.標記資料

可以先使用 label 工具來進行 label,推薦使用 labelimg

  • windows 用戶:可以直接去下載編譯好的版本 labelimg
  • mac 用戶:使用 pip install labelimg 安裝,再用 labelimg 指令打開程式

使用 Open Dir 讀進自己的資料集,label 完後存成 PascalVOC 格式方便做之後的處理

存成 PascalVOC 格式可以得到對應的 xml 檔案

2.訓練YOLOX

  • 官方提供兩種訓練格式 COCO 格式和 VOC格式,我推薦使用 COCO 格式去訓練,不用改太多東西!

COCO 格式訓練(推薦使用)

1.快速體驗

可以先試試看能不能訓練這個簡單的範例,如果能訓練就代表環境安裝都沒有問題。

(1) 下載 mini-coco128

# 安裝 gdown 並下載 mini-coco128
$ pip install gdown
$ gdown --id 16N3u36ycNd70m23IM7vMuRQXejAJY9Fs
# 解壓縮
$ unzip coco128.zip

解壓縮後就可以得到指定的樹狀資料結構

(2) 開始訓練

# 下載預訓練權重
$ wget https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_s.pth
# 開始訓練
$ python tools/train.py -f exps/example/custom/yolox_s.py -d 8 -b 64 --fp16 -o -c yolox_s.pth

(3) 進行測試

$ python tools/demo.py image -f exps/example/custom/yolox_s.py -c YOLOX_outputs/coco128/best_ckpt.pth --path car.jpg --conf 0.25 --nms 0.5 --tsize 640 --save_result --device [gpu]

2.使用自己 label 好的 xml 檔訓練 COCO 格式

(1) 將標記好的資料轉換成 YOLOX 的 COCO 訓練格式

將標記好的資料放在 YOLOX/datasets/data 裡,裡面要包含訓練的影像 (jpg) 和對應的標註 (xml),接著我們使用 train_val_data_split_coco.py 來生成對應的資料夾結構和切分資料集,這邊設置的比例為 9:1,大家也可自行調整

$ cd YOLOX/datasets
$ wget https://raw.githubusercontent.com/d246810g2000/YOLOX/main/datasets/train_val_data_split_coco.py
$ python train_val_data_split_coco.py

執行完後會得到指定的資料夾結構和對應的 instances_train2017.json 和 instances_val2017.json 檔

  • annotations 放對應的 instances_train2017.json 和 instances_val2017.json 檔
  • train2017 放訓練集影像
  • val2017 放驗證集影像

(2) 修改訓練參數

在 YOLOX/exps/example/custom/yolox_s.py 中,修改資料夾路徑 self.data_dir 和類別數量 self.num_classes

在 YOLOX/yolox/data/datasets/coco_classes.py 中的類別改成自己對應的類別,例如這邊我改成 car

(3) 開始訓練

# 下載預訓練權重
$ wget https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_s.pth
# 開始訓練
$ python tools/train.py -f exps/example/custom/yolox_s.py -d 0 -b 4 --fp16 -o -c yolox_s.pth

訓練好的檔案和訓練歷史紀錄都在 YOLOX/YOLOX_outputs/yolox_s 裡面

(4) 進行測試

$ python tools/demo.py image -f exps/example/custom/yolox_s.py -c YOLOX_outputs/yolox_s/best_ckpt.pth --path datasets/data/car1.jpg --conf 0.25 --nms 0.5 --tsize 640 --save_result --device [gpu]

這邊的範例是 YOLOX-s,如果想用較大一點的網路架構進而得到較高的準確率可以自行修改 exps/example/custom/yolox_s.py 裡面的 self.depth 和 self.width,對應的 depth 和 width 如下表所示:

VOC 格式訓練(較不推薦,要改很多東西)

1.將標記好的資料轉換成 YOLOX 的 VOC 訓練格式

將標記好的資料放在 YOLOX/datasets/data 裡,裡面要包含訓練的影像 (jpg) 和對應的標註 (xml),還有類別資訊 (class_names.txt),接著我們使用 train_val_data_split_voc.py 來生成對應的資料夾結構和切分資料集,這邊設置的比例為 9:1,大家也可自行調整

$ cd YOLOX/datasets
$ wget https://raw.githubusercontent.com/d246810g2000/YOLOX/main/datasets/train_val_data_split_voc.py
$ python train_val_data_split_voc.py

執行完後會生成指定的資料夾結構和對應的 train.txt 和 val.txt 檔案

  • Annotations 放標記好的 xml 檔
  • JPEGImages 放資料集的影像
  • ImageSets/Main 放對應的 train.txt 和 val.txt 檔

2.修改訓練參數

(1) 修改類別

在 YOLOX/yolox/data/datasets/voc_classes.py 中的類別改成自己對應的類別,例如這邊我改成 car

(2) 修改 year 資訊

在 YOLOX/yolox/data/datasets/voc.py 中因為自己的資料集沒有 year 的資訊,所以程式裡有用到 year 的都需要更改

  • _get_voc_results_file_template
  • _do_python_eval

(3) 修改 yolox_voc_s.py

在 YOLOX/exps/example/yolox_voc/yolox_voc_s.py 中修改以下地方

  • self.num_classes = 20 -> self.num_classes = 1
  • get_data_loader 的 train 路徑
  • get_eval_loader 的 val 路徑

3.開始訓練

# 下載預訓練權重
$ wget https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_s.pth
# 開始訓練
$ python3 tools/train.py -f exps/example/yolox_voc/yolox_voc_s.py -d 0 -b 64 -c yolox_s.pth

4.進行測試

$ python tools/demo.py image -f exps/example/yolox_voc/yolox_voc_s.py -c YOLOX_outputs/yolox_voc_s/best_ckpt.pth --path datasets/data/car1.jpg --conf 0.25 --nms 0.5 --tsize 640 --save_result --device [gpu]

Reference

https://github.com/Megvii-BaseDetection/YOLOX

https://zhuanlan.zhihu.com/p/397499216

--

--