ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

AutoML Vision Edgeが作るニューラルネットワーク

AutoML Vision Edgeがどのようなニューラルネットワークを作るのかが気になったので調べてみました。 Kaggleの犬猫分類(画像による2クラス分類)をAutoML Vision EdgeでTensoflow Liteのモデルを作り、ネットワーク構造を読み出して分析しました。まだ、完全に理解したわけではないので間違っている所もありそうでうが、雰囲気がつかめたのでまとめてみます。

準備

データを用意する。

ここから、犬と猫の画像をそれぞれ2000枚選びました。
https://www.kaggle.com/c/dogs-vs-cats

データをAutoMLで扱えるようにする。

この2つを見ればだいたいわかります。

ディレクトリに分けた画像をzipにして4000枚アップロードしたところ、ディレクトリ構造は認識してくれず、結局手で4000枚ラベル付けしました。ラベル付けのUIはあまり使いやすくなかったです。まずは500枚くらいアップロードして、作戦を考えた方が良いでしょう。今回であれば、先に犬の画像を2000枚アップロードし全てにdogのラベルをつけた後、猫の画像を2000枚アップロードして未分類の物を全てcatにすれば楽でした。自力でラベル付けした時点で少なくとも10枚は間違っていたのですが、今回は精度はあまり興味が無いのでこのまま進みました。

モデルをトレーニングする。

トレーニングの方法はここの通りに進めればOKです。
https://qiita.com/shinkoizumi0033/items/4ae75e0bebb2848cbd54

上で準備した同じデータセットに対して、Lowest latency、Best Trade-off、Higher accuracyの設定でそれぞれトレーニングしました。トレーニングは1時間半程度(1時間では終わらなかった)で終わり、メールが届くのでそのリンク先を開くと結果がみれます。

f:id:natsutan:20190504101230p:plain

精度が悪いのは、上に書いたようにデータセットがすでに間違っているからだと思います。

モデルをダウンロードする。

訓練が終わった後、、AutoML Visionの画面からモデルを選択し、PREDICTのタブをクリックします。

f:id:natsutan:20190504101340p:plain

この画面でEXPORTをクリックすると、GCP上にデータがエクスポートされます。gsutilを使ってローカルへ持ってきましょう。

TFLiteのモデルをJSONへ変換する。

TFLiteモデルの中身は、flatbufferです。

github.com

flatbuffersをインストールして、flatc コマンドを使えるようにします。

フォーマットの定義ファイルは、wgetで持ってきましょう。

wget https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/lite/schema/schema.fbs

flatcコマンドが動けばJsonファイルができるはずです。

flatc --json --defaults-json  --strict-json  schema.fbs  -- XXXX.tflite

JSONファイルを読み込んでdotファイルを作る。

ここは自作ツールでやりました。ONNXで同じようなことをしていれば簡単にできると思います。そんなに難しくないです。需要があれば公開します。

dotファイルができれば、pngやPDFに変換して完了です。

オプションによるモデルの比較

モデルの大きさ比較

Lowest latency Best Trade-off Higher accuracy
TFliteファイルのサイズ(Kb) 548 3,179 5,851
推論速度の見積もり(ms) 22 65 105
計算のサイズ UINT8 UINT8 UINT8
層数 65 64 64

TFliteの中身を見てみましたが特に圧縮されている様子も無く、ファイルサイズがほぼパラメータのデータサイズと思って良さそうです。データの持ち方は全モデルでUINT8でした。意外にもレイヤ数はほぼ同じでした。

可視化したニューラルネットワーク

とりあえず3つ並べてみました。

f:id:natsutan:20190504104628p:plain:w200 f:id:natsutan:20190504104625p:plain:w200 f:id:natsutan:20190504104628p:plain:w200

ニューラルネットワークの基本構造

3つのモデルの構造を見てみました。基本的な構造は3つとも同じのようにみえます。

f:id:natsutan:20190504101835p:plain

ResNetに似た構造が、10~11個シーケンシャルにつなげています。これだけで5層あるので5×10で50層、最初、真ん中、最後に少し違う構造が入っていて、合計で64層のニューラルネットワークを構成しています。
Lowest latency が11個、残りの2つが10層で全体のニューラルネットワークを構成しているので、微妙なところではモデルに違いがありそうです。これが、速度、精度との問題なのか、AutoMLで使われているであろう乱数の結果による違いなのかは分かりません。もう少し、いろんなデータで試す必要がありそうです。

入力層直後を除き、2DConvが全て1x1のみで、5x5等はDepthwiseConv2Dでのみ出てくるところが面白いです。

データ数の比較

3つのモデルについて、先頭と最後のデータ数(重みの数)を比べてみました。Best Trade-offとHigher accuracyは構造が同じで、パラメータの数だけの違いに見えます。Lowest latencyはネットワーク構成が違い、パラメータを大きく減らしています。Best Trade-offの半分以下です。

layer Lowest latency Best Trade-off Higher accuracy
0 Conv2D 3x3 16 Conv2D 3x3 32  Conv2D 3x3 48
1 DConv2D 3x3 16 DConv2D 3x3 32  DConv2D 3x3 48 
2 Conv2D 8 Conv2D 16  Conv2D 24 
3 Conv2D 24 Conv2D 48  Conv2D 72
4 DConv2D 3x3 24 DConv2D 3x3 48  DConv2D 3x3 72
5 Conv2D 8 Conv2D 24  Conv2D 24
6 Conv2D 24 Conv2D 72  Conv2D 72 
7 DConv2D 3x3 24 DConv2D 3x3 72 DConv2D 3x3 72
8 Conv2D 8 Conv2D 24  Conv2D 24
9 Add Add   Add
10 Conv2D 24 Conv2D 72  Conv2D 72
 
50 Add Conv2D 1152  Conv2D 1632
51 Conv2D 384 DConv2D 5x5 1152  DConv2D 5x5 1632
52 DConv2D 5x5 384 Conv2D 192  Conv2D 272
53 Conv2D 64 Add  Add
54 Add Conv2D 1152   Conv2D 1632
55 Conv2D 384 DConv2D 5x5 1152  DConv2D 5x5 1632
56 DConv2D 5x5 384 Conv2D 192  Conv2D 272
57 Conv2D 64 Add   Add
58 Add Conv2D 1152  Conv2D 1632
59 Conv2D 384 DConv2D 3x3 1152   DConv2D 3x3 1632
60 DConv2D 3x3 384 Conv2D 320   Conv2D 448
61 Conv2D 112 Conv2D 1280   Conv2D 1280
62 Conv2D 1280 Reducer   Reducer
63 Reducer FC  FC
64 FC SoftMax   SoftMax
65 SoftMax  

こうやって並べてみると、データ数が8の倍数になっているのは分かります。例えば24個のUINT8(8bit)のデータを22個にしても、速度への影響はあまりないのだと思います。ギリギリで削るというよりは、いくつかの組み合わせを試しているように見えます。おそらく、エッジ動作での速度を確保するために、クラウドで使用するAutoMLよりは制約がきつくなっていると感じます。4x4みたいなカーネルの方が精度が高かったとしても、エッジ側のライブラリが3x3と5x5にしか対応していなければ、速度がでないとかの事情はありそうです。

上には書いていないですが、アクティベーション層が全て計算が少ないReLUになっているのもエッジ動作を想定してのことだと思います。

量子化

ちゃんと調査したわけでは無いのであくまで予想ですが、量子化は2種類のフォーマットを組み合わせています。

ここに詳しく説明されていますが、まだ全部みれてません。

heartbeat.fritz.ai

A typical quantized layer

一般的なTF Liteで使われる量子化フォーマット

          "quantization": {
            "min": [
              -22.376556
            ],
            "max": [
              23.63975
            ],
            "scale": [
              0.180456
            ],
            "zero_point": [
              124
            ],

Fake Quantization

おそらく、単純にかけ算をするだけのフォーマット。

          "quantization": {
            "scale": [
              0.011161
            ],
            "zero_point": [
              0
            ],

他に気になったこと

定番のMaxpoolingやBatchNormalizationが入っていないのも気になりました。Maxpoolingに関してはResNetの構造を上手く使っているので必要なさそうですが、BatchNormalizationはあまり効果がないのかConvの計算に組み込まれて(Fuse)いるのかは良く分かりません。

まとめ

  • AutoML Vision Edgeで作ったモデルは、JSONに変換して構成を見ることができる。
  • 今回のケースでは、ResNetっぽいNNを生成している。いくつかの組み合わせから選んでいる様子。
  • エッジでの計算早くなりそうなレイヤーを組み合わせている。
  • Lowest latencyは層数こそ変わらないが、かなり重みの数を減らしている。

次は物体検出が、どのようなネットワークで構成されているかをやってみたいです。