NVIDIA TAO Toolkit と NVIDIA DeepStream を使用して、AI の専門知識がなくてもカスタム行動認識アプリケーションを開発および展開する

Chris To
NVIDIA Japan
Published in
27 min readDec 14, 2021

人間は常に動いていて、歩く、走る、座るなどの動作を毎日行っています。これらの動作は、私たちの日常生活の中で自然に行われているものです。このような特定の行動を認識するアプリケーションを構築することは、スポーツ分野での分析、ヘルスケア分野での患者の安全性、小売分野でのより良いショッピング体験などにおいて、非常に価値のあることです。

しかし、人間の行動の時間的情報を理解できる AI アプリケーションの構築と展開は、大量のトレーニングと AI に関する深い専門知識を必要とし、困難で時間のかかるものです。

この記事では、事前学習済み行動認識モデルを NVIDIA TAO Toolkit を使ってカスタムデータやクラスでファインチューニングし、NVIDIA DeepStream SDK を通じて推論用にデプロイすることで、AI の専門知識を一切必要とせずに、AI アプリケーションの開発を加速する方法を紹介します。

図 1. 事前学習済みモデルから始まり、NVIDIA TAO Toolkit でファインチューニングし、DeepStream でデプロイするエンド ツー エンドのワークフロー

行動認識モデル

アクション (行動) を認識するためには、ネットワークは 1 つの静的なフレームだけでなく、複数の連続したフレームを見なければなりません。これにより、アクションを理解するための時間的コンテキストが得られます。

これらの行動認識モデルは、2D 畳み込みニューラルネットワーク (CNN) を使用して作成されており、次元は幅、高さ、およびチャネル数です。2D 行動認識モデルは、他の 2D コンピュータビジョンモデルと同様ですが、チャネル次元には時間的情報も含まれています。

  • 2D 行動認識モデルでは、時間的フレーム D にチャネルカウント C を掛けて、チャネル次元入力を形成します。例: 時間的フレーム = 4、チャネル = 3 の場合は 12 チャネルを作成します。
  • 3D 行動認識モデルの場合、時間的情報を表す新しい次元 D が追加されます。

2D と 3D の両方の畳み込みネットワークからの出力は、全結合層 (FC) に入り、続いて Softmax 層でアクションを予測します。

図 2. 行動認識の 2D および 3D 畳み込みネットワーク

事前学習済みモデルとは、代表的なデータセットで学習し、重みやバイアスをファインチューニングしたモデルのことです。NVIDIA の行動認識モデルは、NGC カタログから入手でき、5 つの一般的なクラスで学習されています。

  • 歩く
  • 走る
  • 押す
  • 自転車に乗る
  • 転ぶ

これがサンプルモデルです。さらに重要なことは、このモデルをゼロから始めるのではなく、カスタムデータを使って簡単に短時間で再学習できることです。

事前学習済みモデルは、HMDB51 データセットの数百の短いビデオクリップで学習されました。モデルを学習した 5 つのクラスについて、2D モデルは 83%、3D モデルは 86% の精度を達成しました。さらに、モデルをそのまま導入した場合に、各種 GPU で期待される性能を以下の表に示します。

表 1. モデル別の期待推論性能

今回の実験では、腕立て伏せ (push up)、腹筋 (sit up)、懸垂 (pull up) などの簡単な動作で構成された 3 つのクラスを新たに追加して、モデルをファインチューニングします。51 種類のアクションが含まれる HMDB51 データセットのサブセットを使用します。

前提条件

開始する前に、学習と展開のために以下のリソースが必要です。

  • NVIDIA GPU ドライバーのバージョン: >470
  • NVIDIA Docker: 2.5.0–1
  • クラウドまたはオンプレミスの NVIDIA GPU: A100、V100、T4、RTX 30x0
  • NVIDIA TAO Toolkit: 3.0–21.11
  • NVIDIA DeepStream: 6.0

詳細については、TAO Toolkit Quick Start Guide を参照してください。

TAO Toolkit を使用して学習、適応、最適化

このセクションでは、TAO Toolkit を使用して、新しいクラスでモデルをファインチューニングします。

TAO Toolkit は、既存のニューラルネットワークモデルから学習された特徴を利用し、それを新しいモデルに適用する転移学習 (Transfer Learning)を採用しています。NVIDIA TAO フレームワークの CLI および Jupyter Notebook ベースのソリューションである TAO Toolkit は、AI/DL フレームワークの複雑さを抽象化し、AI の専門知識がなくてもユースケースに合わせたカスタムモデルや実運用モデルを作成することができます。

CLI ウィンドウで簡単な指示を出すこともできますし、Jupyter ノートブックを使って学習やファインチューニングを行うこともできます。NGC の行動認識ノートブックを使用して、カスタムの 3 クラスモデルを学習します。

TAO Toolkit Computer Vision Sample Workflows のバージョン 1.3 をダウンロードし、パッケージを解凍します。/action_recognition_net ディレクトリには、行動認識学習用の Jupyter ノートブック(actionrecognitionnet.ipynb)と、トレーニング、評価、モデルエクスポート用の spec ファイルが入った /specs ディレクトリがあります。これらの spec ファイルを学習用に設定します。

Jupyter ノートブックを起動し、action_recognition_net/actionrecognitionnet.ipynb ファイルを開きます。

jupyter notebook --ip0.0.0.0 --port 8888 --allow-root

ステップ1: TAO Toolkit をセットアップしてインストールする

トレーニングの手順は、すべて Jupyter ノートブック内で実行されます。ノートブックを起動した後、ノートブックに含まれる Set up env variables and map drivesInstall TAO launcher の手順を実行します。

ステップ2: データセットと事前学習済みモデルをダウンロードする

TAO Toolkit のインストールが完了したら、次は学習用のデータセットをダウンロードして準備します。Jupyter Notebook には、HMDB51 データセットをダウンロードして前処理する手順が記載されています。独自のカスタムデータセットをお持ちの場合は、ステップ 2.1 でそれを使用することができます。

この記事では、HMDB51 データセットから 3 つのクラスを使用します。いくつかの行を修正して、腕立て伏せ (push up)、懸垂 (pull up)、腹筋 (sit up) の各クラスを追加します。

$ wget -P $HOST_DATA_DIR http://serre-lab.clps.brown.edu/wp-content/uploads/2013/10/hmdb51_org.rar
$ mkdir -p $HOST_DATA_DIR/videos && unrar x \ $HOST_DATA_DIR/hmdb51_org.rar $HOST_DATA_DIR/videos
$ mkdir -p $HOST_DATA_DIR/raw_data
$ unrar x $HOST_DATA_DIR/videos/pushup.rar $HOST_DATA_DIR/raw_data
$ unrar x $HOST_DATA_DIR/videos/pullup.rar $HOST_DATA_DIR/raw_data
$ unrar x $HOST_DATA_DIR/videos/situp.rar $HOST_DATA_DIR/raw_data

各クラスの動画ファイルは、$HOST_DATA_DIR/raw_dataの下の、それぞれのディレクトリに格納されています。これらはエンコードされた動画ファイルで、モデルを学習するためには動画ファイル内の圧縮フレームを非圧縮フレームへデコードする必要があります。学習用のデータを準備するためのスクリプトが用意されています。

ヘルパースクリプトをダウンロードして、依存関係をインストールしてください。

$ git clone https://github.com/NVIDIA-AI-IOT/tao_toolkit_recipes.git
$ pip3 install xmltodict opencv-python

動画ファイルをフレーム単位で解凍します。

$ cd tao_recipes/tao_action_recognition/data_generation/
$ ./preprocess_HMDB_RGB.sh $HOST_DATA_DIR/raw_data \ $HOST_DATA_DIR/processed_data

各クラスの出力を以下のコード例で示します。f cnt: 82は、この動画ファイルが 82 フレームに非圧縮されていることを意味します。この処理は、ディレクトリ内のすべてのビデオに対して行われます。クラスの数、データセットや動画ファイルのサイズによっては、この処理に時間がかかることがあります。

Preprocess pullup
f cnt: 82.0
f cnt: 82.0
f cnt: 82.0
f cnt: 71.0
...

処理されたデータの形式は、以下のコード例のようになります。自分のデータを使って学習を行う場合は、データセットもこのディレクトリ形式になるようにしてください。

$HOST_DATA_DIR/processed_data/
|--> <Class name>
|--> <Video 1>
|--> rgb
|--> 000001.png
|--> 000002.png
|--> 000003.png

次のステップは、データを学習セットと検証セットに分割することです。HMDB51 データセットでは、クラスごとに分割ファイルが用意されているので、それをダウンロードして、データセットを 70% のトレーニングと 30% の検証に分割します。

$ wget -P $HOST_DATA_DIR http://serre-lab.clps.brown.edu/wp-content/uploads/2013/10/test_train_splits.rar
$ mkdir -p $HOST_DATA_DIR/splits && unrar x \ $HOST_DATA_DIR/test_train_splits.rar $HOST_DATA_DIR/splits

データを分割するには、ヘルパースクリプト split_dataset.py を使用します。これは、HMDB データセットで提供される分割ファイルでのみ動作します。自分で作ったデータセットを使っている場合は、この限りではありません。

$ cd tao_recipes/tao_action_recognition/data_generation/

$ python3 ./split_dataset.py $HOST_DATA_DIR/processed_data \ $HOST_DATA_DIR/splits/testTrainMulti_7030_splits \ $HOST_DATA_DIR/train \
$HOST_DATA_DIR/test

トレーニング用のデータは $HOST_DATA_DIR/trainに、テストおよび検証用のデータは $HOST_DATA_DIR/testにあります。

データセットを準備した後、NGC から事前学習済みモデルをダウンロードします。Jupyter Notebook の 2.1 の手順に従ってください。

$ ngc registry model download-version "nvidia/tao/actionrecognitionnet:trainable_v1.0" --dest $HOST_RESULTS_DIR/pretrained

ステップ3: 学習パラメータを設定する

学習パラメータは spec YAML ファイルで提供されます。 /specsディレクトリには、学習、ファインチューニング、評価、推論、出力のすべての spec ファイルがあります。学習には、train_rgb_3d_finetune.yamlを使用します。

この実験では、変更可能なハイパーパラメータをいくつか紹介します。すべての異なるパラメータの詳細については、ActionRecognitionNet を参照してください。

また、実行中にパラメータを上書きすることもできます。ほとんどのパラメータはデフォルトのままです。変更するいくつかのパラメータは、以下のコードブロックに示されています。

## モデル構成
model_config:
model_type: rgb
input_type: "3d"
backbone: resnet18
rgb_seq_length: 32 ## フレームシーケンスの長さを 3 から 32 に変更
rgb_pretrained_num_classes: 5
sample_strategy: consecutive
sample_rate: 1

## 学習ハイパーパラメータの設定
train_config:
optim:
lr: 0.001
momentum: 0.9
weight_decay: 0.0001
lr_scheduler: MultiStep
lr_steps: [5, 15, 25]
lr_decay: 0.1
epochs: 20 ## 学習するエポック数
checkpoint_interval: 1 ## モデルのチェックポイント間隔の保存

## データセットの構成
dataset_config:
train_dataset_dir: /data/train ## 学習データセットを使用するように変更する
val_dataset_dir: /data/test ## 検証データセットを使用するように変更する
## 新しいクラスのラベルマップ。カスタムクラスのためにこれを修正する
label_map:
pushup: 0
pullup: 1
situp: 2
## モデルの入力解像度
output_shape:
- 224
- 224
batch_size: 32
workers: 8
clips_per_video: 5

ステップ4: AI モデルを学習する

学習では、Jupyter Notebook のステップ 4 に従ってください。環境変数を設定します。

行動認識を学習する TAO Toolkit のタスクは、action_recognitionと呼ばれます。トレーニングを行うには、tao action_recognition trainコマンドを使用します。トレーニングの spec ファイルを指定し、出力ディレクトリと事前学習済みモデルを指定します。また、model_config パラメータで事前学習済みモデルを設定することもできます。

$ tao action_recognition train \
-e $SPECS_DIR/train_rgb_3d_finetune.yaml \
-r $RESULTS_DIR/rgb_3d_ptm \
-k $KEY \
model_config.rgb_pretrained_model_path=$RESULTS_DIR/pretrained/actionrecognitionnet_vtrainable_v1.0/resnet18_3d_rgb_hmdb5_32.tlt

GPU、シーケンスの長さ、エポック数によっては、この作業に数分から数時間かかることもあります。エポックごとに保存しているため、エポック数と同数のモデルチェックポイントが表示されます。

モデルのチェックポイントは ar_model_epoch=<EPOCH NUM>-val_loss=<VAL LOSS>.tltとして保存されます。モデルの評価と出力のために最後のエポックを選びますが、検証損失が最も少ないものであればどれを使っても構いません。

ステップ5: 学習されたモデルを評価する

学習されたモデルを動画ファイルで評価するために、2 種類の異なるサンプリング戦略があります。

  • Center Mode: 推論を行うためにシーケンスの中間フレームをピックアップします。例えば、モデルが入力として 32 フレームを必要とし、動画ファイルが 128 フレームである場合、インデックス 48 からインデックス 79 までのフレームを選んで推論を行います。
  • Conv Mode: 1 つの動画から 10 個のシーケンスを畳み込みサンプリングし、推論を行います。その結果を平均化します。

評価には、/specsディレクトリに用意されている評価用スペックファイル(evaluate_rgb.yaml)を使用します。これは学習用の設定と同様です。学習対象の 3つのクラスを使用するように dataset_configパラメータを変更します。

dataset_config: 
## 新しいクラスのラベルマップ。カスタムクラスのためにこれを修正する
label_map:
pushup: 0
pullup: 1
situp: 2

tao action_recognition evaluateコマンドで評価します。video_eval_modeには、先ほど説明したように、center mode か conv mode を選択できます。学習時に最後に保存したモデルチェックポイントを使用します。

$ tao action_recognition evaluate \
-e $SPECS_DIR/evaluate_rgb.yaml \
-k $KEY \
model=$RESULTS_DIR/rgb_3d_ptm/ar_model_epoch=<EPOCH NUM>-val_loss=<VAL LOSS>.tlt \
batch_size=1 \
test_dataset_dir=$DATA_DIR/test \
video_eval_mode=center

評価出力:

100%|███████████████████████████████████████████| 90/90 [00:03<00:00, 29.82it/s]
*******************************
pushup 56.67
pullup 100.0
situp 90.0
*******************************
Total accuracy: 82.222
Average class accuracy: 82.222
2021-11-17 17:46:52,590 [INFO] tlt.components.docker_handler.docker_handler: Stopping container.

この評価は、3 つのアクションの動画を集めた 90 個のビデオデータセットで行われました。全体の精度は約 82% で、データセットのサイズにしてはまずまずの結果です。データセットが大きければ大きいほど、モデルの一般化が進みます。お手持ちの動画ファイルでテストしてみて、精度を評価してみてください。

ステップ6: DeepStream のデプロイ用に出力

最後のステップは、デプロイ用にモデルを出力することです。出力するには、tao action_recognition export コマンドを実行します。その際、出力 specs ファイルを指定する必要があります。このファイルは、/specsディレクトリに export_rgb.yamlとして含まれています。export_rgb.yaml内の dataset_configの値を変更して、学習した 3 つのクラスを使用します。これは、evaluate_rgb.yamldataset_configと同じです。

$ tao action_recognition export \
-e $SPECS_DIR/export_rgb.yaml \
-k $KEY \
model=$RESULTS_DIR/rgb_3d_ptm/ar_model_epoch=<EPOCH NUM>-val_loss=<VAL LOSS>.tlt \
/export/rgb_resnet18_3.etlt

おめでとうございます。カスタム 3D 行動認識モデルのトレーニングに成功しました。では、このモデルを DeepStream を使って展開してみましょう。

DeepStream を使用したデプロイメント

ここでは、ファインチューニングされたモデルを NVIDIA DeepStream を使って展開する方法を紹介します。

DeepStream SDK は、効率的で高性能なビデオ AI アプリケーションを迅速に構築するのに役立ちます。DeepStream アプリケーションは、NVIDIA Jetson を搭載したエッジデバイス、オンプレミスサーバ、またはクラウド上で実行することができます。

行動認識モデルを対応するために、DeepStream 6.0 には Gst-nvdspreprocess プラグインが追加されています。このプラグインは、カスタムライブラリ(custom_sequence_preprocess.so)をロードして、時間的なシーケンスバッチングと関心領域 (Region of Interest, ROI) の部分的なバッチングを実行し、バッチングされたテンソルバッファを下流の推論プラグインに転送します。

DeepStream SDK に含まれている deepstream-3d-action-recognitionアプリケーションを変更して、TAO Toolkit で事前にファインチューニングしたモデルをテストすることができます。

図 3. 3D 行動認識アプリケーションのパイプライン

サンプルアプリケーションでは、4 つの動画ファイルに対して同時に推論を行い、その結果を 2×2 のタイル状のディスプレイに表示します。

修正を行う前に、まず標準のアプリケーションを実行してみましょう。まず、DeepStream 6.0 の開発コンテナを起動します。

$ xhost +
$ docker run --gpus '"'device=0'"' -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -w /opt/nvidia/deepstream/deepstream-6.0 nvcr.io/nvidia/deepstream:6.0-devel

NVIDIA が提供する DeepStream コンテナの詳細については、NGC カタログをご覧ください。

コンテナ内で、3D 行動認識アプリケーションのディレクトリに移動し、NGC の標準的な 3D および 2D モデルをダウンロードしてインストールします。

$ cd sources/apps/sample_apps/deepstream-3d-action-recognition/
$ wget --content-disposition https://api.ngc.nvidia.com/v2/models/nvidia/tao/actionrecognitionnet/versions/deployable_v1.0/zip -O actionrecognitionnet_deployable_v1.0.zip
$ unzip actionrecognitionnet_deployable_v1.0.zip

これで、3D 推論モデルを使ってアプリケーションを実行し、結果を確認することができます。

$ deepstream-3d-action-recognition -c deepstream_action_recognition_config.txt
図 4. 3D 行動認識

PreProcess プラグインの設定

アプリケーションを修正する前に、アプリケーションを実行するために必要な PreProcess プラグインの主要な設定パラメータをよく理解しておいてください。

/app/sample_apps/deepstream-3d-action-recognitionフォルダから config_preprocess_3d_custom.txtファイルを開き、3D モデル用の PreProcess の設定を確認します。

13 行目では、3D モデルで必要な 5 次元の入力形状を定義しています。

network-input-shape = 4;3;32;224;224

このアプリケーションでは、4 つのビデオ入力にそれぞれ 1 つの ROI を使用しています。

  • バッチ番号は 4 (入力数 × 入力あたりの ROI 数) です。
  • 入力は RGB なので、チャンネル数は 3 です。
  • シーケンスの長さは 32 で、入力解像度は 224 x 224 (H x W) です。

18 行目は、ネットワークの入力層がカスタムシーケンスであることをPreProcess ライブラリに伝えています。

network-input-order = 2

51 行目と 52 行目では、フレームを推論エンジンに渡す方法を定義しています。

stride = 1 
subsample = 0
  • subsampleの値が 0 の場合は、フレームを順次 (フレーム1、フレーム2、…) 推論ステップに渡すことを意味します。
  • stride値が 1 の場合は、配列間に 1 フレームの差があることを意味します。例えば:
  • シーケンス A: フレーム 1、2、3、4、…
  • シーケンス B: フレーム 2、3、4、5、…

最後に、55 行目から 60 行目では、入力数と ROI の数を定義しています。

src-ids=0;1;2;3
process-on-roi=1
roi-params-src-0=0;0;1280;720
roi-params-src-1=0;0;1280;720
roi-params-src-2=0;0;1280;720
roi-params-src-3=0;0;1280;720

すべてのアプリケーションおよび PreProcess のパラメータの詳細については、DeepStream ドキュメントの「Action Recognition」セクションを参照してください。

新しいモデルの実行

これで、アプリケーションの設定を変更し、腕立て伏せ、懸垂、腹筋の 3つの運動を認識できるようにファインチューニングされた新しい動作認識モデルをテストする準備が整いました。

Docker イメージを使用しているため、ホストのファイルシステムとコンテナの間でファイルを転送するには、コンテナーの起動時に -v mountフラグを使用して共有可能な場所を設定するのが最適です。たとえば、-v /home:/homeを使うと、ホストの /homeディレクトリをコンテナーの /homeディレクトリにマウントします。

新しいモデル、ラベルファイル、テスト動画を /app/sample_apps/deepstream-3d-action-recognition フォルダにコピーしてます。

# 元のラベルファイルをバックアップします
$ cp ./labels.txt ./labels_bk.txt
$ cp /home/labels.txt ./
$ cp /home/Exercise_demo.mp4 ./
$ cp /home/rgb_resnet18_3d_exercises.etlt ./

deepstream_action_recognition_config.txtを開き、30 行目を運動のテスト動画ファイルを指すように変更します。

uri-list = file:////opt/nvidia/deepstream/deepstream-6.0/sources/apps/sample_apps/deepstream-3d-action-recognition/Exercise_demo.mp4

config_infer_primary_3d_action.txtを開き、63 行目の推論に使用するモデルを指定して、68 行目のバッチサイズを 4 から 1 に変更します。4 つの入力から 1 つの入力になるからです。

tlt-encoded-model=./rgb_resnet18_3d_exercises.etlt

...

batch-size=1

最後に、config_preprocess_3d_custom.txtを開きます。35 行目のnetwork-input-shapeの値を、運動認識モデルの単一入力と構成を反映して変更します。

network-input-shape = 1; 3; 3; 224; 224

77~82 行目のソース設定を、単一の入力と ROI に合わせて変更します。

src-ids = 0 
process-on-roi = 1
roi-params-src-0 = 0; 0; 1280; 720
roi-params-src-1 = 0; 0; 1280; 720
roi-params-src-2 = 0; 0; 1280; 720
roi-params-src-3 = 0; 0; 1280; 720

次のコマンドを使って、新しいモデルをテストすることができます。

$ deepstream-3d-action-recognition -c deepstream_action_recognition_config.txt
図 5. 運動認識出力

アプリケーションのソースコード

行動認識サンプルアプリケーションでは、アプリケーションのソースコードを変更することなく、入力ソース、入力数、使用モデルを柔軟に変更することができます。

アプリケーションがどのように実装されたかは、/sources/apps/sample_apps/deepstream-3d-action-recognitionフォルダにある、アプリケーションのソースコードと、PreProcess プラグインで使用されるカスタムシーケンスライブラリをご参照してください。

まとめ

この記事では、TAO ToolkitDeepStream SDK をそれぞれ使用して、行動認識モデルをファインチューニングしてデプロイするエンドツーエンドのワークフローを紹介しました。TAO Toolkit と DeepStream はどちらも AI フレームワークの複雑さを抽象化したソリューションで、AI の専門知識がなくても AI アプリケーションを実運用環境で構築・展開することができます。

NGC カタログからモデルをダウンロードして、行動認識モデルを使い始めましょう。

詳細については、以下のリソースを参照してください。

--

--

Chris To
NVIDIA Japan

Manager, Solution Architecture & Engineering | NVIDIA