コロナ禍の中、商業施設でよく目にするのが、赤外線カメラを用いた非接触の体温計や、手のひらへの消毒用アルコール自動噴霧器、そしてマスク着用・非着用の検出カメラといったあたりではないでしょうか。

今回は、画像認識(物体検出)ライブラリであるYOLOv5を使って、CircleCIを使った

  • マスク着用/マスク非着用の画像データを用いた深層学習(ディープラーニング)
  • 学習内容を元にしたテストセットの実行

の自動化手順をご紹介します。


YOLOv5とは

YOLOv5はUltralytics社により開発、2020年6月に公開された画像中の物体認識ライブラリです。Pythonから利用することができ、バックエンドではPyTorchパッケージを使用しています。PyTorchパッケージは、NVIDIA社のライブラリ(cuDNN - CUDA Deep Neural Network library)を使用していることから、NVIDIA GPUが利用可能な環境でYOLOv5を実行することで、学習、検出の双方でパフォーマンス向上が期待できます。

CircleCIのGPUサポート

さて、開発者ひとりひとりのPC環境でGPUを用意しなくても、開発者間でGPUを共有し、使いたい時にどのPCからでも利用することができれば、今回ご紹介するような深層学習の開発や検証、利用をより効率的に行うことができます。

CircleCIでは、誰もがどこで開発していてもGPUを利用できるように、2つの方法を用意しています。

上の2つの方法は、GPUの場所が、CircleCIクラウドのマネージド環境にあるのか、自社が管理するインフラストラクチャ上にあるのかという大きな違いがあるものの、開発者の側からは、ほとんど同じコンフィグ(自動化手順の設定)で利用することが可能です。それでは、具体的に見ていきましょう。

なお、ここで使用したプロジェクトはGitHub上で CCI-Feature-GPU として公開していますので、実際に動かしてみるには、自分のアカウントに fork してみてください。パイプライン実行時(Trigger Pipeline)に、パラメーター run_on_runner に値が未指定、または false が指定されていると、CircleCI が提供するクラウド上のGPU環境が、trueが指定されているとCircleCI ランナー上(つまり自社環境上に設定した)GPUがそれぞれ使用されます。

CircleCIのGPU環境を使用する (有償プランのみ)

CircleCI の GPU 環境は、machine executor (仮想マシン) として提供されています。ワークフロー run_on_cloud の中で、train_to_test_on_gpu ジョブでは CircleCI のGPU環境を使用するために、次のように指定しています。

jobs:
  train_to_test_on_gpu:
    machine:
      resource_class: gpu.nvidia.small
      image: ubuntu-2004-cuda-11.4:202110-01
    steps:
      - checkout
      - run:
          name: Check GPU status
          command: nvidia-smi

このジョブでは、NVIDIA GPU デバイスの管理用コマンド nvidia-smi を呼び出しており、CircleCI 上では実行結果が次のように表示されます(ただし、常に次の結果が得られることを保証するものではありません)。

nvidia-smiの呼び出し結果画面

ワークフロー内では、コマンド(commands)として定義した以下の処理を実行しています。

  1. GitHub 上にある yolov5 リポジトリを取得(git clone)する - clone_yolov5 コマンド

  2. 学習用データセットとして、Roboflow 社が提供する Mask Wearing Dataset (149イメージ)を取得する(有償) - load_maskdataset コマンド

  3. YOLOv5 が提供する train.py スクリプトを呼び出し、GPU を使った学習(トレーニング)を行い、学習結果をアーティファクトに格納する - train_with_maskdataset コマンド

  4. YOLOv5 が提供する detect.py スクリプトを呼び出し、学習結果( ./runs/train/exp/weights/best.pt )を用い、Mask Wearing Dataset が提供するテストデータ( ../MaskDataset/test/images )、および筆者が用意したテストデータ( ../images )中のマスク着用有無を検出し、アーティファクトとして格納する - test_mask_detection コマンド

学習結果は、先に 3 で示したように、アーティファクト train-result_on_gpu.zip ファイルに格納されており、CircleCI のワークフロー実行結果画面からダウンロードすることが可能です。

テスト結果は、先に 4 で示したように、アーティファクト detect-result_on_gpu.zip ファイルに格納されており、同様に CircleCI のワークフロー実行結果画面からダウンロードすることが可能です(下に示す例では、test_wo_mask2 イメージがマスク未着用にも関わらず、マスク着用と認識されてしまっていますが、閾値を 0.76 より大きな値に設定することで、マスク着用と認識されなくなるものと考えられます)。

テストの結果

CircleCIランナーを使って自社のGPU環境を使用する (Freeプランでも実装可)

さて、自社にGPU環境がある場合、CircleCI が有償で提供するクラウド上の GPU 環境ではなく、自社の GPU 環境を使って、ワークフローを実行することが可能です。今回は train_to_test_on_runner ジョブをご覧いただくとわかるように、CircleCI ランナーをインストールした GPU 環境を mayoct/runner-sls というリソースクラスに割り当てて使用しています(自分で実際に試してみる場合は、リソースクラス名を自分で作成した名前に置き換えてください)。

train_to_test_on_runner:
  machine: true
  resource_class: mayoct/runner-sls

今回は、Windows 10 バージョン 21H2 以降でサポートが開始された WSL 上での NVIDIA CUDA サポート機能を使い、Ubuntu 20.04 環境に CircleCI ランナーをインストールします。ただし、WSL2上のLinux環境では、初期状態でsystemctlコマンドでのサービスの有効化や起動ができないため、たとえば genie といったツールを合わせて使用する必要があります。

なお、Linux 環境での CircleCI ランナーの設定方法に関しては、CircleCI のドキュメント、および (Raspberry Pi 上で動作する ARM64 環境のUbuntuを例にとった説明ですが) 私の書いた CircleCIで組み込み開発(1) - Arm版CircleCIランナーのセットアップがステップを追った具体的な説明として参考になるかと思います。

CircleCI ランナーを使って自社のGPU環境を使用して学習(トレーニング)、およびテストを行うには、パラメータ run_on_runner に boolean値 true を指定してワークフローを実行します。値が未指定、または false の際には、run_on_cloud ワークフロー(つまり、train_to_test_on_gpu ジョブ)が実行されるのに対し、true が指定された際には、run_on_runner ワークフロー(つまり、train_to_test_on_runner ジョブ)が実行され、その中で CircleCI ランナー(サンプルではリソースクラス mayoct/runner-sls)が実行されます。

なお、筆者の環境では、NVIDIA GPU デバイスの管理用コマンド nvidia-smi を呼び出した結果は、次の通りでした。

Nvidia-smiの呼び出し結果

また、学習時にはGPUが使用されていることが、CircleCI ランナーが動作する Windows のタスクマネージャー上のGPU使用率、および、GPUメモリの使用量からも見て取れます。

GPUメモリの使用量

また、この学習結果を使用したテストデータにおけるマスク着用の検出結果は次の通りでした。

マスク着用の検出結果

まとめ

今回ご紹介したコンフィグを見てわかるのは、CircleCI のGPU環境で実行する場合であっても、CircleCI ランナーを使って自社のGPU環境で実行する場合であっても、コンフィグの記述自体はほとんど変わらないことです。ほとんどの部分は共通化されており、外だししたパラメータによって実行環境を指定しています。

したがって、いったんコンフィグを記述してしまえば、学習内容(つまり求められるGPU性能)に応じて、比較的柔軟に実行環境を変えられるというメリットがあり、またコンフィグを他のプロジェクトでも容易に使いまわすことが可能、つまり、機械学習(深層学習)を行うには、データさえあれば、強力なGPUを備えたワークステーションを用意したり、学習スクリプトを毎回作り直さなくても、クラウドGPU環境やオンプレミスGPU環境が誰にでも利用可能になります。

今回ご紹介した顔データのように、匿名化する(例えば、目の部分に線を入れたり、モザイクをかける)ことが難しい、意味がないデータの場合、データをどこに置き、どのように管理するのかが重要なポイントとなります。その意味でも、学習をクラウド側、自社環境側のいずれでも、大きな変更を加えることなく行えることには大きな意味があります。ぜひCircleCIを使って、機械学習(深層学習)にも自動化と自由な実行環境の選択肢を取り込んでみてはいかがでしょう?