赞
踩
TensorFlow Lite的量化类型如下:
以下是上述量化方法在部分模型上的延迟和准确性实验结果:
1. 训练后量化
训练后量化(Post-training quantization)是一种对浮点TensorFlow模型做转换的技术,可以减小模型尺寸,同时还可以改善模型在CPU和硬件加速器上的延迟,而模型精度几乎不会降低。TensorFlow Lite转换器可以对已训练的浮点TensorFlow模型做量化,将其转换为TensorFlow Lite格式。
以下决策树可以帮助确定不同情况适用哪种训练后量化方法:
动态范围量化是训练后量化的最简单形式,仅将权重从浮点数静态量化为整数,其精度为8比特:
- import tensorflow as tf
- converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
- converter.optimizations = [tf.lite.Optimize.DEFAULT]
- tflite_quant_model = converter.convert()
执行推理时,权重从8比特精度转换为浮点,并使用浮点内核进行计算。此转换仅做一次,然后将转换结果缓存以减少延迟。
为了进一步改善延迟,动态范围算子根据激活数值范围将其动态量化为8比特,并使用8比特权重和激活执行计算。动态范围量化后的模型能达到全定点推理的延迟性能。但是,输出仍使用浮点存储,因此,动态范围量化的性能提升小于全定点计算。
纯整数量化可以进一步改善延迟,减少峰值内存使用量,并与纯整数硬件设备或加速器兼容性。使用纯整数量化时,需要将输入数据样本提供给转换器,测量激活和输入的动态范围。请参考以下代码中使用的Representative_dataset_gen()函数。
在对模型进行纯整数量化时,有些算子可能没有整数实现,只能使用浮点算子。为确保转换顺利进行,这时可以使用带浮点回退的整数(使用默认的浮点输入/输出),步骤如下:
- import tensorflow as tf
- converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
- converter.optimizations = [tf.lite.Optimize.DEFAULT]
- def representative_dataset_gen():
- for _ in range(num_calibration_steps):
- # Get sample input data as a numpy array in a method of your choosing.
- yield [input]
- converter.representative_dataset = representative_dataset_gen
- tflite_quant_model = converter.convert()
这里的tflite_quant_model与纯整数设备(例如8位微控制器)和加速器(例如Coral Edge TPU)不兼容,因为输入和输出仍为浮点,与原来的纯浮点模型接口相同。
TensorFlow Lite的微控制器和加速器用例一般都是纯整数模型。为确保与纯整数设备和加速器兼容,可以使用以下步骤为所有操作(包括输入和输出)强制执行纯整数量化:
- import tensorflow as tf
- converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
- converter.optimizations = [tf.lite.Optimize.DEFAULT]
- def representative_dataset_gen():
- for _ in range(num_calibration_steps):
- # Get sample input data as a numpy array in a method of your choosing.
- yield [input]
- converter.representative_dataset = representative_dataset_gen
- converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
- converter.inference_input_type = tf.int8 # or tf.uint8
- converter.inference_output_type = tf.int8 # or tf.uint8
- tflite_quant_model = converter.convert()
还可以通过将权重量化为float16(16位浮点数的IEEE标准)来减小浮点模型的尺寸。可通过以下步骤启用float16量化:
- import tensorflow as tf
- converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
- converter.optimizations = [tf.lite.Optimize.DEFAULT]
- converter.target_spec.supported_types = [tf.float16]
- tflite_quant_model = converter.convert()
float16量化的优点是可以将模型尺寸减小一半,因为所有32位浮点权重都变成其原始尺寸的一半。而且,精度损失也最小。支持某些可以直接对float16数据进行操作的委托(例如GPU delegate),因此执行速度比float32计算快。float16量化的缺点是延迟改善效果不如定点量化。默认情况下,float16量化模型在CPU上运行时将权重值反量化到float32。 (请注意,GPU delegate不会执行反量化,因为GPU delegate可以对float16数据进行操作。)
纯整数量化的另一个实验方案是8比特权重16比特激活。该方案与纯整数量化方案相似,但是根据激活的范围将其量化为16位,将权重量化为8位整数,将偏置量化为64位整数,也称为16x8量化。这种量化方案的主要优点是可以显着提高准确性,但只会些微增加模型尺寸。
- import tensorflow as tf
- converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
- def representative_dataset_gen():
- for _ in range(num_calibration_steps):
- # Get sample input data as a numpy array in a method of your choosing.
- yield [input]
- converter.representative_dataset = representative_dataset_gen
- converter.optimizations = [tf.lite.Optimize.DEFAULT]
- converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
- tflite_quant_model = converter.convert()
如果模型中的某些算子不支持16x8量化,仍可以对模型进行量化,但不支持的算子仍使用浮点数。以下选项应添加到target_spec中以允许此操作。
- converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
- tf.lite.OpsSet.TFLITE_BUILTINS]
这种量化方法的缺点是,由于缺乏优化的内核实现,目前的推理速度明显比8比特纯整数量化模型慢。而且。目前这种量化方法不能与现有的硬件加速TFLite delegate兼容。
由于权重是在训练后量化的,因此可能会导致准确性下降,这对较小网络尤其明显。TensorFlow Lite模型库中为特定网络提供了预训练(Pre-trained)的完全量化模型。关键是要检查量化模型的准确性,保证准确性的下降在可接受的范围内。
如果准确性下降过大,可以考虑使用量化感知训练(quantization aware training)。但是,使用量化感知训练需要在模型训练时修改模型,添加伪量化节点。训练后量化技术则使用已有的预训练模型。
2. 训练后动态范围量化
TensorFlow Lite在模型从tensorflow graphdefs转换为TensorFlow Lite flat buffer格式时,支持将权重转换为8比特精度。动态范围量化使模型尺寸减少了4倍。此外,TFLite支持对激活进行即时(on the fly )量化和反量化,这样就可以使用量化kernel,实现更快计算速度,并在图的不同部分混合浮点kernel和量化kernel。
在这种量化方式中,激活始终以浮点保存。对于支持量化kernel的算子,激活将在处理之前动态量化为8比特精度,并在处理后反量化为浮点精度。视转换的模型不同,这种处理方式可以提供比纯浮点计算更快的速度。
与量化感知训练相反,动态范围量化在训练后对权重进行量化,并在推理时对激活进行动态量化。因此,模型权重不会重新训练以补偿量化引起的误差。关键是检查量化模型的准确性,确保量化导致的准确性下降在可接受范围内。
使用TFLiteConverter,可以将训练后的模型转换为TensorFlow Lite模型。未量化的模型文件保存在mnist_model.tflite中。
- converter = tf.lite.TFLiteConverter.from_keras_model(model)
- tflite_model = converter.convert()
- tflite_models_dir = pathlib.Path("/tmp/mnist_tflite_models/")
- tflite_models_dir.mkdir(exist_ok=True, parents=True)
- tflite_model_file = tflite_models_dir/"mnist_model.tflite"
- tflite_model_file.write_bytes(tflite_model)
要对导出的模型进行量化,应设置优化标志,针对模型尺寸进行优化。量化的模型文件保存mnist_model_quant.tflite中。
- converter.optimizations = [tf.lite.Optimize.DEFAULT]
- tflite_quant_model = converter.convert()
- tflite_model_quant_file = tflite_models_dir/"mnist_model_quant.tflite"
- tflite_model_quant_file.write_bytes(tflite_quant_model)
量化的模型文件的尺寸是未量化的模型文件的约1/4。
- total 214M
- -rw-rw-r-- 1 colaboratory-playground 50844828 44K Jun 23 06:04 mnist_model_quant_f16.tflite
- -rw-rw-r-- 1 colaboratory-playground 50844828 24K Jun 23 06:12 mnist_model_quant.tflite
- -rw-rw-r-- 1 colaboratory-playground 50844828 83K Jun 23 06:12 mnist_model.tflite
- -rw-rw-r-- 1 colaboratory-playground 50844828 44M Jun 23 06:10 resnet_v2_101_quantized.tflite
- -rw-rw-r-- 1 colaboratory-playground 50844828 171M Jun 23 06:09 resnet_v2_101.tflite
使用TensorFlow Lite Interpreter可以运行TensorFlow Lite模型。首先,分别将未量化模型和量化模型加载到Interpreter:
- interpreter = tf.lite.Interpreter(model_path=str(tflite_model_file))
- interpreter.allocate_tensors()
- interpreter_quant = tf.lite.Interpreter(model_path=str(tflite_model_quant_file))
- interpreter_quant.allocate_tensors()
然后,以interpreter和interpreter_quant分别调用evaluate_model,得到准确率分别为0.9262和0.9264。
- print(evaluate_model(interpreter))
- print(evaluate_model(interpreter_quant))
3. 训练后整数量化
在将TensorFlow转换为TensorFlow Lite的flat buffer格式时,TensorFlow Lite支持将模型权重和激活转换为8比特整数。这样可将模型尺寸减少4倍,并将模型在CPU上的性能提高3到4倍。此外,纯整数硬件加速器可以直接运行这种全量化模型。
与训练后的“即时”(on-the-fly)量化(仅将权重存储为8比特整数)不同,训练后整数量化会在模型转换过程中静态量化所有权重和激活。
使用TFLiteConverter,可以将训练后的模型转换为TensorFlow Lite模型。未量化的模型文件保存在mnist_model.tflite中,其中的所有参数数据都是32位浮点数。
- converter = tf.lite.TFLiteConverter.from_keras_model(model)
- tflite_model = converter.convert()
- tflite_models_dir = pathlib.Path("/tmp/mnist_tflite_models/")
- tflite_models_dir.mkdir(exist_ok=True, parents=True)
- tflite_model_file = tflite_models_dir/"mnist_model.tflite"
- tflite_model_file.write_bytes(tflite_model)
要对导出的模型进行量化,应设置优化标志,针对模型尺寸进行优化。
converter.optimizations = [tf.lite.Optimize.DEFAULT]
为了创建具有准确动态激活范围的量化值,需要提供数据集样本。为了支持多个输入,每个样本数据点都是一个列表,并且列表中的元素依其索引被输入进模型。
- mnist_train, _ = tf.keras.datasets.mnist.load_data()
- images = tf.cast(mnist_train[0], tf.float32) / 255.0
- mnist_ds = tf.data.Dataset.from_tensor_slices((images)).batch(1)
- def representative_data_gen():
- for input_value in mnist_ds.take(100):
- # Model has only one input so each data point has one element.
- yield [input_value]
-
- converter.representative_dataset = representative_data_gen
最后,将模型转换为TensorFlow Lite格式,量化的模型文件保存mnist_model_quant.tflite中。
- tflite_model_quant = converter.convert()
- tflite_model_quant_file = tflite_models_dir/"mnist_model_quant.tflite"
- tflite_model_quant_file.write_bytes(tflite_model_quant)
量化的模型文件的尺寸是未量化的模型文件的约1/4。
- -rw-rw-r-- 1 yashkatariya 10086651 25K Jun 23 06:07 mnist_model_quant.tflite
- -rw-rw-r-- 1 yashkatariya 10086651 83K Jun 23 06:06 mnist_model.tflite
模型现在应该完全量化了(其实还没有)。但是,如果转换的模型包含TensorFlow Lite无法量化的任何操作,则这些操作仍以浮点方式执行。如此一来,就可以完成模型转换,转换后的模型与某些需要全整数量化的ML加速器不兼容。同样,默认情况下,转换后的模型仍使用浮点输入和输出,这也与某些加速器不兼容。
因此,要确保转换后的模型得到完全量化(如果转换器遇到无法量化的操作,则使转换器抛出错误),并以整数作为模型的输入和输出,则需要使用以下附加配置再次转换模型:
- 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_quant = converter.convert()
- tflite_model_quant_file = tflite_models_dir/"mnist_model_quant_io.tflite"
- tflite_model_quant_file.write_bytes(tflite_model_quant)
新的量化模型使用量化的输入和输出,可与更多的加速器兼容,例如Coral Edge TPU。
现在处理的两个TensorFlow Lite模型中,tflite_model_file是仍使用浮点参数的转换模型,tflite_model_quant_file是通过全整数量化转换的模型,包括uint8输入和输出。
使用TensorFlow Lite Interpreter可以运行TensorFlow Lite模型。首先,分别将未量化模型和量化模型加载到Interpreter:
- interpreter = tf.lite.Interpreter(model_path=str(tflite_model_file))
- interpreter.allocate_tensors()
- interpreter_quant = tf.lite.Interpreter(model_path=str(tflite_model_quant_file))
- interpreter_quant.allocate_tensors()
然后,以interpreter和interpreter_quant分别调用evaluate_model,得到准确率基本没有变化。
- print(evaluate_model(interpreter))
- print(evaluate_model(interpreter_quant))
4. 训练后float16量化
在将TensorFlow转换为TensorFlow Lite的flat buffer格式时,TensorFlow Lite支持将权重转换为16位浮点值。这样可将模型尺寸减小2倍。某些硬件(例如GPU)原生支持这种降低精度的计算,从而实现比传统浮点计算更快的执行速度。 Tensorflow Lite GPU delegate可以配置为以训练后float16量化方式运行。转换为float16权重的模型无需额外修改就可以在CPU上运行,只需在第一次推断之前将float16权重上采样到float32。训练后float16量化可以显著减小模型尺寸,对延迟和准确性的影响也最小。
将训练后的模型转换为TensorFlow Lite模型的方法同上。要在导出时将模型量化为float16,首先要将优化标志设置为使用默认优化,然后指定float16是目标平台支持的类型:
- converter.optimizations = [tf.lite.Optimize.DEFAULT]
- converter.target_spec.supported_types = [tf.float16]
注意,默认情况下,为方便调用,转换后的模型仍将使用浮点输入和输出。输出文件尺寸减小了1/2。
- tflite_fp16_model = converter.convert()
- tflite_model_fp16_file = tflite_models_dir/"mnist_model_quant_f16.tflite"
- tflite_model_fp16_file.write_bytes(tflite_fp16_model)
运行模型的方式同上,以interpreter和interpreter_quant分别调用evaluate_model,得到准确率基本没有变化。
- interpreter = tf.lite.Interpreter(model_path=str(tflite_model_file))
- interpreter.allocate_tensors()
- interpreter_fp16 = tf.lite.Interpreter(model_path=str(tflite_model_fp16_file))
- interpreter_fp16.allocate_tensors()
- print(evaluate_model(interpreter))
- print(evaluate_model(interpreter_fp16))
参考文献
[1] https://www.tensorflow.org/lite/performance/model_optimization
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。