mxnet-finetunerの使い方

ディープラーニングによる画像分類モデルをほぼ自動的に作成できるツールを作ったので、簡単に使い方を紹介します。

docker環境および、ある程度の枚数の識別したい画像を準備すれば、本記事の手順に添って、簡単なyamlの設定ファイルを記述するだけで、モデルの学習から画像識別APIサーバを起動するところまで、一通り実施できます。

本ツールはコンテナ内部でGPU利用を含んだほとんどの処理を自動実行するため、機械学習フレームワークを利用する際にハマりやすい、GPUドライバやCUDAやcuDNN等のインストールのトラブルやドライバの組み合わせによる相性問題に悩まされることがありません。GPU無しでもCPUで学習できますが、画像枚数が多くなると学習時間が長いためGPU環境をオススメします。また、名前にあるとおり、ツールの内部では Apache MXNet を利用しています。

ソースコードは以下で公開しています。
https://github.com/knjcode/mxnet-finetuner

2017年8月に公開したラーメン二郎全店舗識別bot(@jirou_deep)の開発にもこのツールを活用しています。

目次

特徴

ざっくり、特徴をまとめると以下のとおりです

  • docker-composeでお手軽起動(GPU利用も可)
  • 学習データの加工・整形の自動実行
  • 学習済みモデルの自動ダウンロード
  • 学習データのクラス数に応じた学習済みモデルの自動整形
  • 各種データ拡張機能(反転、回転、輝度変更、等々)
  • 学習結果のグラフ化、混同行列や分類精度のレポート機能
  • Slackへの学習結果のアップロード
  • 学習済みモデルのエクスポート
  • 学習済みモデルをAPIサーバとして起動

必要環境

  • docker
  • docker-compose
  • jq
  • wget もしくは curl

NVIDIAのGPUを利用する場合には nvidia-docker または nvidia-docker2 が必要です

セットアップ

GitHubからソースコードをクローンしてセットアップします。

$ git clone https://github.com/knjcode/mxnet-finetuner
$ cd mxnet-finetuner
$ bash setup.sh

setup.sh を実行することで、カレントディレクトリにホスト環境に応じた docker-compose.yml および、学習やテスト等の設定値が記載された config.yml が作成されます。

ホストに nvidia-docker または nvidia-docker2 がインストールされている場合にはGPUが利用可能であると判断し、 docker-compose.yml にホスト側GPUをコンテナ内部から利用できる設定を追加します。

ホストのGPUドライバーをアップデートした場合やホストのGPU数が増減した場合には、 setup.sh を再度実行し、現在の環境に対応した docker-compose.yml を再度作成してください。(nvidia-docker2を利用している場合にはこの作業は不要です)

簡単な使い方

詳細はこの後の各セクションで説明しますが、学習対象の画像を用意するだけで、以下のコマンド例にあるように、モデルの学習から画像識別APIサーバを起動するまで、このツールで一通り実施できます。

# 画像識別モデルの学習
$ docker-compose run finetuner
# 学習したモデルのテスト
$ docker-compose run finetuner test
# 学習したモデルのエクスポート
$ docker-compose run finetuner export
# 学習したモデルをAPIサーバとして起動
$ dcoker-compose up -d mms

以降の手順は、mxnet-finetunerをcloneしたディレクトリで作業することを想定しています。

学習用画像の準備

学習用画像を images/train, images/valid, images/test 配下に以下のような構造で用意します。
下記は、 ariplaneswatch の2種類の画像を用意した例です。

images/
    train/
        airplanes/
            airplane001.jpg
            airplane002.jpg
            ...
        watch/
            watch001.jpg
            watch002.jpg
            ...
    valid/
        airplanes/
            airplane101.jpg
            airplane102.jpg
            ...
        watch/
            watch101.jpg
            watch102.jpg
            ...
    test/
        airplanes/
            airplane201.jpg
            airplane202.jpg
            ...
        watch/
            watch201.jpg
            watch202.jpg
            ...

お試し用の画像を使う

画像を用意するのは面倒だが、とりあえず試してみたいという場合には、 util/caltech101_prepare.sh を実行することで、 example_images ディレクトリ配下に、Caltech101データセットから切り出した10クラスの学習用画像を準備できます。

$ util/caltech101_prepare.sh

作成されるディレクトリの構成は以下の通りです

  • example_images/train 配下に学習用画像が各クラス60枚、計600枚
  • example_images/valid 配下にバリデーション用画像が各クラス20枚、計200枚
  • example_images/test 配下にテスト用画像が各クラス20枚、計200枚

元々ある images ディレクトリを example_images ディレクトリに置き換えることで学習を始めるための画像の準備が整います。

$ rm -rf images
$ mv example_images images

モデルの学習(ファインチューニング)の実施

モデルの学習は docker-compose で以下のように行います。

$ docker-compose run finetuner

コマンドを実行すると、自動的に学習用画像の加工・整形を行い、ImageNetで学習済みのモデルをダウンロードした後、ファインチューニング(転移学習)を行います。
学習時のログやテスト結果等は logs ディレクトリ配下に保存され、学習済みのモデルファイルは学習エポック毎に model ディレクトリに保存されます。

config.yml は、以下のような感じで記載します。

common:
  num_threads: 8                  # CPUを8コア使用
  gpus: 0,1                       # IDが0と1の2つのGPUを使用

finetune:
  models:
    - imagenet1k-resnet-50        # 学習済みのResNet-50を利用
  optimizers:
    - sgd                         # optimizerにSGDを利用
  num_epochs: 10                  # 10エポック学習
  lr: 0.0001                      # 学習率は 0.0001
  mom: 0.9                        # モメンタムは 0.9
  wd: 0.00001                     # Weight Decayは 0.00001
  batch_size: 32                  # バッチサイズは 32
  data_aug_level: 3               # データ拡張(強め)実施
  train_accuracy_graph_output: 1  # 学習結果のグラフを出力

自動生成される config.yml にコメントアウトした状態で各種設定項目を記載しているので、ディープラーニングの経験がある方は、だいたい雰囲気でわかるかと思います。
利用できる学習済みモデルの一覧についてはこちらに、データ拡張の詳細についてはこちらに詳細を記載しています。

学習したモデルをテストする

images/test 配下に保存した画像を使って、モデルの識別精度をテストします。

config.ymltest.model に利用したい学習済みのモデルを指定します。

学習済みモデル model/201705292200-imagenet1k-nin-sgd-0001.params をテストに利用したい場合には、 config.yml に以下のように記載します。

test:
  model: 201705292200-imagenet1k-nin-sgd-0001

モデル名を指定せず、最後に学習したモデル(この場合にはvalidationの精度が最も高いものが使われます)を利用することもできます。

test:
  use_latest: 1

テストは以下のコマンドで実行します。

$ docker-compose run finetuner test

テストの結果および識別精度のレポートが logs ディレクトリに保存されます。

学習したモデルのエクスポート

学習済みのモデルをエクスポートできます。
エクスポートしたモデルは、MXNetやONNXの学習済みモデルをAPIサーバとして利用可能な mxnet-model-server で利用できる形式で保存されます。

テストの際と同様な方法で、 config.yml に以下のように学習済みモデルを指定し、

export:
  model: 201705292200-imagenet1k-nin-sgd-0001

最後に学習したモデルをエクスポートする場合

export:
  use_latest: 1

次のコマンドでモデルをエクスポートできます。

$ docker-compose run finetuner export

エクスポートされたモデルは拡張子 .model というファイル名で model ディレクトリに保存されます。

エクスポートしたモデルをAPIサーバとして起動

先ほど紹介した mxnet-model-server のビルド済みDockerイメージを利用して、エクスポートしたモデルをAPIサーバとして起動できます.

$ docker-compose up -d mms

デフォルトでは、最後にエクスポートしたモデルを自動的に読み込んで起動します。
ローカルホストの8080番ポートに以下のようにアクセスすることでAPIを利用可能です。

$ curl -X POST http://127.0.0.1:8080/model/predict -F "[email protected]"

以下のような結果が返却されます。

{
  "prediction": [
    [
      {
        "class": "airplane",
        "probability": 0.9950716495513916
      },
      {
        "class": "watch",
        "probability": 0.004928381647914648
      }
    ]
  ]
}
{
  "prediction": [
    [
      {
        "class": "airplane",
        "probability": 0.9950716495513916
      },
      {
        "class": "watch",
        "probability": 0.004928381647914648
      }
    ]
  ]
}

学習済みモデルのエクスポート時に、APIサーバ起動用の設定ファイルを、CPU環境では model/mms_app_cpu.conf に、GPU環境では model/mms_app_gpu.conf に出力します。起動するモデルを変更したい場合には、適宜この設定ファイルを修正してください。

その他

学習結果・識別精度のslackへの自動アップロード

config.yml に以下の設定を追加することで、学習結果および学習済みモデルの評価(混同行列による評価)をslackへ自動アップロードできます。

この機能を利用する場合には、以下のように、slackのAPIトークンを発行し環境変数 SLACK_API_TOKEN を設定しておく必要があります。

$ export SLACK_API_TOKEN="xoxp-123456789-123456789-123456789-123456789"

学習結果のアップロード

config.ymlfinetune.train_accuracy_graph_slack_upload1 を設定します。
アップロードするチャンネルを指定したい場合は finetune.train_accuracy_graph_slack_channels にチャンネル名を指定します。複数指定すると複数チャンネルに同時に投稿します。

finetune:
  train_accuracy_graph_slack_upload: 1
  train_accuracy_graph_slack_channels:
    - general

上記の設定で、以下のような画像がslackのgeneralチャンネルにアップロードされます。

学習結果の例

モデルの評価結果のアップロード(混同行列による評価)

config.ymltest.confusion_matrix_slack_upload1 を設定します。
アップロードするチャンネルを指定したい場合は test.confusion_matrix_slack_channels にチャンネル名を指定します。複数指定すると複数チャンネルに同時に投稿します。

test:
  confusion_matrix_slack_upload: 1
  confusion_matrix_slack_channels:
    - general

上記の設定で、以下のような画像がslackのgeneralチャンネルにアップロードされます

混同行列の例

スクラッチからの学習

開発当初は mxnet-finetuner という名前にもあるとおり、学習済みモデルのファインチューニングを前提にしていましたが、開発途中から各種モデルのスクラッチからの学習にも対応しました。

モデルの指定を下記のように scratch プレフィックス付きのものを指定することで学習済みモデルを利用せず、スクラッチからの学習になります。

finetune:
  models:
    - scratch-inception-v3

スクラッチからの学習に利用できるモデルについてはこちらに記載しています。

その他にも、モデルのレイヤーを一部フリーズしての学習や、複数の学習済みモデルのアンサンブル、各モデルの識別結果のdiversityの確認、等が可能ですが、長くなったので、また別の記事で紹介したいと思います。

各機能の詳細については mxnet-finetuner を御覧ください。

スポンサーリンク
レクタングル(大)