次世代AIライブラリ Detectron2 をカスタムデータで学習させる (Python)

AI
スポンサーリンク

スポンサーリンク

はじめに

前回の記事では、次世代AIライブラリ Detectron2 の推論方法について説明しました。

今回は、カスタムデータで学習させていきます。

前提条件

前提条件は、以下の通りです。

  • OS は Linux または、WSL2
  • Python >= 3.7 ※3.8.10を使用します。
  • PyTorch == 1.11.0+cu113 ※ バージョンを合わせる必要があります。
  • OpenCV >= 4.5 ※4.5.5を使用します。
  • CUDA-Toolkit == 11.3.1
  • Detectron2 == 0.6

CUDA と PyTorch と Detectron2 のバージョンは合わせる必要があるので、前回を参考にしてください。

学習に使用するデータについて

学習に使用するデータは、Yolov5 や、Yolact-Edge で使用したデータを使用します。
入手方法はこちらの記事を参考にしてください。
以下の画像のようにアノテーションしたデータです。

Class1_def の 1.png ~ 15.png, Class2_def の 16.png ~ 30.png を、使用していきます。
データ形式は COCO が最も簡単に学習させることができます。
COCO 形式のデータセットの作成方法はこちらの記事を参考にしてください。
images_annotation-coco フォルダをまるごとコピーして使用します。

データの準備

環境を合わせるために、フォルダとデータの配置を合わせていきます。

cd ~/detectron2-dev
mkdir detectron2-train
cd detectron2-train
touch detectron_train_COCO.py
code .

今作成した detectron2-train フォルダに images_anotation-coco もコピーしてきてください。

学習用コードの作成

detectron_train_COCO.py を以下のように作成してください。
コードは、こちらを参考にしています。

import os
import cv2
import random
from detectron2 import model_zoo
from detectron2.engine import DefaultTrainer
from detectron2.config import get_cfg
from detectron2.utils.visualizer import Visualizer
from detectron2.data import DatasetCatalog, MetadataCatalog
from detectron2.data.datasets import register_coco_instances

register_coco_instances("train", {}, "./images_annotation-coco/annotations.json", "./images_annotation-coco")
metadata = MetadataCatalog.get("train")
dataset_dicts = DatasetCatalog.get("train")

for d in random.sample(dataset_dicts, 1):
  img = cv2.imread(d["file_name"])
  visualizer = Visualizer(img[:, :, ::-1], metadata=metadata, scale=1.0)
  vis = visualizer.draw_dataset_dict(d)
  cv2.imshow("frame", vis.get_image()[:, :, ::-1])
cv2.waitKey(0) 
cv2.destroyAllWindows()

cfg = get_cfg()
cfg.OUTPUT_DIR = './output'
cfg.CUDA = 'cuda:0'

cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
cfg.DATASETS.TRAIN = ('train',)
cfg.DATASETS.TEST = ()   # no metrics implemented for this dataset
cfg.DATALOADER.NUM_WORKERS = 2
cfg.SOLVER.IMS_PER_BATCH = 2
cfg.SOLVER.BASE_LR = 0.00025
cfg.SOLVER.MAX_ITER = 500
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 128   # faster, and good enough for this toy dataset
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3

os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)
trainer = DefaultTrainer(cfg) 
trainer.resume_or_load(resume=False)
trainer.train()

コードの説明をしていきます。

register_coco_instances("train", {}, "./images_annotation-coco/annotations.json", "./images_annotation-coco")

register_coco_instances は、COCO形式の データセットを Detectron2 のデータ形式に登録することができます。たった1行でデータローダーへの変換もしてくれます。簡単すぎます。
引数は、(name, metadata, json_file, image_root) となります。
今回でいうと、

  • name=”train” 訓練用なので “train” としておきます。
  • metadata={} 空の辞書にしておき、あとで登録します。
  • json_file=”./images_annotation-coco/annotations.json”
  • image_root=”./images_annotation-coco” JPEGImages までのフォルダパスを指定します。
metadata = MetadataCatalog.get("train")
dataset_dicts = DatasetCatalog.get("train")

MetadataCatalog.get(“train”) は、先ほど登録した “train” のデータから、metadata を作成します。この metadata は、評価や可視化において非常に便利になります。

DatasetCatalog.get(“train”) は、ラベルを取得します。 0=__background__, 1=finger のように、推論結果とクラスラベルを紐づける辞書となります。

for d in random.sample(dataset_dicts, 1):
  img = cv2.imread(d["file_name"])
  visualizer = Visualizer(img[:, :, ::-1], metadata=metadata, scale=1.0)
  vis = visualizer.draw_dataset_dict(d)
  cv2.imshow("frame", vis.get_image()[:, :, ::-1])
cv2.waitKey(0) 
cv2.destroyAllWindows()

学習に使用する画像をランダムで1枚取得し、表示するプログラムです。

Visualizer(img[:, :, ::-1], metadata=metadata, scale=1.0) は、Detectron2 の Visualizer クラスを使用します。metadata は、先ほど作成した metadata を使用します。

あとは、draw_dataset_dict を使用するだけでアノテーション情報を画像に描画してくれます。
あとは、cv2.imshow() で表示するだけです。

cfg = get_cfg()
cfg.OUTPUT_DIR = './output'
cfg.CUDA = 'cuda:0'

get_cfg() は、学習や推論の設定をこのクラスですべて管理できます。
cfg.OUTPUT_DIR = ‘./output’ は、結果の出力フォルダを指定します。
cfg.CUDA = ‘cuda:0’     は、使用するデバイス (CPUとかGPUとか)を指定できます。
非常に簡単に分かりやすく設定が変更できます。

cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")

cfg.merge_from_file は、使用するインスタンスセグメンテーションの設定ファイルを読み込みます。
cfg.MODEL.WEIGHTS は、設定ファイルからネットワークの重みを読み込みます。

cfg.DATASETS.TRAIN = ('train',)
cfg.DATASETS.TEST = ()   # no metrics implemented for this dataset
cfg.DATALOADER.NUM_WORKERS = 2

cfg.DATASETS.TRAIN = (‘train’,) は “train” データセットを学習に使用するために cfg へ読み込ませます。cfg.DATASETS.TEST は検証用のデータセットを指定します。
cfg.DATALOADER.NUM_WORKERS は、データローダーの数を指定します。

cfg.SOLVER.IMS_PER_BATCH = 2
cfg.SOLVER.BASE_LR = 0.00025
cfg.SOLVER.MAX_ITER = 500

cfg.SOLVER は、学習率やイテレーションの数を指定します。ひとまず、デフォルトを指定しておきます。loss が発散するようであれば、変更してください。

cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 128   # faster, and good enough for this toy dataset
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3

cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE は デフォルトの128で大丈夫です。
cfg.MODEL.ROI_HEADS.NUM_CLASSES は、__background__を含めるので、3クラスになります。

os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)
trainer = DefaultTrainer(cfg) 
trainer.resume_or_load(resume=False)
trainer.train()

./output フォルダを作成し、DefaultTrainer に先ほど作成した cfg を渡します。
resume_or_load() は、resume=True でOUTPUT_DIR の last_checkpoint から学習を始めます。

trainer.train() で学習開始です。

学習の実行と結果の確認

早速、学習を実行します。

python3 detectron_train_COCO.py

こちらを実行すると、私の環境で約20分で学習が完了します。早いです。

出力は以下のようになります。

結果の見方は Yolact-Edge や、Yolov5 と同じです。loss に注意しておきましょう。

学習が完了すると、./output フォルダに

  • last_checkpoint  最後のモデル保存データ、resume=Trueで続けて学習に使用できる。
  • metrics.json   学習結果の確認に使用できます。
  • model_final.pth  推論に使用する weight ファイル

が作成されています。

model_final.pth を用いて推論すると以下のような出力が得られます。

カスタムデータでの推論方法については、次回の記事で説明します。

おわりに

今回は Detectron2 をカスタムデータで学習させる方法について説明しました。
色々な設定項目の説明をしましたが、数値に関してはほとんどデフォルトでも動きます。

次回はカスタムデータの推論方法について説明します。
その後は、インスタンスセグメンテーション以外の学習方法についても説明していきます。

コメント

タイトルとURLをコピーしました