Как реализовать вывод TF Lite в Python
В исследовательских целях я пытаюсь понять, как TF Lite делает свои выводы. Меня интересует только программная логика.
Я использую TensorFlow 2.1 и TensorFlow Model Optimization 0.3.0.
В качестве примера я использую очень простую полностью подключенную сеть:
tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
tf.keras.layers.Dense(10, activation=None)
])
Я обучаю сеть по mnist с помощью обучения с квантованным осознанием.
А затем квантуйте сеть с помощью TF Lite:
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = data_generator(ds_train)
quantized_tflite_model = converter.convert()
Чтобы убедиться, что я знаю, что делаю, я сделал 3 вещи: Я использовал TF для получения выходных данных из 32-битной модели. Я использовал TF Lite, чтобы получить выходные данные от квантованной модели. Я реализовал в Python прямой проход для 32-битной модели и сравнил его результаты с предыдущими 2.
Теперь я пытаюсь понять, как реализовать прямой проход квантованной модели.
Используя интерпретатор.get_tensor_details(), я получаю следующий вывод:
{'name': 'Identity', 'index': 0, 'shape': array([ 1, 10]), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}
{'name': 'flatten_input_int8', 'index': 1, 'shape': array([ 1, 28, 28, 1]), 'dtype': <class 'numpy.int8'>, 'quantization': (0.003921568859368563, -128)}
{'name': 'sequential/quant_dense/BiasAdd', 'index': 2, 'shape': array([ 1, 10]), 'dtype': <class 'numpy.int8'>, 'quantization': (0.22868551313877106, 49)}
{'name': 'sequential/quant_dense/LastValueQuant/FakeQuantWithMinMaxVars/transpose', 'index': 3, 'shape': array([ 10, 784]), 'dtype': <class 'numpy.int8'>, 'quantization': (0.01087072491645813, 0)}
{'name': 'sequential/quant_dense/MatMul_bias', 'index': 4, 'shape': array([10]), 'dtype': <class 'numpy.int32'>, 'quantization': (4.263029768480919e-05, 0)}
{'name': 'sequential/quant_dense/BiasAdd_float', 'index': 5, 'shape': array([ 1, 10]), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}
{'name': 'flatten_input', 'index': 6, 'shape': array([ 1, 28, 28, 1]), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}
Я использую этот документ как ссылку: https://arxiv.org/pdf/1712.05877.pdf Я также читал эту страницу: https://www.tensorflow.org/lite/performance/quantization_spec
Моя текущая реализация выглядит так:
def quantization_params(index):
return tensor_details[index]['quantization'][0], tensor_details[index]['quantization'][1]
image = get_single_test_image(show_image=False)
# #### Convert input image from float32 to int8 ####
q_scale, q_zero = quantization_params(index=1)
x = image / q_scale + q_zero
# #### Flatten input ####
x = x.flatten()
# #### Dense layer ####
kernel, bias = tflite_model.interpreter.get_tensor(3), tflite_model.interpreter.get_tensor(4)
s_input, z_input = quantization_params(index=1)
s_kernel, z_kernel = quantization_params(index=3)
s_output, z_output = quantization_params(index=4)
M = s_input * s_kernel
quantized_multiplier, right_shift = quantize_multiplier_smaller_than_one(M)
dense_output = np.zeros((kernel.shape[0],), dtype=np.int32)
for i in range(dense_output.shape[0]):
for j in range(kernel.shape[1]):
dense_output[i] += int((x[j] + z_input) * (kernel[i, j] + z_kernel))
x = dense_output + bias
x = np.right_shift(x * quantized_multiplier, right_shift)
функция quantize_multiplier_smaller_than_one - это моя реализация Python для функции C здесь: https://github.com/google/gemmlowp/blob/master/doc/quantization_example.cc
Итак, мои вопросы: правильный ли это подход? Мне здесь точно не хватает расчета, что это? А также, когда у меня большая сеть, как мне узнать, как систематически использовать правильные индексы для получения параметров квантования для каждого уровня.
Большое спасибо за любой совет.
1 ответ
Наконец, я решил эту проблему, покопавшись в коде TensorFlow / Lite. Я нашел соответствующий код и изменил его, чтобы он распечатал всю необходимую информацию в текстовых файлах. Оттуда я мог разобрать все на Python и запустить Python-версию логики cpp.
Если кто-то захочет попробовать сделать то же самое, для создания решения CPP перейдите к сборке из исходников.
Точка входа в пример приложения находится здесь: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/examples/minimal
И, например, ссылочный код свертки находится здесь: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h
Наслаждайтесь (не совсем)