#データセットを準備する
###データベース
・画像を用意
精度は考えずに,簡易なモデルで学習を行います.今回は全34種の牌それぞれを0°, 90°, 180°, 270°ずつ回転させた136枚の画像を用意しました.ファイル名が荒れていてごめんなさい.
・アノテーション
アノテーションは学習データにラベルを付ける作業です.Darknetには__labelImg__というアノテーションツールが付属しており,作業を効率化することができます.はじめにDarknet/labelImg/data/predifined_classes.txtにクラスを記述しておきます.
1p
2p
3p
4p
5p
6p
7p
8p
9p
1m
2m
3m
4m
5m
6m
7m
8m
9m
1s
2s
3s
4s
5s
6s
7s
8s
9s
South
North
East
West
Haku
Hatsu
Chun
以下のコマンドでlabalImgを起動.
cd darknet/labelimg
python labeling.py
Open Dirからデータベースを開き,File Listからファイルを選択します.Create RectBoxを使って対象を選択.次に対象がpredifined_classes.txt
に入力したクラスのうち,どれかを選び確定,保存します.このときアノテーション情報を格納するファイルの形式を__YOLO__(.txt)にしておきます.PascalVOC(.xml)はYOLOでは読み取れないので,注意が必要です.
このように,画像1枚にテキストファイル1つが対応することになります.最後に以下をprocess.pyとして保存.これはデータベースを学習データと教師データに分割するプログラムです.出来上がったデータベースをDarknet/data/mahjongにコピー.学習に使うデータの場所は,パス指定ファイルで指定するので任意です.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import glob, os
# Current directory
current_dir = os.path.dirname(os.path.abspath(__file__))
# Directory where the data will reside, relative to 'darknet.exe'
path_data = 'data/mahjong/'
# Percentage of images to be used for the test set
percentage_test = 10;
# Create and/or truncate train.txt and test.txt
file_train = open('train.txt', 'w')
file_test = open('test.txt', 'w')
# Populate train.txt and test.txt
counter = 1
index_test = round(100 / percentage_test)
for pathAndFilename in glob.iglob(os.path.join(current_dir, "*.jpg")):
title, ext = os.path.splitext(os.path.basename(pathAndFilename))
if counter == index_test:
counter = 1
file_test.write(path_data + title + '.jpg' + "\n")
else:
file_train.write(path_data + title + '.jpg' + "\n")
counter = counter + 1
###コンフィグファイル
ハイパーパラメータを設定します.Darknet/cfgに様々なコンフィグファイルがありますが今回はyolov2-voc.cfgを書き換えて使うことにします.
6|batch=64
7|subdivision=8
237|filters=195(計算式(classes+5)*5=195から求めています)
244|classes=34
batch
は一回の学習で使う画像の枚数で, subdivisions
でバッチで除算します(8*8グリッドで学習を行う?).GPUの性能により適当な値があるようですが,理解が出来ていない部分ですので先人たちに倣うことにします.
###クラスファイル
Darknet/cfg/obj.namesに,predefined_classes.txtと同様にクラスを記述します.
###パス指定ファイル
Darknet/cfg/obj.dataを以下のように作成します.
classes=34
train = data/mahjong/train.txt
valid = data/mahjong/test.txt
labels = cfg/obj.names
backup = backup/
trainとvalidは前述の通り,process.pyで生成される学習データと教師データを指定しています.
###重みの初期値データ
学習を収束しやすくするためのデータです.
YOLOv2とYOLOv3では使用するものが違うので注意します.
・v2の場合
darknet19_448.conv.23を以下からダウンロード.
https://pjreddie.com/media/files/darknet19_448.conv.23
・v3の場合
darknet53.conv.74を以下からダウンロード.
https://pjreddie.com/media/files/darknet53.conv.74
ダウンロードしたものをDarknet/cfgにコピーします.
###学習結果が出力される間隔を調整する
学習結果は,学習回数が1000回までは100回ごとに出力し,それ以降は10000回ごとに出力される設定となっています.GPUの性能次第では1000以降に学習結果が出力されるのが数日後,ということも十分ありえますのDarknet/examples/detector.cの138行目を,if(i%100==0 || (i < 1000 && i%100 == 0)){
とします.これにより常に100回おきに学習結果が出力されます.
#学習の準備が整いました
以下のコマンドで学習を実行します.
cd Darknet
./darknet detector train cfg/obj.data cfg/yolov2-voc.cfg cfg/darknet19_448.conv.23
成功です.書き起こしてみると淡々と進んでいますが,ここまで来るのにかなりの時間を要しました.このまま走らせて様子を見ることにします.