toshiki814
2022年1月21日 16時26分
お世話になっております。 金田です。
現在、armadillo IoT G4用にuint8量子化したtfliteモデルを作成しました。
しかしながら、このモデルに対して、異なる画像を入力しても、出力が一定値になってしまう問題が発生しています。
"float32量子化"の場合には、出力は一定値にならず、"問題なく取得"することができます。
問題を再現するプログラムを添付いたします。
main.pyの上部に書かれているrequirementを実行していただき、main.pyを実行していただければ、問題が再現できると思います。
プログラムの流れとしては、pytorchモデルをonnx経由でtensorflowモデルに変換し、そこから量子化を行ってtfliteモデルを作成しています。
uint8量子化を行っている部分は、pt2tflite.pyファイルの143行目から165行目になります。pt2tflite.pyファイルのfloat32量子化は167行目から171行目になります。
出力が変化したかどうかは、異なる画像をモデルに二枚いれて、各出力の差の最大最小を見ています。
機械学習寄りの質問にはなってしまいますが、原因が分かる方がいましたら、助言を頂けると幸いです。
ファイル | ファイルの説明 |
---|---|
toshiki814.zip | 再現プログラム |
コメント
at_akihito.irie
入江です。
現状、正確な原因を特定できておらず申し訳ございませんが、モデルの変換に
おいてKerasを経由することで異なる入力毎に出力が変化することが確認でき
ましたので、取り急ぎ手順のみご案内します。
モデル変換のルートとしましては、Pytorch->onnx->Keras->TFLiteです。
model.onnxを生成するまでは頂いたソースコードのままです。
以下のようにonnx->Kerasの変換を行います。model.onnxへのパスは適宜読み
替えてください
import onnx from onnx2keras import onnx_to_keras onnx_model = onnx.load('/path/to/model.onnx') k_model = onnx_to_keras(onnx_model=onnx_model, input_names=['input'], change_ordering=True, verbose=False)
ここで、onnx_to_kerasの引数としてchange_ordering=True
を指定することで、
モデルの入力がchannel-first(NCHW)からchannel-last(NHWC)に変換されます。
生成したk_modelをTFLiteへ変換します。下の実行例は量子化しない例です。
converter = tf.lite.TFLiteConverter.from_keras_model(k_model) tflite_model = converter.convert() with open('./float32_via_keras.tflite', 'wb') as f: f.write(tflite_model)
量子化を行う場合は以下のように変換を行います。
データセットへのパスは適宜読み替えてください。
def representative_data_gen(): dataset_list = tf.data.Dataset.list_files('/path/to/dataset/' + "*.png") for i in range(len(os.listdir('/path/to/dataset'))): image = next(iter(dataset_list)) image = tf.io.read_file(image) image = tf.io.decode_jpeg(image, channels=3) image = tf.image.resize(image, [224, 224]) image = tf.cast(image / 255, tf.float32) image = tf.expand_dims(image, 0) ★変更点 yield [image] converter = tf.lite.TFLiteConverter.from_keras_model(k_model) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_data_gen converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.inference_input_type = tf.uint8 converter.inference_output_type = tf.uint8 tflite_model = converter.convert() with open('./uint8_via_keras.tflite', 'wb') as f: f.write(tflite_model)
representative_data_genは頂いたソースから一部変更しています。
★変更点: Kerasを経由した時にNHWCに変換したので、transposeは必要なくなりました。
checker.pyのtflite_outputも同様にinputのtransposeを削除してください。
最後に生成したモデルでcheck_outputを実行すると、当方の環境では異なる入
力毎に出力も変わるようになりましたので、お試しください。
toshiki814
at_akihito.irie
2022年1月26日 18時44分
入江です。
当方でも同じ現象が再現できました。
原因の調査に当たっておりますので、今しばらくお待ちください。
以上、よろしくお願いいたします。