YOLOv4 を tflite に convert する

のびのびラーニング
8 min readMay 13, 2020

取り組みは途中なのですが、書ける内容から書き出していきます。

今回は tflite への convert で fp16, int8 が成功、full-int8 も最終的に成功した所までです。

Prologue

_
2020 年 4 月 24 日、pjreddie さんの Beehive に何事かが起こり、彼の impl. が停止して以降、約 1 年半ぶりの commit がありました。
https://github.com/pjreddie/darknet

darknet を fork して Windows 向けの実装などを行っていた AlexeyAB さんYOLOv4 を発表したというものでした。
https://github.com/AlexeyAB/darknet

すわ Jetson TK1 などを引っ張り出して試行してみたものの、非常に巨大なネットワークのため動かず、ひとまず英傑のどなたかが TF2 向けの実装をしてくれることを待ち望んでいました。

5 月、英傑 hunglc007 さんが現れたことに気づいたので、作業を開始しました。
https://github.com/hunglc007/tensorflow-yolov4-tflite

hunglc007 さんは AlexeyAB さんの yolov4.weights を load して detection を実行するだけでなく、この weights を tflite に convert するコードまで作ってくれていました。

早速 Colab. で実行してみたところ、なんと動いてしまいました。

fp16 と int8 の quantize

_
以下、私の Colab. での手順を ipynb から抜出していきます。
試した時点での Colab. の環境は以下の通りです。

なお、ランタイムは TPU で実施しました。

!lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic

TensorFlow 関連のバージョンです。

!pip3 list | grep -i tensorflow

tensorflow 2.2.0
tensorflow-addons 0.8.3
tensorflow-datasets 2.1.0
tensorflow-estimator 2.2.0
tensorflow-gcs-config 2.1.8
tensorflow-hub 0.8.0
tensorflow-metadata 0.21.2
tensorflow-privacy 0.2.2
tensorflow-probability 0.10.0rc0

tensorflow-addons が requirement に満たないため upgrade します

!pip3 install -U tensorflow-addons

まずは AlexeyAB さんの yolov4.weights を用意します。

!wget -c -t 0 https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights

hunglc007 さんの repository を git clone します。

!git clone https://github.com/hunglc007/tensorflow-yolov4-tflite.git
%cd /content/tensorflow-yolov4-tflite/

私の環境では convert_tflite.py でエラーが出たため、以下の 1 行を追記しました。

   converter = tf.lite.TFLiteConverter.from_keras_model(model)
+ converter.experimental_new_converter = False
if FLAGS.quantize_mode == 'int8':

Colab. に upload して入れ替えます。

%mv /content/convert_tflite.py ./

あとは convert を実行するだけです。

  • fp16

!time python3 convert_tflite.py --weights /content/yolov4.weights --output /content/yolov4-fp16.tflite --quantize_mode float16

  • int8

!time python3 convert_tflite.py --weights /content/yolov4.weights --output /content/yolov4-int8.tflite --quantize_mode int8

full-int8 の quantize

_
しかし full-int8 の convert ではエラーになってしまいました。

!time python3 convert_tflite.py --weights /content/yolov4.weights --output /content/yolov4-full-int8.tflite --quantize_mode full_int8 --dataset data/dataset/val2017.txt

RuntimeError: Max and min for dynamic tensors should be recorded during calibration
https://github.com/tensorflow/model-optimization/issues/349

これは PINTO 先生の記事でクリアすることができました。
https://qiita.com/PINTO/items/008c54536fca690e0572

Integer Quantization を行う場合は、Float32 の数値を UInt8 に変換する
過程でキャリブレーション用の画像データを与える必要があります。

full-int8 への convert でのみ --dataset が渡されているのも、これが理由でした。
hunglc007 さんの data/dataset/val2017.txt は彼の環境の filepath が記載されているので、Colab. 用の path に replace し、/content/ 直下に upload します。

-/media/user/Source/Data/coco_dataset/coco/images/val2017/
+/content/val2017/

MS-COCO の dataset から val2017.zip を download し、同じく /content/ 直下に解凍します。

%cd /content/
!wget -c -t 0 http://images.cocodataset.org/zips/val2017.zip
!unzip val2017.zip

これで /content/val2017/ が参照され、きちんとキャリブレーションできるようになります。

%cd /content/tensorflow-yolov4-tflite/
!time python3 convert_tflite.py --weights /content/yolov4.weights --output /content/yolov4-full-int8.tflite --quantize_mode full_int8 --dataset /content/val2017.txt

処理時間は 5 〜 6 分で完了するのですが、
TF 2.2.0 では、ここで更に以下のエラーが出ました。

Didn't find op for builtin opcode 'LEAKY_RELU' version '2'

しかし、こちらの issue によると、ごく最近 LEAKY_RELU の対応が追加されている様子でした。

そこで、tf-nightly を追加で install し、再度 full-int8 の convert をしてみます。

!pip3 install -U tf-nightly

私が作業した時点では、tf-nightly の version は以下のものでした。

!pip3 list | grep -i 'tf-'

tf-estimator-nightly 2.3.0.dev2020051301
tf-nightly 2.3.0.dev20200513

これで、LEAKY_RELU のエラーも発生しなくなりました。

今回の内容は以上です。
ご精読頂き、まことにありがとうございます。

次回は、作成した tflite を RasPi4 で動作確認していきます。

--

--