Понимание параметров квантования tf.contrib.lite.TFLiteConverter - PullRequest
0 голосов
/ 22 февраля 2019

Я пытаюсь использовать квантование UINT8 при преобразовании модели тензорного потока в модель tflite:

Если использовать post_training_quantize = True, размер модели будет в 4 раза меньше, чем у исходной модели fp32, поэтому я предполагаю, что веса модели равны uint8,но когда я загружаю модель и получаю тип ввода через interpreter_aligner.get_input_details()[0]['dtype'], это float32.Выходы квантованной модели примерно такие же, как и у исходной модели.

converter = tf.contrib.lite.TFLiteConverter.from_frozen_graph(
        graph_def_file='tflite-models/tf_model.pb',
        input_arrays=input_node_names,
        output_arrays=output_node_names)
converter.post_training_quantize = True
tflite_model = converter.convert()

Ввод / вывод преобразованной модели:

print(interpreter_aligner.get_input_details())
print(interpreter_aligner.get_output_details())
[{'name': 'input_1_1', 'index': 47, 'shape': array([  1, 128, 128,   3], dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}]
[{'name': 'global_average_pooling2d_1_1/Mean', 'index': 45, 'shape': array([  1, 156], dtype=int32), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}]

Другой вариант - указать больше параметров явно: Размер моделиx4 ниже, чем исходная модель fp32, тип ввода модели - uint8, но вывод модели больше похож на мусор.

converter = tf.contrib.lite.TFLiteConverter.from_frozen_graph(
        graph_def_file='tflite-models/tf_model.pb',
        input_arrays=input_node_names,
        output_arrays=output_node_names)
converter.post_training_quantize = True
converter.inference_type = tf.contrib.lite.constants.QUANTIZED_UINT8
converter.quantized_input_stats = {input_node_names[0]: (0.0, 255.0)}  # (mean, stddev)
converter.default_ranges_stats = (-100, +100)
tflite_model = converter.convert()

Ввод / вывод преобразованной модели:

[{'name': 'input_1_1', 'index': 47, 'shape': array([  1, 128, 128,   3], dtype=int32), 'dtype': <class 'numpy.uint8'>, 'quantization': (0.003921568859368563, 0)}]
[{'name': 'global_average_pooling2d_1_1/Mean', 'index': 45, 'shape': array([  1, 156], dtype=int32), 'dtype': <class 'numpy.uint8'>, 'quantization': (0.7843137383460999, 128)}]

Итак, мои вопросы:

  1. Что происходит, когда установлен только post_training_quantize = True?т.е. почему первый случай работает нормально, а второй - нет.
  2. Как оценить средние, стандартные и диапазонные параметры для второго случая?
  3. Похоже, что во втором случае вывод модели быстрее, не так ли?зависит от того, что для ввода модели используется uint8?
  4. Что означает 'quantization': (0.0, 0) в 1-м случае и 'quantization': (0.003921568859368563, 0), 'quantization': (0.7843137383460999, 128) во 2-м случае?

Обновление:

Ответ на вопрос 4 найден Что означает «квантование» в interpreter.get_input_details ()?

1 Ответ

0 голосов
/ 28 февраля 2019

1) См. Документация .Короче говоря, эта методика позволяет получить квантованный график uint8 с точностью работы, близкой к исходной, и не требующей дальнейшего обучения квантованной модели.Однако скорость заметно меньше, чем если бы использовалось обычное квантование.

2) Если ваша модель тренировалась с нормализованным вводом [-1.0, 1.0], вам следует установить converter.quantized_input_stats = {input_node_names[0]: (128, 127)}, ипосле этого квантование входного тензора будет близко к (0.003921568859368563, 0).mean - это целочисленное значение от 0 до 255, которое отображается с плавающей точкой 0.0f.std_dev равно 255 / (float_max - float_min).Это решит одну возможную проблему

3) Вывод нейронной сети Uint8 примерно в 2 раза быстрее (в зависимости от устройства), чем вывод float32

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...