[Python / YOLOv8] Webえんじにゃ、物体検知をする④学習モデルを自作する
Webえんじにゃです
機械学習は大学時代(n>1 年前🤔)にチョトヤッタくらいのレベルです
当時とはだいぶ進化している…ので1からやっていきます
今回はPythonとYOLOv8を使って機械学習して物体検知にとりくみます
長くなるので分割して記事にしていきます
この記事は4個目です
[Python / YOLOv8] Webえんじにゃ、物体検知をする①仮想環境構築まで
[Python / YOLOv8] Webえんじにゃ、物体検知をする②YOLOv8で簡単に遊ぶ
[Python / YOLOv8] Webえんじにゃ、物体検知をする③学習の準備
[Python / YOLOv8] Webえんじにゃ、物体検知をする④学習モデルを自作する
画像ができあがったので、遂に学習させていきます
YOLOv8 の Train モードで学習後、Val モードで検証していきます
どきどきだね…(゚Д゚;)
用意するもの
おさらいです。下記が必要です
- アノテーションを施した画像フォルダ一式(images フォルダ)
- アノテーションを施した画像に対応するタグフォルダ一式(labels フォルダ)
- 検証用の画像いくつか(imagesに使ってない画像)(val フォルダとします)
これらを venv
直下に配置します(お好みで)
今回は下記として説明してきます
venv
└── datasets
├── images
├── labels
└── val
設定ファイルを作成
-
venv\Lib\site-packages\ultralytics\cfg\datasets\
の中にある、 coco8.yaml をコピーして、mydatasets.yaml ファイルを作成する(名前はお好み)
-
mydatasets.yaml (coco8.yaml)の中身を編集
ここで設定するのは大きく分けて主に2点です
- データのパスを指定する
- Classesを指定する
データのパスを指定する
coco8.yaml では下記のようになっています
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ../datasets/coco8 # dataset root dir
train: images/train # train images (relative to 'path') 4 images
val: images/val # val images (relative to 'path') 4 images
test: # test images (optional)
◆中身
- path: データの大元のパス(今回は
datasets
) - train:
path
以降の、学習用画像のフォルダ(今回はimages
) - val:
path
以降の、検証用画像のフォルダ(今回はval
) - test:
path
以降の、テスト用画像のフォルダ(オプション。今回は指定しない)
つまり、mydatasets.yaml
では下記のように設定すればよきです
path: ../datasets
train: images
val: val
Classesを指定する
coco8.yaml では下記のようになっています
# Classes
names:
0: person
1: bicycle
2: car
3: motorcycle
~略~
◆中身
今回アノテーションしたタグの種類をここで設定しています
(今回はlabels/classes.text
)
これの順番と同じように設定すればよいです
例えば classes.text が下記のように出力されている場合
fox
dog
cat
mydatasets.yaml
では下記のように設定!
names:
0: fox
1: dog
2: cat
順番注意してね🫶適当な順番で設定すると、きつねさんなのに猫さんで検知されたりするよ(1敗)
不要な設定は削除
例えば下記のような設定項目については、ネットに転がってるデータセットとかを使う場合で、ダウンロードがまだの場合は設定すると実行するだけで勝手にDLがはじまって幸せになれる
今回は無論不要です
# Download script/URL (optional)
download: https://ultralytics.com/assets/coco8.zip
こういったいらない設定はすべて消し消ししましょうね
YOLOv8 の設定を作成する
-
venv\Lib\site-packages\ultralytics\cfg\models\v8\
の中にある、 yolov8.yaml をコピーして、myyolo.yaml ファイルを作成する(名前はお好み) -
クラス数の部分だけを修正する
nc: 80 # number of classes
この部分を、mydatasets.yaml
で設定したクラス(タグの種類)の数に設定します
つまり、今回は「fox」「dog」「cat」の3種類なので
nc: 3
でOK
main.py で学習コードを作成する
サンプルコードを実行してみる
公式ドキュメントでは下記がTrainモードのサンプルコードとなっています
from ultralytics import YOLO
# Load a model
model = YOLO('yolov8n.yaml') # build a new model from YAML
model = YOLO('yolov8n.pt') # load a pretrained model (recommended for training)
model = YOLO('yolov8n.yaml').load('yolov8n.pt') # build from YAML and transfer weights
# Train the model
results = model.train(data='coco128.yaml', epochs=100, imgsz=640)
これを実行するとなんか色々ターミナルに書かれる
長いので省略
engine\trainer: task=detect, mode=train, model=yolov8n.pt, data=mydatasets.yaml, epochs=100, time=None, patience=100, batch=16, imgsz=640, save=True, save_period=-1, cache=False, device=None, workers=8, project=None, name=train4, exist_ok=False, pretrained=True, optimizer=auto, verbose=True, seed=0, deterministic=True, single_cls=False, rect=False, cos_lr=False, close_mosaic=10, resume=False, amp=True, fraction=1.0, profile=False, freeze=None, multi_scale=False, overlap_mask=True, mask_ratio=4, dropout=0.0, val=True, split=val, save_json=False, save_hybrid=False, conf=None, iou=0.7, max_det=300, half=False, dnn=False, plots=True, source=None, vid_stride=1, stream_buffer=False, visualize=False, augment=False, agnostic_nms=False, classes=None, retina_masks=False, embed=None, show=False, save_frames=False, save_txt=False, save_conf=False, save_crop=False, show_labels=True, show_conf=True, show_boxes=True, line_width=None, format=torchscript, keras=False, optimize=False, int8=False, dynamic=False, simplify=False, opset=None, workspace=4, nms=False, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=7.5, cls=0.5, dfl=1.5, pose=12.0, kobj=1.0, label_smoothing=0.0, nbs=64, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0, auto_augment=randaugment, erasing=0.4, crop_fraction=1.0, cfg=None, tracker=botsort.yaml, save_dir=runs\detect\train4
Overriding model.yaml nc=80 with nc=3
ほんで読み込みが始まります
Starting training for 100 epochs...
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
1/100 0G 1.638 3.578 2.22 19 640: 100%|██████████| 1/1 [00:04<00:00, 4.51s/it]
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 1/1 [00:00<00:00, 1.00it/s]
all 5 0 0 0 0 0
~略~
そのまま放置しておくと、.runs/detect/train
フォルダが生成されます。機械学習の結果やら色々でてきてすごい
結果はあとで見るので、とりあえずコードの中身を確認していきましょう
Load a model
model = YOLO('yolov8n.yaml')
YOLOv8 の設定を読み込みます
つまり今回はmyyolo.yaml
をここで読み込むようにします
model = YOLO('yolov8n.pt')
すでに学習済みの .pt ファイルを読み込みます
今回はデフォルトの学習ファイルを使用するのでそのままにします
model = YOLO('yolov8n.yaml').load('yolov8n.pt')
YOLOv8をロードします
上記に則り今回は YOLO('myyolo.yaml').load('yolov8n.pt')
とすればOK
Train the model
**results = model.train(data='coco128.yaml', epochs=100, imgsz=640)
**
train モードでデータを読み込む部分です
Predict モードを触ってみたときと同じく、train モードでも色々引数を設定できます
サンプルコードの場合は
①データの設定ファイルを読み込み(data='coco128.yaml'
)
②学習の精度を設定(epochs=100
)
③ターゲットの画像サイズを設定(imgsz=640
)
というかんじ
今回はとりあえず model.train(data='mydatasets.yaml', epochs=30)
とでもしておこうかな
てなわけで main.py はこうなった
from ultralytics import YOLO
# Load a model
model = YOLO('myyolo.yaml') # build a new model from YAML
model = YOLO('yolov8n.pt') # load a pretrained model (recommended for training)
YOLO('myyolo.yaml').load('yolov8n.pt')
# Train the model
results = model.train(data='mydatasets.yaml', epochs=30)
実行してみよう
実行して数分(数時間?🥺)待ち、無事に完了したことを確認しましょう
全部完了すると結果を出してくれます(下記例は100エポックですが)
100 epochs completed in 0.174 hours.
Optimizer stripped from runs\detect\train4\weights\last.pt, 6.3MB
Optimizer stripped from runs\detect\train4\weights\best.pt, 6.3MB
Validating runs\detect\train4\weights\best.pt...
Ultralytics YOLOv8.1.27 🚀 Python-3.11.0 torch-2.2.1+cpu CPU (12th Gen Intel Core(TM) i5-1235U)
Model summary (fused): 168 layers, 3006233 parameters, 0 gradients, 8.1 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 1/1 [00:00<00:00, 1.09it/s]
all 5 0 0 0 0 0
WARNING ⚠️ no labels found in detect set, can not compute metrics without labels
Speed: 20.9ms preprocess, 122.1ms inference, 0.0ms loss, 27.0ms postprocess per image
Results saved to runs\detect\train4
何分かかったよーとか、
weights フォルダの中に last.pt、best.pt を出力したよーとか、
結果は runs\detect\train4 に出したよーとか いろいろ書いてありますね🤔
というわけで、結果何が出力されたのか見てみましょう
結果何が生み出されたのか
last.pt / best.pt
これ、誰?と思いますよね??私は思いました
.pt ファイル……🤔?って、どこかで見ませんでしたか?('ω')
そう、学習済みモデルのファイル ですね
main.py にて YOLO('yolov8n.pt')
で指定したと思います
これこれ
つまり、俺流の学習モデルがこの子たち、ということですね。わが子ですよ。無事出産できました
では、これらの違いは何でしょう?
公式を引用してみると
weights/
This directory contains the saved PyTorch models for the last and the best
iterations during the hyperparameter tuning process.last.pt: The last.pt are the weights from the last epoch of training.
best.pt: The best.pt weights for the iteration that achieved the best fitness score.
つまりどういうことだってばよ?
last.pt
学習の最後に保存されたモデル(の重み)のこと
例えば追加で学習したい場合など、学習を継続する場合はこっちを使用するとよいよ
best.pt
学習中に最も性能が高かったモデル(の重み)のこと
つまり、今回の学習では一番精度がよかった部分を保存してくれています
実際に predict モードで自作モデルとして使うのは best をよく使うよ
その他
もう少し詳しく結果を見たい場合はその他のファイルもみていくといいでしょう
train フォルダ直下に様々な曲線ができてると思います
例えばこんなやつとか(P_curve.png)
これは精度曲線で、閾値が変化したときに精度がどのくらい変化するかを示したものです
こまかく精度とか比較してゴリゴリ学習をさせていきたい場合は参考にするのかな?
ビジュアル出力、というやーつらしいです
というわけで自作モデルで predict
②で触ったサンプルコードで、モデルの読み込み先を変更してみます
from ultralytics import YOLO
if __name__ == '__main__':
# Load a model
model = YOLO('runs/detect/train/weights/best.pt')
# Predict the model
model.predict('sample.jpg', save=True, conf=0.5)
これで、イイカンジの結果が得られれば学習成功!わーいだドン!
今回はここまで
業務に大体おいついたので次回は未定です
Discussion