Edge TPU を試す

2019年7月26日 Bee今村

はじめに

 Beeは組込み会社では知見の少ないAIにも取り組んでおり、組込みソフト開発専門の知見を活かし組込みAI(エッジAI)にも積極的に取り組んでいます。 エッジデバイスは性能が低いため、推論に時間がかかってしまう欠点がありますが、アクセラレータを使用することでエッジデバイスでもリアルタイムに推論することができます。
 今回は、Google から発売された USB Accelerator を使用してモデルの実行を試してみます。

Google Edge TPU とは

 Edge TPU はエッジデバイス向け機械学習/ディープラーニングのフレームワークTensorFlow Lite で作成したモデルの推論部分を高速化するためのコプロセッサです。 Edge TPUが搭載されたデバイスとしては、開発ボードとしてはGoogle Coral Dev Board、USB AcceleratorのColal USB Acceleratorが発売されています。

USB Accelerator

  • 高速 ML 推論
    オンボードの Edge TPU プロセッサは、毎秒0.5ワットを使用して、1秒間に4兆回の操作を実行できるそうです。
    以下は、CPU と Edge TPU の性能を比較したベンチマークです。
    ベンチマーク: https://coral.withgoogle.com/docs/edgetpu/benchmarks/
  • Debian Linux で動作
    付属の USB 3.0 Type Cケーブルで、Debian ベースの Linux システムに接続。
  • TensorFlow Lite をサポート
    TensorFlow Lite モデルを Edge TPU 上で動作するようにコンパイル可能。

Dev board

Edge TPUコプロセッサを搭載したシングルボードコンピュータ。

USB Accelerator のデモを試す

環境

  • Raspberry Pi 3 Model B
  • OS:Raspbian Stretch

    現在すでにRaspbianの新バージョンのBusterがDL出来ますが、まだ動作が不安定な所や、ライブラリ類が追いついていないこともあり、今回はStretchを利用しています。過去バージョンは以下から取得しました。
    過去バージョン : http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/

  • Google EdgeTPU USB Accelerator

対応しているデバイス

  • USB ポート付きの Linux マシンに対応
    • Debian 6.0 以上(Ubuntu 10.0+)
    • x86-64 or ARM32/64 with ARMv8

公式にサポートしているデバイスは、Raspberry Pi 2/3 Model B/B+ です。
非公式ですが Raspberry Pi Zero でも利用可能です。

デバイス設定

  1. Edge TPU ランタイムをインストールします。
  2. 
    cd ~/
    wget https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz -0 edgetpu_api.tar.gz --trust-server-names
    tar xzf edgetpu_api.tar.gz
    cd edgetpu_api
    bash ./install.sh
    								

    Edge TPU は Python3.5対応のため Python3.6以上だとデモが動かないです。
    Raspbian Stretch は標準で Python3.5 のため Stretch にしておくとすぐにデモ試せます。
    参考: https://qiita.com/iwatake2222/items/e8e29babc7e60d983093

  1. 付属のUSB3.0ケーブルを使用してアクセラレータを接続します。(すでに接続している場合は、再接続)

Edge TPU 上でモデルを実行する

サンプルの鳥分類モデルをダウンロードします。


cd ~/Downloads/
wget https://dl.google.com/coral/canned_models/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite \
https://dl.google.com/coral/canned_models/inat_bird_labels.txt \
https://coral.withgoogle.com/static/docs/images/parrot.jpg
								

オウムの画像を使用して画像分類を実行します。


# on Debian/Ubuntu Linux:
cd /usr/local/lib/python3.6/dist-packages/edgetpu/demo
# on Raspberry Pi :
cd /usr/local/lib/python3.5/dist-packages/edgetpu/demo
python3 classify_image.py \
--model ~/Downloads/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite \
--label ~/Downloads/inat_bird_labels.txt \
--image ~/Downloads/parrot.jpg
								

画像分類モデルを試してみる

約11msでリアルタイムに分類しています。

Xavier + EdgeTPU を試す

環境

  • Jetson Xavier
  • Google EdgeTPU USB Accelerator

手順

  • edgetpu のダウンロード、インストールまではデモと同じです。
  • Ubuntu の場合は Python3.6 上で edgetpu は動作します。
    # on Debian/Ubuntu Linux: cd /usr/local/lib/python3.6/dist-packages/edgetpu/demo
  • EdgeTPU実行時にエラー ModuleNotFoundError: No module named '_edgetpu_cpp_wrapper' が出る場合。
    • install.shの実行時に_edgetpu_cpp_wrapper.so のファイル名を設定してくれないことがあります。
    • 手動でファイル名を変更することで解決できます。
    
    cd /usr/local/lib/python3.6/dist-packages/edgetpu/swig/
    sudo cp _edgetpu_cpp_wrapper.cpython-35m-aarch64-linux-gnu.so _edgetpu_cpp_wrapper.so
    											

課題

  • RuntimeError: Failed to allocate tensors でデモ実行できず。

独自モデル + Raspberry Pi + EdgeTPU を試す

手順

 今回は、Quantization-aware training ※1 をしていないモデルで試してみます。

※1 Quantization-aware training
 量子化を意識したトレーニング。モデルへの入力、重みパラメータを uint8 にします。EdgeTPU の入力が uint8 のため、Quantization-aware training をしたほうがいいです。
 今回は学習済モデルの重みパラメータを uint8 に変換したモデル(Post-training quantization)を使用します。

  1. 学習済モデルの準備
  2. 下記モデルのどれかを用意。

    • SavedModel directories
    • Frozen GraphDef (models generated by freeze_graph.py)
    • Keras HDF5 models
    • Models taken from a tf.Session
  1. tfliteモデル作成
  2. tflite_convertコマンドでモデルを tflite モデルに変換します。
    Keras HDF5 models を変換する場合の例:

    
    tflite_convert ^
      --output_file=towei_tpu_test.tflite ^
      --keras_model_file=result/towei_out_cnl_WH9_tDA9.h5 ^
      --inference_type=QUANTIZED_UINT8 ^
      --input_shapes=1,94,110,3:1,5 ^
      --input_arrays=input_1,input_2
      --output_arrays=l4/BiasAdd ^
      --default_ranges_min=0.0 ^
      --default_ranges_max=9310.0
      --mean_values=0,0 ^
      --std_dev_values=255,0.027389903329752954
    											
  1. EdgeTPU 用モデル作成
  2. 作成した tflite モデルを EdgeTPU 用に変換します。
    変換には Google が提供している Web コンパイラを使用します。
    https://coral.withgoogle.com/web-compiler/

  1. 実行
  2. EdgeTPU API で推論コードを実装、実行します。

    
    #_*_ coding: utf-8 _*_
    import numpy as np
    import time
    import sys,os
    import pickle
    
    from edgetpu.basic.basic_engine import BasicEngine
    
    sys.path.append('/home/nvidia/AI/chainer/')
    
    # private library
    import lib_data_handle as dh
    
    class MODEL_DATA(object):
    	MODEL_FILE = 'result/towei_out_cnl_WH9_t7.tflite'
    	TARGET = 'WH9'
    
    def load_test_case():
    	with open('test.binaryfile', 'rb') as web:
    		l = pickle.load(web)
    		xtest, ytest, ztest, ttest = dh.get_data(l, mode='amptime', dtype='CWH', max_weight_lim=100000.)
    		# 入力層の形式に合わせる
    		xtest = np.transpose(xtest, (0,3,2,1))
    		return xtest, ytest, ztest, ttest
    
    def edgetpu_infer():
    	# load test data
    	x, y, z, t = load_test_case()
    
    	# Initialize engine.
    	engine = BasicEngine(MODEL_DATA.MODEL_FILE)
    	print('Initialize engine.')
    
    	 # Run inference.
    	array_size = engine.required_input_array_size()
    
    	for i in range(x.shape[0]):
    		print('\n------------------------------')
    		print('Run infrerence.')
    		print('  required_input_array_size: ', array_size)
    		print('  input shape: ', x.shape)
    
    		input = x[i].flatten()
    		input_uint8 = input.astype(np.uint8)
    
    		result = engine.RunInference(input_uint8)
    
    		print('------------------------------')
    		print('Result.')
    		print('Inference latency: ', result[0], ' milliseconds')
    		print('Output tensor: ', result[1])
    		print('Inference: ', np.argmax(result[1]))
    		print('Label    : ', y[i])
    
    args = sys.argv
    if __name__ == "__main__":
    	MODEL_DATA.MODEL_FILE = args[1]
    	edgetpu_infer()
    										

課題

  • EdgeTPU の推論は1入力のみ?
    • 独自モデルを EdgeTPU で推論させるには、edgetpu.basic.basic_engine を使用します。
    • 推論用の API RunInference() の第1引数に入力データ渡します。この引数が uint8 の 1次元配列のみ受け付けています。
  • 推論結果が常に0
    • 2入力のモデルに対して1入力のみ与えたせい?原因不明。

まとめ

 Google Edge TPU USB Accelerator を使ったデモを試してみました。デモはPythonのバージョンを気をつけていれば難なく動かせることができました。画像分類モデルのデモでは性能の低いエッジデバイスでもリアルタイムに推論できる処理能力の高さを実感できました。
 複雑なモデルを動かすことは難しいですが、Edge TPU APIを使って独自モデルを動かすことができるため、応用ができるのではないかと思います。