Tensorflow Lite从入门到精通( 五 )


import tensorflow as tfconverter = tf.lite.TFLiteConverter.from_keras_model(model)# 启动默认的 optimizations 来量化所有固定参数(权重)converter.optimizations = [tf.lite.Optimize.DEFAULT]# 要量化可变数据(模型输入/输出 和层之间的中间体),提供 RepresentativeDataset,来估算所有可变数据的动态范围converter.representative_dataset = representative_data_gentflite_model_quant = converter.convert()现在,所有权重和可变数据都已量化,并且与原始 TensorFlow Lite 模型相比,该模型要小得多 。
但是 , 为了与传统上使用浮点模型输入和输出张量的应用保持兼容,TensorFlow Lite 转换器将模型的输入和输出张量保留为浮点,这通常对兼容性有利,但它无法兼容执行全整形运算的设备(如 Edge TPU) 。
interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)input_type = interpreter.get_input_details()[0]['dtype']print('input: ', input_type)    # <class 'numpy.float32'>output_type = interpreter.get_output_details()[0]['dtype']print('output: ', output_type)  # <class 'numpy.float32'>2、全整型量化
为了量化输入和输出张量 , 我们需要使用一些附加参数再次转换模型:
converter = tf.lite.TFLiteConverter.from_keras_model(model)converter.optimizations = [tf.lite.Optimize.DEFAULT]    # 先启动默认的optimizations将模型权重进行量化converter.representative_dataset = representative_data_gen  # 使用代表数据集量化模型中间值# 如果有任何的 ops不能量化,converter 将抛出错误converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]# 将输入和输出tensors设置为int8 类型converter.inference_input_type = tf.int8   # or tf.uint8converter.inference_output_type = tf.int8  # or tf.uint8tflite_model_quant = converter.convert()现在我们可以看到输入和输出张量现在是整数格式:
interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)input_type = interpreter.get_input_details()[0]['dtype']print('input: ', input_type)    # <class 'numpy.int8'>output_type = interpreter.get_output_details()[0]['dtype']print('output: ', output_type)  # <class 'numpy.int8'>我们来整一个栗子 , 您将从头开始训练一个 MNIST 模型、将其转换为 TensorFlow Lite 文件,并使用训练后整型量化 。最后,将检查转换后模型的准确率并将其与原始浮点模型进行比较 。

Tensorflow Lite从入门到精通

文章插图
Tensorflow Lite从入门到精通

文章插图
# -*- coding:utf-8 -*-# Author:凌逆战 | Never# Date: 2022/10/12"""整型量化"""import logging# 只显示bug不显示 warninglogging.getLogger("tensorflow").setLevel(logging.DEBUG)import tensorflow as tfimport numpy as np# 加载 MNIST 数据集mnist = tf.keras.datasets.mnist(train_images, train_labels), (test_images, test_labels) = mnist.load_data()# Normalize 输入图像,使每个像素值在0到1之间train_images = train_images.astype(np.float32) / 255.0test_images = test_images.astype(np.float32) / 255.0# 搭建模型结构model = tf.keras.Sequential([    tf.keras.layers.InputLayer(input_shape=(28, 28)),    tf.keras.layers.Reshape(target_shape=(28, 28, 1)),    tf.keras.layers.Conv2D(filters=12, kernel_size=(3, 3), activation='relu'),    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),    tf.keras.layers.Flatten(),    tf.keras.layers.Dense(10)])model.compile(optimizer='adam',              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),              metrics=['accuracy'])model.fit(train_images, train_labels, epochs=5, validation_data=https://www.huyubaike.com/biancheng/(test_images, test_labels))# 下面是一个没有量化的转换后模型 -------------------------------converter = tf.lite.TFLiteConverter.from_keras_model(model)tflite_model = converter.convert()# 下面是全整型量化 -----------------------------------------def representative_data_gen(): for input_value in tf.data.Dataset.from_tensor_slices(train_images).batch(1).take(100): # 模型只有一个输入 , 因此每个数据点有一个元素 yield [input_value]converter = tf.lite.TFLiteConverter.from_keras_model(model)converter.optimizations = [tf.lite.Optimize.DEFAULT] # 先启动默认的optimizations将模型权重进行量化converter.representative_dataset = representative_data_gen # 使用代表数据集量化模型中间值# 如果有任何的 ops不能量化 , converter 将抛出错误converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]# 将输入和输出tensors设置为int8 类型converter.inference_input_type = tf.uint8 # or tf.int8converter.inference_output_type = tf.uint8 # or tf.int8tflite_model_quant = converter.convert()import pathlibtflite_models_dir = pathlib.Path("./mnist_tflite_models/")tflite_models_dir.mkdir(exist_ok=True, parents=True)# Save the unquantized/float model:tflite_model_file = tflite_models_dir / "mnist_model.tflite"tflite_model_file.write_bytes(tflite_model)# Save the quantized model:tflite_model_quant_file = tflite_models_dir / "mnist_model_quant.tflite"tflite_model_quant_file.write_bytes(tflite_model_quant)# 在TFLite模型上运行推理def run_tflite_model(tflite_file, test_image_indices): global test_images # 初始化 Interpreter interpreter = tf.lite.Interpreter(model_path=str(tflite_file)) interpreter.allocate_tensors() # 分配张量 input_details = interpreter.get_input_details()[0] # 输入 output_details = interpreter.get_output_details()[0] # 输出 predictions = np.zeros((len(test_image_indices),), dtype=int) for i, test_image_index in enumerate(test_image_indices): test_image = test_images[test_image_index] test_label = test_labels[test_image_index] # 检查输入类型是否被量化,然后将输入数据缩放到uint8 if input_details['dtype'] == np.uint8: input_scale, input_zero_point = input_details["quantization"] test_image = test_image / input_scale + input_zero_point test_image = np.expand_dims(test_image, axis=0).astype(input_details["dtype"]) interpreter.set_tensor(input_details["index"], test_image) interpreter.invoke() output = interpreter.get_tensor(output_details["index"])[0] predictions[i] = output.argmax() return predictions# 在所有图像上评估一个TFLite模型def evaluate_model(tflite_file, model_type): global test_images global test_labels test_image_indices = range(test_images.shape[0]) predictions = run_tflite_model(tflite_file, test_image_indices) accuracy = (np.sum(test_labels == predictions) * 100) / len(test_images) print('%s model accuracy is %.4f%% (Number of test samples=%d)' % ( model_type, accuracy, len(test_images)))evaluate_model(tflite_model_file, model_type="Float")# Float model accuracy is 97.7500% (Number of test samples=10000)evaluate_model(tflite_model_quant_file, model_type="Quantized")# Quantized model accuracy is 97.7000% (Number of test samples=10000)

推荐阅读