Closed kyakuno closed 1 year ago
入出力画像のリサイズについてメモ
画像のアスペクト比を "維持せずに" リサイズを行っています。 アスペクト比を維持したままだと、パディング部分も推論されてしまい、良好な結果が得られません。
学習モデル .tflite(int8) 版について [03/10 14:45 現在]
COCO2017データセット 5000枚で 学習した (int8)版の学習モデルの精度が良くありません。
ADD U2Net #47 こちらのissueの内容を参考に、再度学習モデルの生成を行ってみます。
~~残りの作業 ・推論フレームワーク ailia-TF runtime を使えるようにする (※なぜかailia_tflite.dll が見つからないエラーが出る) ・(int8)版 (float)版の .tflite 学習モデル 再生成
↓ ・Readme等ドキュメントを作成し、GitHubへ~~
(メモ) ・onnx2tfを用いて onnx → .tflite (float32)(int8) へ変換
midas.onnx の入力は dynamic dimension になっているので、-ois input:1,3,384,384
オプションが必要。
また、saved_modelの出力のためには -dgc
オプション も必要
結果として、onnx2tf -i midas.onnx -ois input:1,3,384,384 -dgc
のコマンドで、.tflite(float32) 及び saved_model が出力される
しかし、onnx2tf を用いて 生成した .tflite(float32) モデルは、ailia-tf runtime で推論しようとするとエラーが出る。 公式のTFならエラーは出ない。
~”原因調査中"~
エラーの内容
raise AiliaTFLiteError(f"ailia tflite runtime error "+detail, status) ailia_tflite.AiliaTFLiteError: ailia tflite runtime error (operator is not supported. (idx.2 operator.PADV2)) code:-7
PADV2については、ailia TFLite Runtime側の更新で対応しようと思いますので、ailiaでは動かなくても問題ありません。
[現状メモ] ・onnx2tf を用いて変換した .tflite(int8) のモデルで精度が出ない。 ・また、1枚の画像推論に要する時間が異様に長い(15分~)。 →再度 int8 版の モデル生成を見直してみる。
@kyakuno ・float32の精度は良好なので、いったんfloat32版のみでPRしても良いでしょうか?
@craft-c キャリブレーション画像にテスト用の入力画像を使った場合に、どのような出力が得られるか確認いただくことは可能でしょうか。キャリブレーション画像に入力画像を使うと精度が出る場合は、キャリブレーション用のデータセットを別のものにした方がいいかもしれません。tfliteは内部的に、floatで推論して、tensorのmin/maxを計算してそのレンジでint8に量子化しているため、テスト用の推論画像1枚を使って量子化して推論するのが、テスト用の画像では最も精度が出ると思います。ただし、汎化性能はなくなるので、あくまでテスト用になります。
@craft-c また、コードも確認したいため、一旦、現状でPRをいただければと思います。合わせて、convertというサブフォルダを作成し、変換に使用したスクリプトも同梱いただければと思います。
ailia-models-tflite/depth_estimation/midas/midas.py : サンプル ailia-models-tflite/depth_estimation/midas/convert/convert.sh : openvino2tensorflowの呼び出しスクリプト ailia-models-tflite/depth_estimation/midas/convert/quantize.py : 量子化スクリプト(キャリブレーションディレクトリは引数で与える)
処理時間については、Google公式のtensorflowがIntelに対応していないために重いだけですので、ailia tflite runtimeが対応すれば高速化される想定です。
先ほど示した結果は "onnx2tf" を用いて変換したモデルなのですが、int8版の.tfliteモデルについて、僕が少し勘違いしていたかもしれません。
1枚目の図に示すように、onnx2tfを用いて midas.onnx を変換すると、saved_model内に 「midas_full_integer_quant.tffile」が生成されます。僕はこのファイルが int8版の.tfliteモデル だと思っていたのですが、これは間違いでしょうか?
要するに2枚目の画像のように、この「saved_model」+「キャリブレーション画像」を用いて量子化したファイルが int8版の.tfliteモデルになるのでしょうか?
@kyakuno あと、確認なのですが、PRは main へ向けて行えば良いですか? それとも開発用の他のブランチですか?
一応、コードの確認だけでしたら、midasブランチをGitHubへPushしてあるので、そちらから確認できます。 https://github.com/axinc-ai/ailia-models-tflite/tree/midas
気になる部分がいくつか出てきたので、PRはもう少し待ってもらえますか?
onnx2tensorflowで出てくる量子化モデルは、乱数で量子化されたモデルであるため、精度が出ない可能性があります。 そのため、kerasのsaved_modelを出力した後、pythonで量子化を行なっていただければと思います。 PRはmainへ向けて行えば問題ありません。 PRの時期については了解しました。
@kokuno1122
kokunoさんへ
初めまして。 先々週からaxellのインターンでお世話になっています。 tanikubo です。
midasサンプルにおいて、 .onnx ファイルを .tflite(int8) へ変換する作業で詰まっています。 kokunoさんが issue #47 [ADD U2Net] で同様の作業をされていたので質問があります。
・まず、私はsaved_modelの出力に onnx2tf を用いているのですが、コマンドを実行する際、引数の指定において注意する点はありますか? 私はmidas.onnx の変換に際して、onnx2tf -i midas.onnx -osd -ois input:1,3,384,384 -dgc のコマンドを実行しました。
・可能でしたら、出力されたsaved_modelを量子化する際に使用したpythonスクリプト を見せていただけませんか?
よろしくお願いします。
@craft-c はじめまして。ご連絡ありがとうございます! 私も量子化は今回のPRではじめて実施したため、知見があるわけではないので、 適切な回答できないかもしれません。 コマンドで色々試してみて、精度が出るものを採用したという感じです。
使用したコマンドは下記です。
onnx2tf -i ~.onnx -oiqt
量子化のサンプルは、こちらが参考になると思います!
@craft-c numpyでキャリブレーションのデータを作成しておいて、 それをコマンドで読み込ませる方法もあるようです。 下記のページで"-qcind"オプションを検索してみてください! https://github.com/PINTO0309/onnx2tf
データはこの方法でつくるようです https://github.com/PINTO0309/onnx2tf#6-calibration-data-creation-for-int8-quantization
@craft-c 自分も次のモデルの量子化がうまくできなくて試行錯誤してるので、 似た状況かもしれませんね。またなにか分かれば共有しますね!
了解しました! ありがとうございます。
@kokuno1122 .tflite(int8) midasサンプルにおいては、 「onnx2tf」を使う方法よりも「openvino2tensorflow」を使う方法の方が精度が出ているように思います。
@kokuno1122
また、"-qcind"オプション を使ってキャリブレーションする方法については、MEAN と STD に何を指定するのかよく理解できませんでした。
そもそも僕の場合、「onnx2tf」のやり方 + 量子化のPythonスクリプトを用いる方法こちら で精度が出ないので、saved_model の出力の時点で何か間違っているのかもしれません。
現状報告でしたm(__)m
meanとstdは画像の前処理の値だと思います。例えば、imagenetの前処理を行う場合、下記のような前処理で、値を-1.0 - 1.0に正規化します。
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
image = image / 255.0
for i in range(3):
image[:, :, i] = (image[:, :, i] - mean[i]) / std[i]
return image
meanとstdの値は学習時にどういう設定を使ったによって決まり、meanとstdに合わせた乱数を作ってキャリブレーションしているのではないかと思います。
int8モデルを用いる推論の際に、 dtype = float にすると、精度がよくなりました。
推論結果をまとめたpdfを添付します。
大きな問題点は無いように思います。 ~細かい部分を確認した後、PRを起票したいと思います。~
下記のONNXからtflite (float)とtflite (int8)を追加する。 https://github.com/axinc-ai/ailia-models/tree/master/depth_estimation/midas