Квантованная модель TFLite по-прежнему выводит числа с плавающей запятой

У меня уже работает CNN, но теперь необходимо установить его на каком-то конкретном оборудовании. Для этого мне сказали квантовать модель, поскольку оборудование может использовать только целочисленные операции.

Я прочитал здесь хорошее решение: Как чтобы убедиться, что TFLite Interpreter использует только операции int8?

И я написал этот код, чтобы он работал:

model_file = "models/my_cnn.h5"

# load data
model = tf.keras.models.load_model(model_file, custom_objects={'tf': tf}, compile=False)

# convert
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint16 # or tf.uint8
converter.inference_output_type = tf.uint16  # or tf.uint8
qmodel = converter.convert()
with open('thales.tflite', 'wb') as f:
   f.write(qmodel)

interpreter = tf.lite.Interpreter(model_content=qmodel)
interpreter.allocate_tensors()
# predict
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
print(input_details)
print(output_details)

image = read_image("test.png")

interpreter.set_tensor(input_details[0]['index'], image)
interpreter.invoke()
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

Когда мы смотрим на напечатанный результат, мы сначала видим детали:

input_details

[{'name': 'input_1', 'index': 87, 'shape': array([  1, 160, 160,   3], dtype=int32), 'shape_signature': array([  1, 160, 160,   3], dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0), 'quantization_parameters': {'scales': array([], dtype=float32), 'zero_points': array([], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}]

output_details

[{'name': 'Identity', 'index': 88, 'shape': array([  1, 160, 160,   1], dtype=int32), 'shape_signature': array([  1, 160, 160,   1], dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0), 'quantization_parameters': {'scales': array([], dtype=float32), 'zero_points': array([], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}]

И результат квантованной модели:

...
[[0.        ]
[0.        ]
[0.        ]
...
[0.00390625]
[0.00390625]
[0.00390625]]

[[0.        ]
[0.        ]
[0.        ]
...
[0.00390625]
[0.00390625]
[0.00390625]]]]

Итак, у меня тут несколько проблем:

  1. В деталях ввода / вывода мы видим, что слои ввода / вывода - это int32, но я указал в коде uint16

  2. Также в деталях ввода / вывода мы видим, что float32 появляется несколько раз как dtype, и я не понимаю, почему.

  3. Наконец, самая большая проблема заключается в том, что вывод содержит числа с плавающей запятой, чего не должно происходить. Похоже, что модель на самом деле не преобразована в целые числа.

Как я могу действительно квантовать свой CNN и почему он не работает с этим кодом?


person Sergio Ferrer Sánchez    schedule 03.06.2021    source источник


Ответы (1)


converter.inference_input_type и converter.inference_output_type поддерживают только tf.int8 или tf.uint8, но не tf.uint16.

person sakumoil    schedule 04.06.2021
comment
как вы видите в комментарии, я пробовал также tf.uint8, но все равно не работает. :( - person Sergio Ferrer Sánchez; 07.06.2021
comment
Вы можете поделиться файлом своей модели? Какую архитектуру вы пытаетесь квантовать? Ваш репрезентативный генератор наборов данных работает? Шкала квантования и нулевая точка в ваших входных и выходных данных равны 0. - person sakumoil; 07.06.2021
comment
Нет, не могу поделиться моделью. Он защищен NDA. Архитектура - это своего рода ОС UNET. Да, генератор работает как положено. - person Sergio Ferrer Sánchez; 07.06.2021
comment
Мне удалось успешно квантовать фиктивную модель, используя приведенный выше код. input_details {'name': 'input_1', 'index': 27, 'shape': array([ 1, 160, 160, 3], dtype=int32), 'shape_signature': array([ -1, 160, 160, 3], dtype=int32), 'dtype': <class 'numpy.uint8'>, 'quantization': (0.003921546973288059, 0), 'quantization_parameters': {'scales': array([0.00392155], dtype=float32), 'zero_points': array([0], dtype=int32), 'quantized_dimension': 0}, 'sparsity_parameters': {}}] Попробуйте взглянуть на свою модель, если есть некоторые слои, которые вообще нельзя квантовать. - person sakumoil; 08.06.2021
comment
Большое спасибо, посмотрю. - person Sergio Ferrer Sánchez; 08.06.2021