【物体検出】keras−yolo3の学習方法

【物体検出】keras-yolo3の学習方法

こんばんはエンジニアの眠れない夜です。

前回はkeras−yolo3の使い方をご紹介しました。

【物体検出】keras−yolo3の使い方

まだ読んでいない方は先にkeras-yolo3の使い方を読んでkeras-yolo3を動くようにしてからこの先を読み進めるとスムーズにkeras-yolo3の学習を始められます。

物体検出ってこんなに簡単にできるの!?ってなります。機械学習がとっても身近なものに感じられるようになります。

keras−yolo3の学習の流れ

  1. sleepless-se/keras-yolo3 をクローン
  2. 教師画像をダウンロード
  3. 教師画像をリサイズ
  4. VOTTでアノテーションを作成
  5. アノテーションファイルをYOLO用に変換
  6. YOLO学習開始

結構ステップが多くて大変そう(;´Д`)

と、感じますがそこはディープラーニング仕方ないですね(^_^;)

sleepless-se/keras-yolo3をクローン

keras−yolo3の学習が行いやすいようにオリジナルのkeras-yolo3に手を加えたものを公開しました。

こちらからクローンしてください。

git clone https://github.com/sleepless-se/keras-yolo3.git

※ 前回作成したkeras-yoloがすでにワーキングディレクトリにある場合はフォルダ名をkeras-yolo3-originなどに変更しておくといいでしょう。

教師画像をダウンロード

物体検出をしたい画像を集める必要があります。

分量は各ラベル(対象)ごとに500は必要。1000枚くらいあるといいと書いている記事が多いです。

たくさん画像を集めてくるのは大変ですが、機械学習の画像収集ならiCrawlerを使うと1回の実行で100枚の画像を集められるので楽ができます。

機械学習の画像集めはiCrawlerがおすすめ!

今回はお試しなので、各クラス(ラベル)ごとに20枚程度で大丈夫です。

あまりたくさんあると大変です。そして動かなかった時に涙します。

精度は出ませんが、今回は学習ができるかを確認することが目的です。

教師画像をリサイズ

一通り画像のダウンロードができたらkeras-yolo3のimage直下に画像を全て移動させます。

物体検出用教師データ(画像)

keras-yolo3ディレクトリで下記のコードを実行します。

python resize_images.py

このコードを実行するとimagesに保存されている画像ファイルのアスペクト比を維持しながら 320px × 320px の画像にリサイズします。画像が正方形ではない場合は白で背景が塗り足されます。

※ このコードは私が追加したものなのでオリジナルのkeras-yolo3には入っていないので気をつけてください。

教師画像のサイズは32pxの倍数である必要があるので320pxに設定しています。32の倍数であれば128pxや352pxなどでも大丈夫です。

あまり画像が大きすぎると学習時にメモリに乗り切らずクラッシュするため小さめのサイズが無難です。

リサイズ時の大きさを変更したい場合は第一引数でサイズを指定してください。

python resize_images.py 128

また、今回はデフォルトでimagesフォルダの画像をリサイズしてresize_imageに保存されるようになっていますが33行目辺りで設定可能です。

images_dir = 'images/'  # 適宜変更
image_save_dir = 'resize_image/'  # 適宜変更

PNGファイルの場合UserWarning: Palette images with Transparency expressed in bytes should be converted to RGBA images ' expressed in bytes should be converted ' +とエラーが出ることがありますが無視して大丈夫です。

アノテーションツールVOTT

画像のここに対象物がありますよ。と伝えることをアノテーションといいます。

このアノテーションを作成するアプリはたくさんあるのですが、個人的にはVOTTというアプリケーションがおすすめです。

理由は

  • Windows・Mac・Linuxで使える
  • 書き出せるアノテーションファイルの形式が豊富
  • 事前に学習したモデルに予測をさせてアノテーションができる

VoTTの使い方は別の記事にまとめたのでこちらをご覧ください。

※ アノテーションファイルを書き出すときのフォーマットはPascal VOCを使います。

【物体検出】アノテーションツールVoTTの使い方

アノテーションファイルをYOLOv3形式にあわせる

上記の記事を参考にPascal VOCでアノテーションファイルを書き出すと、resize_imageの中にxxx-PascalVOC-exportというフォルダが作成されます。

VOTT書き出し

この中のフォルダとファイルをkeras-yolo3/VOCDevkit/VOC2007に移動させます。

VOTT書き出し

※ ここで移動しているのは書き出されたファイルとフォルダだけなのでアノテーションを設定した元のファイルは影響を受けないというVOTTの親切設計です。

train.txt、test.txt、val.txt を作成

学習を実行するにはtrain.txt、test.txt、val.txtの3つのファイルが必要です。

下記のコマンドを実行すると3つのファイルが作成されます。

python make_train_files.py

このスクリプトは

書き出された学習用のアノテーションファイルをそれぞれ、train.txtval.txtにまとめて

val.txtの中身をシャッフルして、3割ほどtest.txtに移動させて保存しています。

※ sleepless-se/keras-yolo3で追加したファイルです。オリジナルのkeras-yolo3にはありません。

作成されたファイルはkeras-yolo3/VOCDevkit/VOC2007/ImageSets/Mainから確認できます。

  • `ラベル名_train.txt`
  • `ラベル名_val.txt`

というファイルがVoTTによって作成されたファイルです。

物体検出用アノテーションフィル

画像ではラベルをitemだけだったので _train _val は1つずつしか作成されていません。

複数ラベル設定した場合はラベルの数だけ作成されます。

スクリプトを実行して作成されたのがこちらの3つのファイルです。

物体検出用教師データYOLO

val.txttest.txtに分ける理由が気になる方はこちらが参考になります。

YOLOの学習用に変換

VOTTで書き出したアノテーションはそのままではYOLOの学習には使えないのでvoc_annotation.pyでYOLOの学習用に変換します。

keras-yolo3直下にあるvoc_annotation.pyの6行目あたりのclassesのリストも自分で学習させる内容に合わせて修正します。

今回は1クラス(ラベル)なので

classes = ["item"]

としました。適宜自分のクラス(ラベル)に合わせて設定してください。

python voc_annotation.py

でYOLOの学習用に変換されます。

※ ファイルの編集をしなくてもこちらも引数でクラスを指定できるようにしました。複数入力可能です。下記の例ではitemのみを追加しています。

python voc_annotation.py item

※ sleepless-se/keras-yolo3ではVOTT→YOLO v3の変換を行うようにオリジナルの voc_annotation.pyに変更を加えています。

変換されたファイルはkeras-yolo3直下にあるmodel_dataに保存されます。

本番用YOLO学習データ

YOLO学習開始

models_dataの中にあるvoc_classes.txtにクラス(ラベル)を列挙する必要があるのですが、これも先程のvoc_annotation.pyで自動で作成するようにしています。学習用にクラスを列挙初期値はデフォルトのモデルで使われているクラスが列挙されています。

今回はitemだけなので上記の画像のようになります。

train.pyの編集

画像のサイズを320pxで進めてきましたが、他のサイズに変換している方は25行目辺りの下記のコードを修正してください。

input_shape = (320,320) # multiple of 32, hw
もしくは、第1引数でサイズを渡してください。

先ほど作成した学習用データとクラス名の設定はannotation_pathclasses_pathで読み込んでいます。

def _main():
    annotation_path = 'model_data/2007_test.txt'
    log_dir = 'logs/000/'
    classes_path = 'model_data/voc_classes.txt'

学習用にweightsを変換

YOLOv3のweightsをダウンロードしてきて、変換します。
※ 変換が必要なのはもとのYOLOがKeras用ではないからだと思います。

wget https://pjreddie.com/media/files/yolov3.weights
python convert.py -w yolov3.cfg yolov3.weights model_data/yolo_weights.h5

YOLO 学習開始!

変換ができたらここまでずいぶん長い道のりでしたがいよいよ学習開始です!

下記のコマンドを実行すると学習が始まります。

python train.py
※ 画像のサイズを指定する場合はこのようにします。
python train.py 128

初めの1分ほどでエラーが出なければ設定に問題はありません。

これまでの作業で設定を間違えているとエラーが出ます。

※ 私はここで数時間、四苦八苦しました(;´Д`)

教師データの量とスペックによりますが、CPU環境で問題なければ1日くらい待てば学習が終了します。

壊滅的な遅さですね(゜o゜;

メモリ不足だと学習の途中で落ちます。私は12時間学習させたところで落ちたことがあります…( TДT)  MacBook Pro メモリ16GB

train.pyの57行目辺りのバッチサイズを32以下の2の倍数にすると一度に消費するメモリが少なくなるので落ちなくなります。

batch_size = 32

※ 他のブログを読んでいると8に設定してうまくいっている人が多いようです。

バッチサイズは第二引数で指定できるようにしています。

python train.py 320 8

KeyError: ‘val_loss’が出た時は?

Epoch 1/50
1/1 [==============================] - 4s 4s/step - loss: 1133.3969
Epoch 2/50
1/1 [==============================] - 2s 2s/step - loss: 1034.1313
Epoch 3/50
1/1 [==============================] - 2s 2s/step - loss: 934.3787
Traceback (most recent call last):
File "train.py", line 195, in
_main()
File "train.py", line 70, in _main
callbacks=[logging, checkpoint])
File "/Users/main/.pyenv/versions/3.7.3/lib/python3.7/site-packages/keras/legacy/interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "/Users/main/.pyenv/versions/3.7.3/lib/python3.7/site-packages/keras/engine/training.py", line 1418, in fit_generator
initial_epoch=initial_epoch)
File "/Users/main/.pyenv/versions/3.7.3/lib/python3.7/site-packages/keras/engine/training_generator.py", line 251, in fit_generator
callbacks.on_epoch_end(epoch, epoch_logs)
File "/Users/main/.pyenv/versions/3.7.3/lib/python3.7/site-packages/keras/callbacks.py", line 79, in on_epoch_end
callback.on_epoch_end(epoch, logs)
File "/Users/main/.pyenv/versions/3.7.3/lib/python3.7/site-packages/keras/callbacks.py", line 429, in on_epoch_end
filepath = self.filepath.format(epoch=epoch + 1, **logs)
KeyError: 'val_loss'

KeyError:'val_loss'とエラーが出た時はkeras-yolo3/model_data/2007_test.txtのテストファイルに含まれるファイル(行)が10個以下の場合です。

動作確認のために動かすだけなら2007_test.txt内の行をコピペで10行に増やすだけで大丈夫です。

KeyError: 'val_loss'の解決方法

学習結果に影響が出るので本番ではこういうことは絶対にしてはいけませんが、本番の場合はテスト用のデータが10件に満たないということはそもそも無いのでこういったエラーは出ません。

学習済みのモデルを実行

学習済みのモデルはkeras-yolo3/logs/000/に保存されいるtrained_weights_final.h5を使います。

物体検出独自学習済みモデル

※ 学習中にベストスコアが出たタイミングでもep075-loss10.849-val_loss10.981.h5等のファイル名で保存されています。

sleepless-se/keras-yolo3ではすぐに学習済みのモデルが使えるようにyolo.pyの24行目辺りのmodel_pathを下記のように変更しています。

"model_path": 'logs/000/trained_weights_final.h5',

 

画像のサイズを変更している人は29行目辺りの画像のサイズ設定を行います。

"model_image_size" : (320, 320),

後は画像や動画を入れて実行するだけです。

画像の場合は

python yolo_video.py --image

の後に画像のファイル名を入力でしたね。

教師データが少ないので精度は程々ですが、悪くないです。

YOLO物体検出結果

動画の場合は

python yolo_video.py --input ファイル名.mp4

でしたね。

この辺り、詳しくは前回の記事を参照してください。

【物体検出】keras−yolo3の使い方

まとめ:YOLOで物体検出学習させる手順

長かったですね( TДT)お疲れ様です!

うまく独自モデルの学習はできましたか?

アノテーションファイルの作成を適当にしても結構ステップがあって大変でしたよね。

もう一度、全体の流れをおさらいするとこんな感じです。

  1. sleepless-se/keras-yolo3 をクローン
  2. 教師画像をダウンロード
  3. 教師画像をリサイズ(python resize_images.py)
  4. VOTTでアノテーションを作成
  5. アノテーションファイルをYOLO用に変換(python voc_annotation.py)
  6. YOLO学習開始(python train.py)

学習させるまでのステップが多いので途中でミスってハマるポイントがいろいろありそうです。

そして、何よりCPU環境なら日が暮れて、登ってもまだ終わりません…

時々落ちるという悪夢も…(笑)

私の希望としては

「アノテーションさえしっかりやっていれば誰でも物体検出ができるよ!」

というところまで持っていきたいです。

最後に一言

この記事を書いた動機は

「物体検出が誰でもできるようになると世の中がもっと便利になる事いっぱいあるよね!」っと思ったからです。

今回のサンプルはitemでしたが対象が変わって、見る人が見ればガンの発見なんかもこれでできるようになります。

その他には

  • 農作物の選果
  • 万引き検知
  • 防犯カメラへの応用
  • 害獣の検知
  • 交通調査
  • 自動運転
  • etc…

横展開するだけでいろんな可能性があるこの技術が

「誰でも使えて、いろんな問題に適応できるて、世界がもっと便利になればいいな(๑´ڡ`๑)」

という思いです。

この記事を読んでくださった方も独自のモデルを使っていろんな問題解決にチャレンジしてみてくださいね(^^)v

今回作成したモデルはこちらの方法で簡単にAPI化してどこからでもアクセスできるようにできます。

【物体検出】1行で学習済みのYOLO独自モデルをAPI化する方法

次回は無料でGPU環境が使えるGoogleColaboを使って短時間で学習させる方法を紹介します。

今回紹介した方法がうまくいかない(>_<)!!CPUだとおそすぎて話にならない!というかたはこちらの方法をお試しください。

【物体検出】(GPU版)YOLO独自モデル簡単作成方法

8 Comments

nagamatsu

train.pyで独自データの学習を試みたところ、

filepath = self.filepath.format(epoch=epoch + 1, **logs)
KeyError: ‘val_loss’

とエラーが出るのですが、どこが問題なのでしょうか?

返信する
sleepless-se sleepless-se

そのエラーメッセージだけでは原因を特定できませんでした。
エラーメッセージの全文をいただけますか?

返信する
katsuno

同じようなエラーが発生してしまいました。
エラー全文です。

Traceback (most recent call last):
File “train.py”, line 195, in
_main()
File “train.py”, line 70, in _main
callbacks=[logging, checkpoint])
File “C:\Users\katsuno\Anaconda3\envs\py36\lib\site-packages\keras\legacy\interfaces.py”, line 91, in wrapper
return func(*args, **kwargs)
File “C:\Users\katsuno\Anaconda3\envs\py36\lib\site-packages\keras\engine\training.py”, line 1418, in fit_generator
initial_epoch=initial_epoch)
File “C:\Users\katsuno\Anaconda3\envs\py36\lib\site-packages\keras\engine\training_generator.py”, line 251, in fit_generator
callbacks.on_epoch_end(epoch, epoch_logs)
File “C:\Users\katsuno\Anaconda3\envs\py36\lib\site-packages\keras\callbacks.py”, line 79, in on_epoch_end
callback.on_epoch_end(epoch, logs)
File “C:\Users\katsuno\Anaconda3\envs\py36\lib\site-packages\keras\callbacks.py”, line 429, in on_epoch_end
filepath = self.filepath.format(epoch=epoch + 1, **logs)
KeyError: ‘val_loss’

返信する
sleepless-se sleepless-se

ありがとうございます!
同じところでエラーが出ているというのはもしかするとなにか書き忘れているか間違えているかもしれませんね…
もう一度精査します。

voc_annotation.pyの6行目あたりのclasses
models_dataの中にあるvoc_classes.txtには同じクラスが列挙されていますか?

返信する
sleepless-se sleepless-se

2007_test.txtに含まれるファイルが少ないことが原因でした。
記事を更新しましたのでそちらをご確認ください。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください