YOLOv8でカスタム分類モデルをトレーニングし、デプロイする
YOLOv8でカスタム分類モデルをトレーニングし、デプロイする
はじめに
このガイドでは、YOLOv8でカスタム分類モデルをトレーニングし、デプロイする方法を説明します。
概要
仮想環境からYOLOv8をインストールし、roboflowから分類モデルをダウンロード、及び学習させ、デプロイするところまでを説明します。
画像の分類
画像分類はコンピュータ・ビジョンの最も単純なタスクで、画像をあらかじめ定義されたクラスのいずれかに分類します。出力として得られるのは、単一のクラスラベルと信頼度スコアです。画像分類は、画像内のオブジェクトの位置を知る必要がなく、画像がどのクラスに属するかを知る必要がある場合に有用です。
システム要件
ハードウェア
ソフトウェア
- JetPack 6.0
- Roboflowアカウント(データセットをダウンロードするために必要)
reComputerの準備
Seeed StudioのreComputer J4012は、Jetson Orin NX 16GBです。 パワフルなマシンですが、Tegra Linuxには多くのものが搭載されており、グラフィックモードで起動しないようブートモードを変更する必要があります。
注:VScodeと、Xフォワーディングを有効にしたSSHターミナルを使って、サンプルとプログラミングをリモートで実行しようと思います。XフォワーディングはSSHのオプションで、リモート・コンピューターではなく、こちら側の接続でグラフィカル・アプリケーションを実行することができます。
ブートモードの変更
アイドルモードでは約1.5GBのメモリを消費している為、設定を変更します。
代わりにコマンドラインから起動するようにします。
sudo systemctl set-default multi-user
現時点では、reComputerを起動すると、CLIが起動します。必要に応じて、今すぐ再起動することも、コマンド1つでCLIに入ることもできます。
sudo systemctl isolate multi-user
メモリ使用量は1.5GBから700MBに減りました。機械学習を使用する場合は、メモリバイト1つ1つが重要です。
電源モードの変更
デフォルトでは、reComputerは15Wで動作しています。 トレーニング、あるいはMLモデルの推論を行う場合、フルパワーで動作させることができれば、その方が良いはずです。
ここでその変更方法を学びましょう。「/etc/nvpmodel.conf」ファイルに、利用可能なパワーモードがあります。
< POWER_MODEL ID=0 NAME=MAXN >
< POWER_MODEL ID=1 NAME=10W >
< POWER_MODEL ID=2 NAME=15W >
< POWER_MODEL ID=3 NAME=25W >
次に、sudo nvpmodel -m <#power model>で電源モードを変更できます。 また、このスレッドの投稿によると、設定は再起動後も保持されるようです。 現在のパワーレベルを確認するために、次のコマンドを実行してください。
sudo nvpmodel -q
そして、モデルのトレーニングのため、最大出力モードを選択してください。
sudo nvpmodel -m 0
再起動後、フルパワーで稼働していることが確認できます。
モデルのトレーニング
モデルのトレーニングにはYOLOv8を使用します。CUDAをサポートしたYOLOv8をインストールする手順は以下の通りです。 また、roboflowのアカウントも必要です。
これから、鳥を分類するモデルを作ります。 これは私の庭に設置するスマートバードフィーダーのプロジェクトの一部で、そこで餌を食べる鳥が何なのかを知りたいのです。 これは分類タスクなので、写真に写っている鳥の位置を知る必要はありません。 分類データセットやモデルであれば、好きな別のデータセットを使うことができます。 私が住んでいる地域に生息していて、近くでよく見られることを知っている鳥の12クラスを調達し、Roboflowで分類データセットを作成しました。
私が識別を試みる鳥のクラスは以下の通りです
- Barn Swallow(ツバメ)
- Common Firecrest(マミジロキクイタダキ)
- Common Nightingale(サヨナキドリ)
- Eurasian Chaffinch(ズアオアトリ)
- Eurasian Crag Martin(チャイロツバメ)
- European Goldfinch(ゴシキヒワ)
- European Greenfinch(アオカワラヒワ)
- European Serin(セリン)
- House Sparrow(イエスズメ)
- Spanish Sparrow(スペインスズメ)
- Western House Martin(ニシイワツバメ)
- white Wagtail(タイリクハクセキレイ)
次に、roboflowからデータセットをダウンロードします。"Download Dataset"を選択してください。
データセットのダウンロードにはアカウント作成が必要です。
次に、"Format"で"Folder Structure"を選択し、"show download code"を選択します。
Jupyter Notebookを使う場合はJupyterを、ターミナルで行う場合はターミナルを選択してください。
本wikiではJupyter Notebookを使用します。
環境構築の概要
これから仮想環境を作ります。PyTorch、YOLOv8の順番でインストールします。 YOLOv8のドキュメントによると、最初にPyTorchをインストールし、次にultralyticsをインストールするのが良いようです。
また、VSCodeで使うためにjupyterlabのパッケージをインストールします。
次の章で、いくつかの依存関係をインストールします。
注 : YOLOv8を使うので、通常は必要ないステップをいくつか行う必要があります。
NVIDIAのディープラーニングのドキュメントに従ってTorchをインストールするだけで、CUDAをサポートしたTorchを手に入れることができます。しかし、PIPを使って普通にPyTorchをインストールすると、CUDAはサポートされませんのでご注意ください。
依存関係
sudo apt install libopenblas-dev cuda-toolkit libcudnn8 tensorrt python3-libnvinfer nvidia-l4t-dla-compiler
Pythonの仮想環境を作成します。
python -m venv birdClassificationModel
エラーが出る場合は、python3-venvパッケージがインストールされていないためです。 インストールして、上のコマンドを繰り返してみましょう。
sudo apt install python3-venv
仮想環境をアクティブにします。
source birdClassificationModel/bin/activate
プロンプトの前にその名前があるので、アクティブであることが確認できます。
YOLOv8
YOLOv8をインストールする前に、ドキュメントのヒントに従うため、まずPyTorchをインストールしましょう。
私はNVIDIA Jetson Linux 36.3とCUDA 12.2が付属しているJetPack 6.0を使っています。 まずPIPをアップグレードしましょう。
pip install -U pip
YOLOv8でTorchを使用できるようにするには、NVIDIAフォーラムの手順に従ってインストールする必要があります。
これは、仮想環境がアクティブな状態で行われ、その中にインストールされます。そうしたらNVIDIAからTorchバージョン2.3をダウンロードしましょう。
wget https://nvidia.box.com/shared/static/mp164asf3sceb570wvjsrezk1p4ftj8t.whl -O torch-2.3.0-cp310-cp310-linux_aarch64.whl
sudo apt-get install python3-pip libopenblas-base libopenmpi-dev libomp-dev
pip3 install 'Cython<3'
pip install numpy torch-2.3.0-cp310-cp310-linux_aarch64.whl
次に、torchvisionをコンパイルしてください。 .whlファイルからインストールすると、CUDAがサポートされません。ブランチのバージョンは、インストールされたTorchのバージョンです。この時、仮想環境をアクティブにしておく必要があります。
sudo apt-get install libjpeg-dev zlib1g-dev libpython3-dev libopenblas-dev libavcodec-dev libavformat-dev libswscale-dev
git clone --branch v0.18.0 https://github.com/pytorch/vision torchvision
cd torchvision/
export BUILD_VERSION=0.18.0
python setup.py install
しばらくするとコンパイルされ、インストールされます。
インストール後、CUDAが使用可能か確認してください。
コマンドラインから
python -c "import torch;print (torch.cuda.is_available())"
これは真を返すはずです。
YOLOv8をインストールする
前の章では、PyTorchをCUDAサポート付きでインストールしました。
ここでYOLOv8をインストールすると、CUDAサポートなしの新しいパッケージ(同じバージョンであっても)をインストールしようとはせず、既にインストールされているバージョンが使用されます。
pip install ultralytics
それでは、roboflowとjupyterlabをインストールしてください。
pip install roboflow jupyterlab
次に、データセットをダウンロードしてください。ノートブックを使っている場合は、そこにあるコードを置き換えるだけでいいです。
rf = Roboflow(api_key="<your_api_key>")
project = rf.workspace("bruno-santos-omqsq").project("bird-classification-19z7c")
version = project.version(1)
dataset = version.download("folder")
モデルをダウンロードすると、3つのディレクトリ(test、train、valid)ができ、それぞれのディレクトリに各クラスの画像が一定数格納されます。各クラスの各画像は、それぞれのディレクトリにあります。これは画像分類のためなので、画像にラベルを付ける必要はありません。YOLOv8は、後で作る設定ファイルだけでなく、ディレクトリからもクラスを知ることができます。
Train/訓練
通常、データセットには画像とオブジェクトの座標を示すラベル(またはアノテーション)が含まれています。これは分類タスクなので、そのようなものは必要なく、ただ、画像がクラス名のディレクトリにあるだけでいいのです。
設定ファイルを準備する。
YOLOv8がクラスを認識するためには、設定ファイルが必要です。このファイルはデータセット・ディレクトリの中に「.yaml」という拡張子で置きます。名前は任意に設定してください。
cd <dataset_directory>
vi birdClassificationModel.yaml
.yamlファイルに以下のテキストを挿入してください。
train: train/
valid: valid/
test: test/
# number of classes
nc: 12
# class names
names: ["Barn Swallow","Common Firecrest","Common Nightingale","Eurasian Chaffinch","Eurasian Crag Martin","European Goldfinch","European Greenfinch","European Serin","House Sparrow","Spanish Sparrow","Western House Martin","white Wagtail"]
分類には、Ultralyticsからすでに提供されている訓練済みのモデルの1つを使用します。
このモデルはImageNetで訓練され、分類のために微調整されています。 このモデルを使い、私たちのデータで訓練します。
これがいわゆる転移学習です。
YOLOv8l-clsというモデルを使います。他のモデルもありますが、リアルタイム性は必要ありません。スピードと精度のトレードオフになります。
それでは、YOLOv8のCLIインターフェイスを使って、モデルをトレーニングしてみましょう。
yolo task=classify mode=train model=yolov8l-cls.pt data=Bird-Classification-1 epochs=100
- task=classify:画像を分類します
- mode=train:モデルをトレーニングします
- model=yolov8l-cls.pt:事前に訓練された分類モデルを使います
- data=Bird-Classification-1:データセットが入ったディレクトリ
- epochs=100:モデルを訓練する時間
では、jtop (tegra-stats)を使って統計を取ってみましょう。
数時間後にトレーニングを完了します。
さて、このモデルがどのような挙動を示すかテストしてみましょう。
yolo task=classify mode=predict model='./runs/classify/train6/weights/best.pt' source=Bird-Classification-1/test/**/*.jpg
これにより、yoloはテスト・ディレクトリに入り、それぞれを予測しようとします。
全て正常に動作しています。そこで他の2つの画像でも試してみましょう。
yolo task=classify mode=predict model='./runs/classify/train6/weights/best.pt' source=house_sparrow.jpg
yolo task=classify mode=predict model='./runs/classify/train6/weights/best.pt' source=white_wagtail.jpg
問題なく結果が表示されました。
モデルをエクスポートする
モデルはそのまま推論に使用できます。開いて使用するだけです。推論時間を短縮するには、例えばNVIDIA Jetson Orin NX または ONNX を使用しているため、TensorRT にエクスポートできます。
このプロジェクトでは推論時間を短縮する必要ないです(リアルタイムビデオで、これを使用する予定はありません) が、使用しているプラットフォームを活用できるのは良いことです。
しかし、仮想環境のため、TensorRTにエクスポートできませんでした。何らかの理由で、Python で tensorrt をインポートできないようです。ですが、仮想環境外では、tensorrtライブラリに問題はありませんでした。
ONNX
モデルをONNX形式にエクスポートするには、次のようにします。
yolo export model='./runs/classify/train6/weights/best.pt' format=onnx imgsz=640
すると、推論に使えるbest.onnxが取得できます。
ONNXを使って推論を実行するには、onnxruntime_gpuホイールをインストールする必要があります。
JetPack 6.0でonnxruntime-gpuをインストールするには、Jetson Zooからダウンロードしてください。
次に、onnxruntime_gpu 1.18.0のPythonバージョン(Python-3.10)用のpip wheelをダウンロードしてください。
wget https://nvidia.box.com/shared/static/48dtuob7meiw6ebgfsfqakc9vse62sg4.whl -O onnxruntime_gpu-1.18.0-cp310-cp310-linux_aarch64.whl
そして、それをインストールしてください。
pip install onnxruntime_gpu-1.18.0-cp310-cp310-linux_aarch64.whl
Inference/推論
以下のコードを使ってbest.ptモデルで推論を実行し、結果を見ます。
# running inference
from ultralytics import YOLO
# load the model
bird_model = YOLO("./runs/classify/train6/weights/best.pt")
#run inference
results = bird_model("house_sparrow.jpg")[0]
# get class names
class_names = results.names
# get top class with more probability
top1 = results.probs.top1
# print the class name with the highest probability
print (f" The detected bird is: {class_names[top1]}")
上のコードでは、モデルをロードし、画像で推論を実行し、結果をresults変数に保存しています。
結果は、Resultsのインスタンスである1つの項目を持つリスト型のultralytics.engine.results.Resultsオブジェクトです。
推論結果を保持する結果変数の[0]により、必要な結果を取得できます。
results = bird_model("house_sparrow.jpg")[0]
次に、その結果を使ってクラス名を取得します。 クラス名を知らないわけではないが、こうすることで、このコードが他のモデルでも使えるようになります。
class_names = results.names
その結果の1つが、より多くの確率を持つTOP1クラスを保持するTOP1変数である。このTOP1はprobsリストで与えられます。
top1 = results.probs.top1
次に、鳥類であるべき最も高い確率のクラスを表示します。
print (f" The detected bird is: {class_names[top1]}")
The detected bird is: House Sparrow
カメラ
では、カメラを使って推論を実行してみます。
JetsonはUSBカメラかRPIカメラを使うことができますが、ここではUSBカメラを接続します。
以下は、カメラの映像を表示できるかどうかをチェックをする為のコードです。
#Lets test if we can use a USB camera
import cv2
cap = cv2.VideoCapture(0)
while True:
ret, img = cap.read()
cv2.imshow('Camera', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows
これは私のデスクトップ・コンピューターにいる私です。 ssh -X username@jetson_ipを使えば、X11ウィンドウがデスクトップに転送されます。 私もLinuxを使っているので、これは使えます。 WSLも使えると思います。
では、ビデオフィードで推論を実行し、確率の高いクラスを表示してみましょう。
以下がそのコードです。
# again, save this code in a file a run it from the Jetson
import cv2
from ultralytics import YOLO
import time
#define confidence level
#only equal or above this level we say it's a class of bird
confidence = 0.95
# time when processed last frame
prev_frame = 0
# time processed current frame
cur_time = 0
# load the model
bird_model = YOLO("./runs/classify/train6/weights/best.pt")
# cv2 font
font = cv2.FONT_HERSHEY_SIMPLEX
# open camera
cap = cv2.VideoCapture(0)
while True:
ret, img = cap.read()
# to display fps
cur_frame = time.time()
fps = 1 / (cur_frame - prev_frame)
prev_frame = cur_frame
fps = int(fps)
fps = str(fps)
cv2.putText (img, fps, (550,50), font, 1, (124,10,120), 2, cv2.LINE_AA)
# inference current frame
results = bird_model(img, verbose=False)[0]
# get class names
class_names = results.names
# get top class with more probability
top1 = results.probs.top1
top1conf = results.probs.top1conf.tolist()
# we will only show the class name if the confidence is higher than defined level
# print the class name with the highest probability
if (top1conf >= confidence):
bird_class = class_names[top1]
print (f" The detected bird is: {class_names[top1]}")
# color is in BGR
confid = round(top1conf,2)
img = cv2.putText(img, bird_class, (50,50), font, 0.9, (0, 0, 255), 2, cv2.LINE_AA)
img = cv2.putText(img, "Conf: " + str(confid), (50,80), font, 0.6, (255, 0, 255), 1, cv2.LINE_AA)
cv2.imshow('Camera', img)
else:
img = cv2.imshow('Camera', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows
これを、動画で紹介していますのでよければご覧ください。
貢献者プロジェクト
このプロジェクトはSeeed Studio貢献者プロジェクトの支援を受けています。
Brunoの努力に感謝し、記事が公開されています。
テクニカルサポートと製品に関するフォーラム
ご購入いただいた製品をスムーズにお使いいただけるよう、Seeedでは様々なサポートを提供しています。ご希望に合わせてコンタクトの方法をお選びください。
出典 : Seeed Studio資料 Wiki - Train and deploy a custom classification model with YOLOv8
https://wiki.seeedstudio.com/train_and_deploy_a_custom_classification_model_with_yolov8/
*このガイドはSeeed Studioの許可を得て、スイッチサイエンスが翻訳しています。