Tensorflow2 lite 模型量化

本文有不准确的地方,希望各位大佬指出。

Tensorflow Lite 和 Tensorflow Model Optimization Toolkit(Tensorflow模型优化工具包)提供了最小优化推理复杂性的工具。

对于移动和物联网 (IoT) 等边缘设备,推理效率尤其重要。这些设备在处理,内存,能耗和模型存储方面有许多限制。 此外,模型优化解锁了定点硬件 (fixed-point hardware) 和下一代硬件加速器的处理能力。

模型量化

深度神经网络的量化使用了一些技术,这些技术可以降低权重的精确表示,并且可选的降低存储和计算的激活值。量化的好处有:

  • 对现有 CPU 平台的支持。
  • 激活值得的量化降低了用于读取和存储中间激活值的存储器访问成本。
  • 许多 CPU 和硬件加速器实现提供 SIMD 指令功能,这对量化特别有益。

TensorFlow Lite 对量化提供了多种级别的对量化支持。

  • 化训练后量:Tensorflow Lite post-training quantization 量化使权重和激活值的 Post training 更简单。
  • 量化感知训练Quantization-aware training 可以以最小精度下降来训练网络;这仅适用于卷积神经网络的一个子集。

训练后量化:训练后动态范围量化、训练后整数量化、训练后float16量化

三种优化方法的各自优势和硬件条件。

下面的决策树可以帮助你确定哪种训练后量化方法最适合您的用例:

训练后动态量化:

推理时,权值由8位精度转换为浮点,并使用浮点核进行计算。此转换只进行一次并缓存以减少延迟。为了进一步改善延迟,“动态范围”操作符将基于8位范围的激活动态量化,并使用8位权重和激活执行计算。这种优化提供了接近完全不动点推断的延迟。然而,输出仍然使用浮点存储,因此动态范围运算的加速比小于全定点计算。

该方式将浮点型的权重量化为int8整型,可将模型大小直接减少75%、提升推理速度最大3倍。该方式在推理的过程中,需要将int8量化值反量化为浮点型后再进行计算,如果某些Ops不支持int8整型量化,那么其保存的权重依然是浮点型的,即部分支持int8量化的Ops其权重保存为int8整型且存在quantize和dequantize操作,否则依然是浮点型的,因而称该方式为混合量化。该方式可达到近乎全整型量化的效果,但存在quantize和dequantize操作其速度依然不够理想,支持该方式的操作如下:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
#converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]

tflite_quant_model = converter.convert()

训练后整型量化:

通过确保所有的模型数学都是整数量化的,您可以得到进一步的延迟改进、峰值内存使用量的减少,以及与只使用整数的硬件设备或加速器的兼容性。对于完全整数量化,需要通过向转换器提供样本输入数据来度量激活和输入的动态范围。

要量化可变数据(例如模型输入/输出和层间的中间层),您需要提供一个表示数据集。这是一个生成器函数,它提供了一组足以表示典型值的输入数据。它允许转换器估计所有变量数据的动态范围。(与培训或评估数据集相比,数据集不需要是唯一的。)为了支持多个输入,每个有代表性的数据点都是一个列表,列表中的元素根据它们的索引被输入到模型中。

现在所有的权值和变量数据都被量化了,并且与原来的TensorFlow Lite模型相比,该模型要小得多。但是,为了保持与传统上使用浮动模型输入和输出张量的应用程序的兼容性,TensorFlow Lite转换器将模型输入和输出张量保留在浮点数中:

我们的整型量化工具需要使用一个小型代表性数据校正集。只需为转换器提供 representative_dataset 生成器,优化参数便会对输入模型执行整型量化。

1.  为了对模型进行完全整数量化,但在没有整数实现时使用浮点操作符(为了确保转换顺利进行),请使用以下步骤:

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),
因为输入和输出仍然保持浮动,以便具有与原始浮标模型相同的接口。

'''




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
'''
但如果某些Ops未实现该方法,则转化是没问题的且其依然会自动保存为浮点型,这就要求我们的硬件支持这样的操作,为了防止这样的问题出现,我们可以在代码里添加如下语句强制检查并在Ops不支持全整型量化时进行报错!converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
'''
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()
'''
为了确保与纯整数设备(如8位微控制器)和加速器(如Coral Edge TPU)的兼容性,可以使用以下步骤对所有操作(包括输入和输出)实施完全整数量化:
从TensorFlow 2.3.0开始,我们支持InferenceInput_type和Inference_Output_type属性。
'''

这通常有利于兼容性,但它不会兼容只执行基于整数的操作的设备,例如边缘tpu。此外,如果TensorFlow Lite不包括该操作的量化实现,上述进程可能会保留浮点格式的操作。此策略允许转换完成,因此您有一个更小和更有效的模型,但同样,它将不兼容只有整数的硬件。(这个MNIST模型中的所有操作都有一个量化的实现。)所以为了确保一个端到端的整数模型,你需要更多的参数.

训练后float16量化

您可以通过量化浮动16(16位浮点数的IEEE标准)的权重来缩小浮点模型的大小。若要启用浮动16量化权重,请使用以下步骤:

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()

浮动16量化的优点如下:(1)它将模型大小减少了一半(因为所有的权重都变成了原来大小的一半)。(2)它造成的准确性损失最小。(3)它支持在GPU上,可以直接对浮动16数据进行操作,因此执行速度比浮动32次计算要快。

浮动16量化的缺点是:(1)它没有像量化一样减少延迟到定点的数学操作。(2)默认情况下,float16量化模型将在CPU上运行时“去量化”float32的权重值。(请注意,GPU不会执行这种去量化,因为它可以对float16数据进行操作。)

当在CPU运行时,半精度量化也需要像int8量化一样进行反量化到float32在进行计算,但在GPU则不需要,因为GPU可以支持float16运算,但官方说float16量化没有int8量化性价比高,因此,在实作中也需要仁者见仁智者见智了。

 还有一种量化方式:Integer only: 16-bit activations with 8-bit weights

这是一个实验量化方案。它类似于“仅整型”方案,但激活是根据它们的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量化,则模型仍然可以量化,但不支持的操作符保持在浮点数中。应该将以下选项添加到目标_spec中,以允许这样做。

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,
tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

该量化方案提供的精度改进的用例包括:*超分辨率,*音频信号处理,如噪声消除和波束形成,*图像去噪,*hdr从单一图像重建。这种量化的缺点是:由于缺乏优化的内核实现,目前的推断明显比8位全整数慢。目前,它与现有硬件加速TFLite委托不兼容。

本文包含有:

(1)tensorflow lite 实现从保存的saveModel模型转化为.tflite模型,并且实现量化的代码。

tensorflow lite提供两种量化方式,训练后量化和量化感知训练。本文只介绍训练后量化。

先后提出了 混合训练后量化----->训练后整形量化,

混合训练后量化:“混合运算”为训练后量化提供支持,该方法可量化模型参数(例如权重),但以浮点方式执行部分计算。今天,我 们很高兴宣布推出一款新工具。(我们之前发布的 “混合”训练后量化 方法可在许多情况下减少模型大小和延迟时间,但却必须进行浮点计算,这可能不适用于所有硬件加速器(如 Edge TPU ,   https://cloud.google.com/edge-tpu/ ),而只适用于 CPU。)

训练后整型量化 :整型量化是一种通用技术,可降低模型权重和激活函数的数值精度,从而减少内存并缩短延迟时间。优化模型以缩减尺寸、延时和功耗,使准确率损失不明显。(我们已推出全新的训练后整型量化方法,可让用户使用已经过训练的浮点模型,并对其进行充分量化,仅使用 8 位带符号整数(即“int8”)。凭借这一量化方案,我们可以在许多模型中获得合理的量化模型准确率,而不必重新训练依靠量化感知 (quantization-aware) 训练的模型。借助这一新工具,模型大小将缩小为原来的 1/4,却能得到更大的 CPU 速度提升。此外,Edge TPU 等固定点硬件 (fixed point hardware) 加速器也将能运行这些模型。)

 

 

 

我将YOLOv4的模型进行了量化。目前存在的问题是有:

# 不指定FLAGS.quantize_mode,则为没有量化的tflite模型
 converter = tf.lite.TFLiteConverter.from_saved_model(FLAGS.weights)
# float16
  if FLAGS.quantize_mode == 'float16':
    converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_LATENCY]
    converter.target_spec.supported_types = [tf.lite.constants.FLOAT16]
    converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]
    converter.allow_custom_ops = True

# int8
  elif FLAGS.quantize_mode == 'int8':
    converter.optimizations = [tf.lite.Optimize.DEFAULT]
    converter.representative_dataset = representative_data_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
    converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]
    converter.allow_custom_ops = True
 
# 动态模型
 elif FLAGS.quantize_mode == 'for_size':
    converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
    converter.representative_dataset = representative_data_gen
    converter.allow_custom_ops = True

  tflite_model = converter.convert()
  open(FLAGS.output, 'wb').write(tflite_model)

(1)转化为tflite模型,没有实现量化,结果模型大小不变,检测速度与saveModel模型比变慢了。

(2)转化为动态量化,大小为1/4,速度和普通tflite几乎一样。

(3)转化为float16,大小1/2,速度和普通tflite几乎一样。

(4)转化int8,转化过程没有报错,但是,用模型检测是出现以下错误

return self._interpreter.AllocateTensors()
RuntimeError: tensorflow/lite/kernels/dequantize.cc:61 op_co
ntext.input->type == kTfLiteUInt8 || op_context.input->type
== kTfLiteInt8 || op_context.input->type == kTfLiteInt16 ||
op_context.input->type == kTfLiteFloat16 was not true.Node n
umber 835 (DEQUANTIZE) failed to prepare.
 

哪位大神能说一说 速度慢的原因,还有int8的那个错误呀,评论区讨论。

 

我在其他地方找到的可能的原因:

1,tflite本身的解释器对tflite模型是有加速的。

2,至于为什么量化后的模型反而效果不好,是因为post training quantized本质上计算时是将int转换成float计算的,因此中间存在量化和反量化的操作占绝了些时间。(inferencehttps://www.cnblogs.com/jiangxinyang/p/12056209.html)

 

 

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值