バイセル Tech Blog

バイセル Tech Blogは株式会社BuySellTechnologiesのエンジニア達が知見・発見を共有する技術ブログです。

GCPのAI Platform ノートブックを使って、Tensorflow 2でObject Detectionを試してみる

テクノロジー開発部の村上です。CASHではObject Detectionを証明書分類などに活用しているのですが、 それを今後のためにTensorflow2に置き換えたいと考えていました。 そうしたところ、TensorFlow 2 meets the Object Detection APIという公式ブログ記事を見つけたので、今のCASHのモデル用に以前作成されたラベル付きデータを使って学習と推論を試してみました。 基本的にはチュートリアル通りなのですが、少し手こずったポイントもあるので紹介させて頂ければと思います。

f:id:nmu0:20200814013311p:plain:w300

AI Platform ノートブックを使う利点

Object Detectionだけに話題を絞ろうと思ったのですが、AI Platform ノートブックの便利さも伝えたくタイトルに入れさせて頂きました。 主に私が思う利点は以下の3つです。

  1. CUDAなどのGPU周りと機械学習系Pythonライブラリがセットアップ済みの状態でインスタンスが立ち上がる
  2. GCPによる認証付きでJupyter labが使用出来る
  3. SSH接続が楽に出来る

1については各社のVMのイメージでも昨今は同様のことが出来ますが、VMのオプションとしてではなくノートブックで何を使うか選ぶようなUIになっているので非常にわかりやすいです。また、Object DetectionはTensorflow 2.2から対応しているのですが、 その2.2もインスタンスのオプションにあり良かったです。

f:id:nmu0:20200814013007p:plain

2は自身でVMにJupyter labを建てたことがある方はわかるかと思いますが、SSL証明書の設定や認証の設定、 それに加えてIP制限も設定したりと結構な手間が掛かります。そこがGCPの認証が使えることで、手軽さもそうですが安全性も高くて安心出来ます。

そして3ですが、個人的にはこれが非常に大きいです。ノートブックが簡単に使えるというと、Google Colabを思い浮かべる方も多いかと思いますが、 SSHが出来るという差異は非常に大きいです。ノートブックを強調しているものの実態はGCEインスタンスなので、SSHで入ってしまえばあとは通常のGCEインスタンスと全く変わらないです。GCSからデータを取得して配置したり、モデルの学習のように時間がかかるスクリプトを直接実行したりとノートブックだけでは実施しづらい作業が簡単に出来ます。また、"楽に"と書いたのは、GCEではOS Loginという機能があり、SSH認証鍵の作成や管理を自分で意識することなく、IAMとgcloudコマンドを使って自動で作成や管理を行ってくれるからです。

これらの特徴を活かして、私は何か試したい期間だけ都度ノートブックを立ち上げるということを行っています。 セットアップに時間が掛からないので、期間が空く場合はライブラリが古くなることも考えると、立ち上げ直して綺麗な環境で実験した方が早いからです。

Tensorflow 2でのObject Detection

実際に少量のデータで学習して推論を試すだけでしたら、参考資料の章に貼りました"Eager Few Shot Object Detection Colab"を順に実行していくのが一番手軽です。しかしこのノートブックでは、リスト形式でデータを与えて1データずつ予測して勾配を計算するというやり方を取っています。中身を理解するのには非常に良いのですが、学習データとテストデータを作成して学習と評価を行うという通常のフローの参考にはあまりなりません。 そこで、何故か公式からのリンクが見当たらなかったのですが、以下の

を参考にすると良いです。基本的にはチュートリアルをなぞるだけなのですが、 簡単に順を追って紹介していきます。

1. 学習データの作成

チュートリアルではLabelImgが使われていますが、何でも良いのでアノテーションデータを用意しましょう。 分類された画像だけあって、bounding boxが無いという場合は、Cloud Visionなどでbounding boxを得ても良いかもしれません。 得られるXMLの形式は異なるのですが、以下のように、画像ごとにExampleインスタンスを作成してTFRecordWriterで書きこんでいるだけなので、 これに合わせてXMLを変換すれば良いです。 チュートリアルの修正点としては、tf.gfile.GFiletf.io.gfile.GFileに、tf.python_io.TFRecordWritertf.io.TFRecordWriterにするくらいです。(そのうち修正されると思いますが)

writer = tf.python_io.TFRecordWriter(args.output_path)
tf_example = tf.train.Example(features=tf.train.Features(feature={
    'image/height': dataset_util.int64_feature(height),
    'image/width': dataset_util.int64_feature(width),
    'image/filename': dataset_util.bytes_feature(filename),
    'image/source_id': dataset_util.bytes_feature(filename),
    'image/encoded': dataset_util.bytes_feature(encoded_jpg),
    'image/format': dataset_util.bytes_feature(image_format),
    'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),
    'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),
    'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),
    'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),
    'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
    'image/object/class/label': dataset_util.int64_list_feature(classes),
}))
writer.write(tf_example.SerializeToString())
writer.close()

2. 学習

ここは完全にチュートリアル通りで問題ないです。 強いて言うと、ディレクトリ構造をチュートリアルに合わせて置くという点と、時間がかかるので必要に応じてpipeline.configのnum_stepsを小さくするか学習スクリプトで--num_train_stepsを指定するかです。また、ノートブックでGPUを別途使用していたり、バッチサイズが大きかったりするとエラーが出るので注意しましょう。 ちなみに、学習スクリプトとobject detectionのコードを見るとわかるのですが、中身は以下のようになっているので、このtrain_loopの中身を追っていくと詳細がわかります。

with strategy.scope():
    model_lib_v2.train_loop(
        pipeline_config_path=str(pipeline_config_path),
        model_dir=str(model_dir),
        train_steps=1000)

学習の様子を見るには、tensorboard --logdir=models/my_ssd_resnet50_v1_fpnでtensorboardを起動し、gcloud compute ssh <インスタンス名> -- -L 6006:localhost:6006のようにSSHポートフォワーディングを使ってブラウザから見られるようにすると良いです。 以下のような様子が見られます。

f:id:nmu0:20200814012917p:plain

3. 推論

まず、exporter_main_v2.pyを使ってモデルをエクスポートしましょう。ここでの注意点は、チュートリアルにも書かれていますがTensorflow 2.2だとTypeError: Expected Operation, Variable, or Tensor, got level_5というエラーが出るのでTensorflowの元のコードを書き換える必要があるということです。 もしかしたら2.3では直っているかもしれません。

このエクスポートしたモデルを使い、Object Detection From TF2 Saved Modelに従って推論を行います。 警視庁で公開されているサンプル免許証を無理やり加工してdetectionすると以下のようになり、すこし枠が大きいですが、免許証の表面と正しく判定されました。

f:id:nmu0:20200814013905p:plain:w300
「運転免許の更新等運転免許に関する諸手続について」(警察庁)(https://www.npa.go.jp/policies/application/license_renewal/index.html)を加工して作成

detection結果が表示されない場合は、viz_utils.visualize_boxes_and_labels_on_image_arraymin_score_threshを下げてみましょう。それでも何も表示されない場合は学習段階に問題がある可能性があります。例えば、参考資料に掲載した5枚のラバーダック画像で上記の学習ステップを試してみたのですが、閾値をかなり下げないと何も表示されませんでした。閾値を下げると表示されたので、ラベルの設定などは間違っていないことがわかりました。おそらく、参考資料の例とは異なりfinetuningをしているため、5枚だとデータが足りないのだと思います。(Object Detectionのコードをまだ良く見ていないので、違っていたら申し訳ないです)

まとめ

AI Platform ノートブックと、Tensorflow 2によるObject Detectionを紹介させて頂きました。 私も何度か試したことがあったのですが、これまではTensorflowでのObject Detectionは公式が使いやすい形で提供していなくハードルが高かった印象があります。 今回かなり導入しやすくなりましたので、興味がある方は試してみると良いと思います。その際に本ブログ記事が参考になれば幸いです。

参考資料