フレクトのクラウドblog re:newal

http://blog.flect.co.jp/cloud/からさらに引っ越しています

Mobilenet v2とInception v4の転移学習

みなさんこんにちは。技術開発室の岡田です。

前回の投稿では、エッジデバイス上での画像認識技術についてご紹介しました。

cloud.flect.co.jp


今回は、この中で紹介した画像認識技術の一つである、Image Classification(物体認識)に用いるモデル(分類機)の作成方法についてご紹介します。

画像認識の分野では転移学習と呼ばれる方法でモデルを作成することが多いです。転移学習は既存のモデルを利用してモデル作成を行うもので、今回も転移学習を用いてモデルを作成しますが、転移学習については多くの文献が存在しています。このため転移学習を用いたモデルの作成方法自体はリファレンスを示すことにし、その中でもあまり文献が発見できなかったMobilenet v2, Inception v4のモデルを転移学習で作成する方法を説明します。また、簡単にではありますが、Mobilenet v1/v2, Inception v3/v4の性能比較もしてみたいと思います。

なお、本記事ではTensorflow のモデル作成になります。

画像認識のニューラルネットワーク

現在、主に画像認識の精度の向上や処理速度の向上、軽量化(容量削減)を目的として、多くの画像認識用のニューラルネットワークが提案されています。
画像認識においては、畳み込みニューラルネットワーク(Convolutional Neural Networks, CNN)の画像認識精度が高いことが知られており、これを組み込んだ構成のニューラルネットワークが一般的に使われるようになっています。代表的なものは下表のようなものがあります。詳細は、良くまとまっている文献が多くあります*1ので、ここでの説明は割愛させていただきます。

ネットワーク ざっくり概要
VGG16/19 畳み込み層とプーリング層から構成されるシンプルなモデル。もともとは層の深さが性能にどのような影響を与えるのかを検証することが目的でシンプルな構成としていた。(たとえば16層のVGG16や19層のVGG19を作って検証するなど) しかし、現在でもそのシンプルさから多くの技術者がこれをベースのネットワークが好んで使われることがあるとのこと。
Inception Inception モジュールと呼ばれるネットワークを重ねてCNNを作っている。このモジュール内では入力を分岐して(層を横に広げて)異なるサイズのフィルターで畳込みを行い、最後にその結果を結合する構成になっている。
ResNet residualモジュールと呼ばれるスキップ構造を導入することで層の深いネットワークにおいて効率的な学習を可能にしている。
Mobilenet 空間方向とチャネル方向に独立に畳み込みを行うことで軽量化を図ったネットワーク。エッジデバイス用にはこのネットワークを用いるのが一般的。

今回は、この中でもInceptionとMobilenetの転移学習を行います。

転移学習

機械学習における学習とはネットワークの最適な重みを探索することです。より良い精度のモデルを作成するためには、多くの学習データ、時間、計算機リソースを用い、より良い重みを探していく必要があります。しかし、多くの場合はこれを行うための十分なデータが集められない、時間や計算機リソースに制約があるなどの問題が発生します。
転移学習は、すでに学習済みのモデルを用いることでより効率的にモデルを作成する方法です。似たような問題領域で学習したモデルは、似たような新しい問題領域にも適応できるであろうという仮説のもと、学習済みモデルの一部を変更して新しい問題を解くモデルを作成します。これにより一から学習を行うよりも少ない時間で精度の高いモデルを作ることができるようになります。「将棋の羽生さんはチェスもかなり強い!(参考)それと同じ!」というのと同じようなことです。・・・と、私は説明されたことがありますが、わかったような、わからないような・・・。とはいえ、転移学習自体は論文等でも多く言及されており、実績もあるものですので、そちらをご確認いただくといいかもしれません*2

ところで、転移学習はその方法で大きく二つにわけることができます(分類の仕方によって三つの場合もある)。
一つは、学習済みのモデルを特徴抽出器として用いて、最後の出力層を学習し直すもの。もう一つは、学習済みモデルの最後の出力層より手前のいくつかの層も学習し直すもの。後者はファインチューニングと呼ばれたりもします。これらの詳細は、使いどころや注意点など含めこのページにわかりやすく記載されていますので一読されると良いかと思います。今回は、前者の学習済みのモデルを特徴抽出器として用いる方で転移学習を行います。

転移学習実践

ここから、実際に転移学習を行っていきますが、はじめに示したとおり、ここはざっくりとした説明とリファレンスのみです。

おそらく、転移学習を行う一番簡単な方法は、Googleがcodelabで公開しているTensorFlow For Poetsを実践することだと思います。これにより、Mobilenet v1, Inception v3の転移学習を行うことができます。まずは騙されたと思って、やってみてください。おそらく1時間もかからずに新しいモデルを作成することができます。このチュートリアルでは、花を分類する例題になっていますが、ご自身で分類させたい画像データをお持ちでしたら、例題を真似て適当なフォルダ構成で画像ファイルを配置してください。そして、'python -m scripts.retrain'の'--image_dir'オプションに画像データのフォルダを指定してあげれば、あなただけの新しいモデルを作成することができます。

いかがでしょうか、できましたでしょうか?
もしこれが初めて作成したモデルでしたら、結構精度高く分類してくれるので驚くのではないかと思います。

では次に、このTensorFlow For Poetsを拡張して、Mobilenet v2, Inception V4の転移学習もできるようにしていきましょう。

tensorflow-for-poets2でMobilenet v2, Inception V4の転移学習

tensorflow-for-poets2は転移学習のためのチュートリアル用のスクリプトではありますが、大変高機能です。たとえば、学習データを増幅させるData Augmentationをサポートしていたり、転移学習を高速化するためのキャッシュ機構を持っていたりします。一方で、現時点で対応しているモデルはMobilenet v1とinception v3のみであり、長い間対応モデルの追加はされていません。このため、より新しい精度の高いモデルの転移学習には使うことができません。

そこで、ここではコードを少しハックして他のモデルも使えるようにしてみることにします。ただし、言うまでもないと思いますが、これはあくまでもチュートリアルスクリプトを実験的に改変しているものです。プロダクション用途に使用できるかは別途検証が必要になることにご注意ください。また、今回は2019/7/7時点で最新のtensorflow-for-poets2のソースを対象とします。

tensorflow-for-poets2をcloneすると、scriptsというフォルダが作成されます。今回はこの中の次のファイルを改変します。

  • retrain.py

retrain.pyの改変

retrain.pyは転移学習を行う処理が記載されたスクリプトです。
色々と難しい内容が含まれていますが、今回変更する部分はcreate_model_info関数です。
この中で if architecture == 'inception_v3'などの条件分岐が記載されているのが、各転移学習の転移元のモデルを定義する部分になっています。
このため、この条件分岐のところに使いたいモデルの情報を追記すれば良さそうです。
Mobilenet v1の定義部分

  elif architecture.startswith('mobilenet_'):
    parts = architecture.split('_')
    <略>
    input_mean = 127.5
    input_std = 127.5

の後ろに次に内容を追記します。

  elif architecture.startswith('inception_v4'):
    data_url = 'https://storage.googleapis.com/download.tensorflow.org/models/inception_v4_2016_09_09_frozen.pb.tar.gz'
    bottleneck_tensor_name = 'InceptionV4/Logits/Logits/BiasAdd:0'
    bottleneck_tensor_size = 1001
    input_width = 299
    input_height = 299
    input_depth = 3
    resized_input_tensor_name = 'input:0'
    model_file_name = 'inception_v4_2016_09_09_frozen.pb'
    input_mean = 128
    input_std = 128
  elif architecture.startswith('mobilenetv2'):
    data_url = 'https://storage.googleapis.com/mobilenet_v2/checkpoints/mobilenet_v2_1.4_224.tgz'
    bottleneck_tensor_name = 'MobilenetV2/Predictions/Reshape:0'
    bottleneck_tensor_size = 1001
    input_width = 224
    input_height = 224
    input_depth = 3
    resized_input_tensor_name = 'input:0'
    model_base_name = 'mobilenet_v2_1.4_224_frozen.pb'
    model_dir_name = './'
    model_file_name = os.path.join(model_dir_name, model_base_name)
    input_mean = 127.5
    input_std = 127.5  

転移学習の開始

スクリプトの変更が完了したら、早速転移学習を行ってみたいと思います。スクリプトの実行方法はオリジナルのtensorflow-for-poet2と同じです。必要なパラメータを書き換えてください。

Inception v4 の例は次のとおりです。

python3.6 -m scripts.retrain \
  --bottleneck_dir=bottlenecks_inc4 \
  --model_dir=models/inceptionv4 \
  --summaries_dir=output/training_summaries_inc4/ \
  --output_graph=output/retrained_graph_inc4.pb \
  --output_labels=output/retrained_labels_inc4.txt \
  --architecture=inception_v4 \
  --image_dir=DATASET/TRAIN \
  --how_many_training_steps=2000


Mobilenet v2の例は次のとおりです。

python3.6 -m scripts.retrain \
  --bottleneck_dir=bottlenecks_mnv2 \
  --model_dir=models/mobilenetv2 \
  --summaries_dir=output/training_summaries_mnv2/ \
  --output_graph=output/retrained_graph_mnv2.pb \
  --output_labels=output/retrained_labels_mnv2.txt \
  --architecture=mobilenetv2 \
  --image_dir=DATASET/TRAIN \
  --how_many_training_steps=2000

推論実行

転移学習が完了したら推論を実行してうまく学習できているかを確認します。こちらもスクリプトの実行方法はオリジナルのtensorflow-for-poet2と同じです。必要なパラメータを書き換えてください。

Inception v4 の例は次のとおりです。

python3.6 -m scripts.label_image \
  --graph=output/retrained_graph_inc4.pb \
  --labels=output/retrained_labels_inc4.txt \
  --image=DATASET/TEST/Abyssinian/Abyssinian_13.jpg \
  --input_layer=input \
  --output_layer=final_result \
  --input_width=299 \
  --input_height=299

Mobilenet v2の例は次のとおりです。

python3.6 -m scripts.label_image \
  --graph=output/retrained_graph_mnv2.pb \
  --labels=output/retrained_labels_mnv2.txt \
  --image=DATASET/TEST/Abyssinian/Abyssinian_13.jpg \
  --input_layer=input \
  --output_layer=final_result \
  --input_width=224 \
  --input_height=224

どうでしょうか、ご期待の推論がなされているのではないかと思います。

性能評価

さて、せっかく転移学習でMobilenet v2もInception v4のモデルも作れるようになりましたので、Mobilenet v1, Inception v3と性能比較してみます。
データセットはObject Detectionのデータセットとしてよく参照されるOxford petを使います。このデータセットには37カテゴリーのかわいいペットの画像が200枚ずつ格納されています。今回は、トレーニング用に180枚、テスト用に20枚という内訳で分割してトレーニングを行います。
f:id:Wok:20190707232607p:plain



また、各モデルの転移元のモデルは次のものを使っています。

モデル 転移元
Inception v3 http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz
Inception v4 https://storage.googleapis.com/download.tensorflow.org/models/inception_v4_2016_09_09_frozen.pb.tar.gz
Mobilenet v1 http://download.tensorflow.org/models/mobilenet_v1_1.0_224_frozen.tgz
Mobilenet v2 https://storage.googleapis.com/mobilenet_v2/checkpoints/mobilenet_v2_1.4_224.tgz

レーニングは2000エポックで統一しています。本当なら学習曲線で確認しながらが良いですが、今回は簡易評価なので手抜きをしています。

次の表が各モデルの性能評価の結果です。

モデル accuracy precision recall f1
Inception v3 0.93 0.94 0.93 0.93
Inception v4 0.92 0.93 0.92 0.92
Mobilenet v1 0.90 0.91 0.90 0.90
Mobilenet v2 0.94 0.94 0.94 0.94

※各値はmacroの値です。

今回はMobilenet v2がすべての値で成績がよく最も良いモデルになったようです。ただし、上記のとおり、チューニング等甘いところがありますのでご参考程度と考えてください。プロジェクトで使う場合は、実際にいくつかのモデルを作成してみて、どれがユースケースに適しているかを確認して使用するようにしてください。

今回の結果のConfusion Matrixもつけておきます。字が細かくてすみません。

f:id:Wok:20190708031249p:plain
f:id:Wok:20190708031257p:plain

f:id:Wok:20190708031151p:plain
f:id:Wok:20190708031312p:plain

最後に

Image Classificationに用いるモデル(Mobilenet v1/v2, Inception v3/v4)の作成方法についてご紹介しました。作成したMobilenetのモデルは、コンバータを用いてtensorflow liteやtensorflowjsのモデルに変換してエッジデバイス上でも使うことができるようになりますので、興味があれば是非チャレンジしてみてください。(まだ計画していませんが、エッジデバイス上で動かすまでについても投稿するかもしれません。)
今回は、前回に比べていくらか技術的な内容を盛り込めたかと思います。次回もこんな感じで記載していこうと思います。

*1:たとえば、名著として名高い「ゼロから作る Deep Learning(斎藤 康毅著)」など

*2:https://arxiv.org/abs/1411.1792