AIと電子工作系ブログ

趣味でやっている電子工作とtennsorflow等を使った何かを書いていきます。

yolov5 学習方法

今回はyolov5に自前で用意した画像とラベルデータを使用して学習させます。


yolov5を導入していない方は以下を参考にしてください
soiyasoiya58.hatenablog.com


学習させる前に環境についてですが。GPUを使用することをお勧めします。
今回やる学習に関しては一人のキャラクターを認識させるだけですが、それでもちゃんと認識させるレベルの物を作るにはかなり時間がかかります。
私の環境ではGTX 1650を使用していますが、丸一日くらいかかるのでぜひGPUを使用してください。(GTX1650は性能が高いgpuではありませんがCPUよりは何倍も高速で学習できます。)
yolov5だけを導入してGPUの設定をしていない方は以下を参考にしてください。
soiyasoiya58.hatenablog.com


学習させるのに必要なデータですが、yolov5では画像と座標データの2つが必要になります。
今回使用する画像データは学以下のキャラクター(水本ゆかり)を使用します。


座標データを生成する方法はいくつかありますが私はLabelImgを使用しています。
使い方は以下サイトに書いていますので作成したことがない方は参考にしてください。
soiyasoiya58.hatenablog.com

ちなみに画像は620枚用意して学習させています。620枚といっても全ての画像に水本ゆかり(今回学習させるキャラクター)が写っているわけではありません。
620枚中260枚が水本ゆかりが写っておりそれ以外は、水本ゆかり以外のキャラクターや背景画像、真っ暗な画像なども入っています。
学習対象(水本ゆかり)のみで学習を行った場合、違うキャラクタでも水本ゆかりとして判定されてしまったり、ただの背景画像からも無理やり探し出して認識してしまう誤検知が多くなるので、
対象となる以外のデータを入れて学習させています。



本題に入ります。

まず、yolov5-6.0のフォルダを開きます。

yolov5-6.0 フォルダ内

次に学習させるためのフォルダを作成します。
学習はトレーニング用データとテスト用のデータが必要になります。
今回はトレーニング用とテスト用データは同じデータを使用しますが、フォルダは分けて生成します。
まずyolov5-6.0直下にtrainigフォルダを生成して以下のようにフォルダを追加していきます。

imagesのtrainとvalidに学習させる用の同じ画像データを入れます。
labelsのtrainとvalidにも学習させるようの同じ座標データを入れます。

images(train)の画像データ
labels(valid)内の座標データ


ここまで準備できたら、.yamlファイルを2つ作成します。
1つ目の.yamlファイルはデータがどこのパスにあるかという記述と、クラスネームの記述をします。
クラスネームというのは認識するキャラクターや物の名前を記入するだけです。
今回は以下の内容をメモ帳に書き込み保存した後、拡張子を.yamlに変更します。
クラスの数が16個になっていますが今回重要なクラス名は「yukari」のみです。
dog等関係ないクラス名は除きたかったのですが、LabelImgでクラスネームの登録を行うとなぜか登録番号が16になってしまうので関係ない15個で埋めています。

# train and val path
train: training/data/images/train/
val: training/data/images/valid/

# number of classes
nc: 16

# class names
names: ['dog','person','cat','tv','car','meatballs','marinara sauce','tomato soup','chicken noodle soup','french onion soup','chicken breast','ribs','pulled pork','hamburger','cavity','yukari']
.yamlに記述する内容

.yamlはtrainingフォルダの下に配置します。

.yamlの配置

2つ目の.yamlファイルにはパラメータを記述します。
このパラメーターはyolov5sのデータをコピーしてきてクラスの個数のみを変えているだけです。

# parameters
nc: 16  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple

# anchors
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# YOLOv5 backbone
backbone:
  # [from, number, module, args]
  -1, 1, Focus, [64, 3,  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, BottleneckCSP, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 9, BottleneckCSP, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, BottleneckCSP, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 1, SPP, [1024, [5, 9, 13]]],
   [-1, 3, BottleneckCSP, [1024, False]],  # 9
  ]

# YOLOv5 head
head:
  -1, 1, Conv, [512, 1, 1,
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, BottleneckCSP, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, BottleneckCSP, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, BottleneckCSP, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, BottleneckCSP, [1024, False]],  # 23 (P5/32-large)

   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]
2つ目の.yamlファイル


2つ目の.yamlファイルも同じtraningフォルダの下に配置します。ファイル名はyolov5s_yukari.yamlとしています。

保存場所

ここまで来たら準備は完了です。
ANACONDAを立ち上げ、yolov5用の環境でターミナル画面を開き、パスをyolov5-6.0にしてください。

次に、以下のように入力します。
今回は、img 640 batch10 epochs300でやっていますが変更しても問題はありません。
ちなみにimg640 は640*640ピクセルに変換し学習を行うことを示しており、batchは1回に何枚の画像を読み込み学習を行うかということで、epochsは学習を何回行うかということを指定します。
imgとbatchはGPUのメモリに読み込み処理するため、GPUメモリサイズが大きくないと値を大きくできません。(メモリサイズを超えるとエラーが起こります)
GPUメモリ4GBだとimg640でbatch10が限界となります。参考にしてください。

python train.py --img 640 --batch 10 --epochs 300 --data training/Dataset.yaml --cfg training/yolov5s_yukari.yaml
コマンド入力

学習がうまく開始できると下の画像のように学習の進行状況を表すバーとepochs数が出てきます。

学習中に表示される画面

学習が完了すると
yolov5-6.0\runs\trainのフォルダにexpフォルダが生成されます。
このexpフォルダ中に学習された経過データと学習データである.ptファイルが生成されます。
学習をやる回数分expフォルダは増えます。exp1、exp2、exp3....という具合に生成されるので一番大きい数字が直近で学習させたデータが入ってるフォルダになります。

expフォルダの生成場所

expフォルダの中は以下のようになっており、学習状態が把握できるような.jpgとcsvで保存されています。

expフォルダの中身


一番重要な学習データはweightsフォルダの中に入っています。
フォルダの中を見るとbest.ptとlast.ptフォルダが入っていますが、bestは一番スコアが良かったもので、lastは一番最後に学習を行った記録がされています。
今回はbest.ptを使用して学習がうまいことできているのかを確認します。

学習データ(.pt)


学習の確認

yolov5-6.0の下にtestフォルダを作成してbest.ptをtestフォルダの中に入れます。

best.ptの配置

次に確認するために試験画像を用意します。
この画像は学習に使用した画像以外を用意すると実際の性能を見れるので良いと思います。
画像データはyolov5-6.0\data\imagesの中に入れます。(yolov5を導入したときに動作確認用の画像が入っているフォルダです)

ここまできたらいよいよ判別させる動作を実行します。

python detect.py --source ./data/images/ --weights ./test/best.pt --conf 0.4

をターミナル画面に入力します。
するとimagesフォルダに入っている画像を処理し始めます。

判別後の画像は
yolov5-6.0\runs\detect\expのexpフォルダの中に入っています。このexpフォルダも生成されるたびにexp2,exp3...と数字が変わっていくので新しいフォルダの中を見てください。

判別後の画像

8枚の画像(学習用画像とは別)を使用して判別させた結果8枚中6枚水本ゆかりが写っていると判別できました。

学習回数を増やせばもっと精度を上げられます。
以上が、yolov5の1からの学習方法と学習済みモデルの確認方法でした。


最後にこれから学習をさせていく方へのアドバイスですが、
画像データ数が多ければ良いというわけではなく学習に対してクリティカルに効いてくる画像を入れるのが重要です。(データ数が多くなると学習時間も伸びます)

学習させるためのコツさえつかんでしまえば、作業する中で一番大変なのは学習させるためのデータ集めと座標データの作成です。
個人的に利用するだけならtwitter等から画像データを集めるという手もあります。twitterAPIを利用すれば1週間以内のデータなら自動で集められますので頑張ってください。