TensorFlow Hub／MobileNetで画像分類してみた

## はじめに
TensorFlow Hub に登録されている MobileNet v1 学習済みモデルを使って CIFAR 10 の画像データを分類してみました。
TensorFlow Hub を使った実装に関する情報が少なく、いくらか試行錯誤が必要でした。
本稿では、前提知識として MobileNet v1 と転移学習について触れつつ、TensorFlow Hub の利用方法と利用価値の考察を共有します。

## MobileNet v1 とは
画像データに使われるディープラーニング手法である CNN のネットワークモデルの1つです。2017年6月に Google が発表しました。

従来の CNN は精度向上を目指して発展してきましたが、計算量が膨大になる傾向がありました。しかし、モバイルや組み込みのデバイスにおいては、僅かな精度向上を追求するより、制限された計算リソースで迅速なレスポンスを返すことの方が重要だったりします。
MobileNet v1 は、僅かな予測精度の低下はあるのもの、（扱うデータによりますが）従来の1/9程度の計算量で予測が可能になるため、その名の通りモバイル端末上の利用で有用なネットワークモデルです。

論文はこちら。
https://arxiv.org/abs/1704.04861

## TensorFlow Hub とは
2018年3月末に Google が発表した、ディープラーニングの学習済みモデルを再利用のために公開する仕組みです。
ディープラーニングの世界では転移学習（後述）という、学習済みモデルを用いて他のモデルを構築するテクニックがあります。
TensorFlow Hub のサイト（ https://tfhub.dev/ ）では、現状 Google と DeepMind が構築した様々な学習済みモデルが公開されており、その学習対象となったドメインの処理以外にも、転移学習で他ドメインの処理にも使うことができます。

※ ここで「他ドメインの処理にも使う」とは、例えば犬と猫を分類するために学習したパラメータの一部を流用して、車とバイクを分類するような事を指します。

## 転移学習とは
CNN では、浅い層（元の画像データに近い方の層）で画像のドメインによらない特徴を抽出し、深い層（分類結果に近い方の層）でドメイン固有の特徴を処理して分類を予測します。
転移学習では、浅い層について他の環境・他の学習データで学習した結果（各種パラメータ）を使い、深い層のパラメータだけ学習することで、他の環境で学習した優れた浅い層の特徴抽出精度を活用しつつ、短い学習時間で深い層のパラメータだけを学習することができます。

今回の例では、ImageNet（1,400万枚超の画像、2万種類以上の分類先）で学習したパラメータを用いて、CIFAR-10（5万枚の画像、10種類の分類先）のドメイン固有の処理の部分だけパラメータを学習します。
転移元の学習ボリュームの大きさから、相応の精度が期待できるのであれば、それだけの学習時間を節約できることのありがたさが伺い知れる気がします。

なお、似たような概念として Fine-Tuning があります。Fine-Tuning は、出力層以外のパラメータの初期値として学習済みデータを使うものの、それらも再学習します。（転移学習は出力層以外は再学習しません）

## やってみた
TensorFlow Hub から学習済みの MobileNet v1 のモデルを取得、転移学習して CIFAR-10 の画像分類を実装しました。

1000回のイテレーション、Google Colab 上での数分の学習時間、試行錯誤無しで予測精度は83.35%でした。（ここで予測精度とは、CIFAR-10 のテストデータ1万枚を分類させた結果、分類先10種類に対して的中した割合です）

参考として Kaggle の [CIFAR-10 のコンペティション](https://www.kaggle.com/c/cifar-10/leaderboard) を見ると、執筆時点で231件のエントリがあり、今回出せた精度は45位（ちょうど上位20%くらい）にあたります。（ちなみに1位は95.53%でした）

数分の学習時間、試行錯誤無し、精度の高さがウリでないモデルの MobileNet v1 であっさり上位20%の精度が出せたので、転移学習のありがたみを感じました。

※ MobileNet の真価は学習時間より予測時の計算速度だと思いますが、今回はその観点での検証はしてません。

## コードの解説
コードは、以下に公開しています。
https://colab.research.google.com/drive/1_HhEJMweAoatMif9MCDmYdOzXZSX0GmI

そのうち、TensorFlow Hubを使う部分の実装について、補足説明します。

以下のコードで、TensorFlow Hub から MobileNet v1 の学習済みモデルをロードします。

```
module = hub.Module("https://tfhub.dev/google/imagenet/mobilenet_v1_100_128/feature_vector/1")
```
このURLは、 [TensorFlow Hubのサイト](https://tfhub.dev/) の使いたいモデルのページから取得します。

URLの各パートの意味は、以下のとおりです。

* 「100」は、MobileNetのdepth multiplierが1.00であることを示します。精度を犠牲にしてももっと速い計算速度が欲しい場合は、「075」（0.75）や「050」（0.50）を選びます。
* 「128」は、128x128x3 の入力画像サイズを扱えることを意味します。他にも、160（160x160x3）, 192（192x192x3）, 224（224x224x3）があるので、扱いたい画像のサイズに近いものを選ぶと良いでしょう。
    * 今回の実装で使った CIFAR-10 の画像は 32x32x3 だったので、128x128x3 に引き伸ばして分類しました。
* 「feature_vector」は、画像分類直前の特徴量（ボトルネック特徴量）（1x1x1024）を抽出するモデル、ということです。
    * その後に全結合層をくっつけて任意の画像セットで全結合層のみを転移学習する用途に使います。
    * 他には「classification」もありますが、こちらは ImageNet の画像分類まで実施するモデルです。ImageNetと同様に画像を分類したい場合に使います。

ロードしたモデルを用いた転移学習のコードは以下です。非常にシンプルですね。

```
# 学習済みモデルで想定されているデータサイズに変換
height, width = hub.get_expected_image_size(module)
images = adjust_image(features["x"], height, width)

# 学習済みモデルによるボトルネック特徴量の算出
hub_mnv1_outputs = module(images)

# 全結合して分類先クラスごとの確率値を算出
logits = tf.layers.dense(inputs=hub_mnv1_outputs, units=10)
```

TensorFlow Hub で公開されているモデルの活用方法は、TensorFlow Hub の公式サイトでも案内されていますので、よろしければそちらもあわせてご覧ください。
https://www.tensorflow.org/hub/overview

## TensorFlow Hub のメリット（考察）
実は TensorFlow Hub を使わなくても、有名どころの Deep Learning のフレームワークは MobileNet などの学習済みモデルを簡単に利用できる仕組みを持っているものが多いです。
では、TensorFlow Hubのメリットって何なのか、考えてみました。

### 1. 公開されているモデルのバリエーションが多い

例えば [Keras](https://keras.io/ja/applications/) の場合、ImageNet の画像セットで事前学習した以下のネットワークモデルが同梱されているそうです。

* Xception
* VGG16
* VGG19
* ResNet50
* InceptionV3
* InceptionResNetV2
* MobileNet
* DenseNet
* NASNet
* MobileNetV2

TensorFlow Hub の MobileNet v1 の学習済みモデルも、ImageNet の画像セットで学習したものでした。
（全く同じ学習結果なのかは不明ですが、Keras も TensorFlow Hub もGoogle発なので、同じではないかと予想しています）

一方 [TensorFlow Hub](https://tfhub.dev/) には、本記事の執筆時点で、以下の学習済みモデルが登録されていました。

* DAN
* DELF
* ELMo
* Faster R-CNN
* I3D
* Inception ResNet V2
* Inception V1
* Inception V2
* Inception V3
* MobileNet V1
* MobileNet V2
* NASNet-A (large)
* NASNet-A (mobile)
* NNLM
* PNASNet-5 (large)
* Progressive GAN
* ResNet V1
* ResNet V2
* Transformer
* word2vec skip-gram
* Other

学習済みモデルの数が多いこと、Keras 同梱と違ってテキスト処理や動画処理のモデルもあることなど、活用の幅が広そうです。

### 2. 様々な学習済みモデルを一様・簡単に扱える
TensorFlow Hub を用いなくても Keras に入っていない学習済みモデルをインポートして利用することはできるでしょうが、配布のされ方や提供されている I/F にばらつきがあることが想定されます。

TensorFlow Hub のモジュールの I/F は統一的であり、サイト上での公開のされ方も画一的なため、便利です。また、今回の実装コードを見て分かる通り、とても簡単に使えます。

### 3. 様々なパブリッシャのモデルを利用できる（ようになるはず）
現状は tfhub.dev は Google と DeepMind が発行するモデルしか扱っていませんが、近い将来、他のパブリッシャのモデルも配置する計画になっているようです。
また、現状でも別サーバを立てれば誰でもモデルを公開することが可能です。

様々なパブリッシャから様々なモデルの優秀な学習済みデータが公開されるようになると、精度の高い学習結果を容易に活用でき、機械学習の普及を促進できそうです。

# まとめ
今後パブリッシャや公開される学習済みモデルが増え、簡単に活用できるようになると思うと、ちょっとワクワクしますね。
6月の公開から5ヶ月たった執筆時点で、思ったよりやってみた系のブログ記事が見当たりませんでしたが、これからなんですかね。
今後の発展に期待します。