NvidiaのチュートリアルであるHello AI worldを日本語に翻訳しています。今回は自分でデータセットを作成し、モデルの再学習を行う方法について紹介します。
データセット作成のために画像を集める
自分自身のデータセットを作り、モデルに学習させるためには、ラベル付けされたオブジェクトや景色の画像を集める必要があります。画像を集めるにあたって、”camera-capture”というツールが提供されており、それを使うとライブ映像から画像をキャプチャし、それぞれのラベルのデータとして保存されます。
このツールは起動すると自動的に次のようなフォルダを作成します。
‣ train/
• class-A/
• class-B/
• …
‣ val/
• class-A/
• class-B/
• …
‣ test/
• class-A/
• class-B/
• …
class-A, class-B, etcというのは、自分で定義するラベル名になります。(例えば、cat, dogなど)
この名前は、この後作成するラベルの定義ファイルに含まれるクラス名と同じになります。
ツールで保存された画像は自動的にそれぞれのクラスのフォルダに保存されます。
※このフォルダ構成はPyTorchを使ってモデルの再学習を行うことが前提となっています。
ラベルファイルを作成する
まず、データセットを保存するための空のディレクトリを作成し、クラスラベルを定義するファイル(通常、labels.txtという名前が使われます。)をその中に作成します。
ラベルファイルは1行の中に一つのラベル名を含み、アルファベット順に並びます。
ラベルがアルファベット順に並んでいないと、学習用の画像データが入ったディレクトリの順番とずれ、画像認識した時に正しいラベル名が返ってこなくなります。
4つのラベル名をもつlabels.txtの例です。
n00000001 blue-ball
n00000002 red-ball
n00000003 tennis-ball
n00000004 yellow-ball
先頭のn0000000xはsynset IDと呼ばれ、Imagenet内でラベルを識別するのに使われるIDです。
このsynset IDを指定しないと正しくlabels.txtが読み込めないようです。
参考 https://github.com/dusty-nv/jetson-inference/issues/71
上の例のようなラベルファイルの場合、キャプチャツールを起動すると、次のようにディレクトリが作成されます。
‣ train/
• blue-ball/
• red-ball/
• tennis-ball/
• yellow-ball/
‣ val/
• blue-ball/
• red-ball/
• tennis-ball/
• yellow-ball/
‣ test/
• blue-ball/
• red-ball/
• tennis-ball/
• yellow-ball/
続いて、キャプチャツールのコマンドラインオプションについて説明します。
キャプチャツールの起動
キャプチャーツールは、 jetson-inference/tools/camera-capture/のディレクトリにあります。また、レポジトリの他のプログラムと同様に aarch64/bin ディレクトリでビルドされ、/usr/local/bin/下にインストールされます。
キャプチャツールは3つのコマンドラインオプションをもちます。
–camera
使用するカメラデバイスを選択します。
MIPI CSI カメラを使用する場合はセンサーインデックスを指定します。 (0 or 1, etc.)
V4L2 USB カメラを使用する場合は /dev/video ノードを指定します。 (/dev/video0, /dev/video1, ect.)
デフォルトの値は、 MIPI CSI カメラでインデックスは 0 です。(–camera=0)
–width, –height
カメラの解像度を指定します。 (デフォルトは 1280×720)
解像度はカメラに合わせた値に設定します。
カメラで使用できるフォーマットを確認するには次のコマンドを使用します。
$ sudo apt-get install v4l-utils $ v4l2-ctl --list-formats-ext
ツールを起動するときのコマンドの例を示します。
$ camera-capture # using default MIPI CSI camera (1280x720) $ camera-capture --camera=/dev/video0 # using V4L2 camera /dev/video0 (1280x720) $ camera-capture --width=640 --height=480 # using default MIPI CSI camera (640x480)
※カメラを使う例として、下記のJetson Wikiのページが参考になります。
– Nano: https://eLinux.org/Jetson_Nano#Cameras
– Xavier: https://eLinux.org/Jetson_AGX_Xavier#Ecosystem_Products_.26_Cameras
– TX1/TX2: ディベロッパーキットにオンボードの MIPI CSI センサモジュール (0V5693)が含まれています。
データを集める
画像はデータキャプチャコントロールウィンドウです。ここで、データセットのパスやクラスラベルファイルを指定することが出来ます。
そして、どのクラスの画像をキャプチャしようとしているのかを指定します。
最初に、データセットのパスとクラスのラベルファイルを開きます。するとキャプチャツールは上で述べたようなデータセット構造を作成します。
カメラを対象に向け、ドロップダウンから対称のラベルを選択、キャプチャーボタン(もしくはスペースキー)を押すと画像が取得されます。画像はクラスのサブディレクトリに保存されます。ステータスバーにはそのカテゴリで何枚の画像が保存されているかが表示されます。
モデルの学習を行う前に、最低でも各クラス、100枚の訓練用画像を用意するとよいでしょう。モデルの評価用に訓練データの10-20%の量の画像があると経験則的にいいことがわかっています。
データを集める際には、対象の角度を変えたり、カメラの視点を変えたり、照明の状態を変えたり、異なる背景でとるなどすることで、モデルはノイズや環境の変化に対してロバストになります。もし、モデルの精度がいまいちだと感じたときには訓練データを増やしてみるとよいでしょう。
モデルの学習
データを集め終わったら、モデルの学習を始めることが出来ます。モデルの学習にはPyTorchを使います。
$ cd jetson-inference/python/training/classification $ python train.py --model-dir=<YOUR-MODEL> <PATH-TO-YOUR-DATASET>
学習が終わったら、PyTorchモデルをONNXに変換します。
$ python onnx_export.py --model-dir=<YOUR-MODEL>
変換されたモデルは、 <YOUR-MODEL>/resnet18.onnx として保存されます。 これをイメージネットコンソールで呼び出すことで、学習させたモデルを使用することが出来ます。
イメージネットで使用する際の例は、
DATASET=<PATH-TO-YOUR-DATASET> # C++ imagenet-camera --model=<YOUR-MODEL>/resnet18.onnx --input_blob=input_0 --output_blob=output_0 --labels=$DATASET/labels.txt # Python imagenet-camera.py --model=<YOUR-MODEL>/resnet18.onnx --input_blob=input_0 --output_blob=output_0 --labels=$DATASET/labels.txt
まとめ
自分でモデルを作るために、画像データを集める方法、モデルに学習させる方法について紹介しました。
次は、GPIOを使って画像認識の結果に応じてデバイスを動かすなどしてみるとよいでしょう。