【模型】模型量化技术:动态范围、全整数和Float16量化

文章介绍了神经网络中三种量化技术:动态范围量化,通过训练后将权重转换为8位整数;全整数量化,确保所有算子为整数,提升效率;float16量化,利用16位浮点数减小模型大小。展示了如何在TensorFlowLite中应用这些方法并讨论了优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一 动态范围量化

二 全整数量化

三 float16量化


通常,表示神经网络的数据类型是32位浮点数(float32),这种数据类型可以提供高精度的计算,但是在计算资源和存储空间有限的设备上运行神经网络时,会带来一定的挑战,因此可以对模型进行量化处理。Int8量化是一种将神经网络权重和激活值转换为8位整数(int8)表示的技术。TensorFlow Lite转换器将已训练的浮点 TensorFlow 模型转换为 TensorFlow Lite 格式后,可以完成对这个模型的量化。

查看网络结构:netron 

技术有动态范围全整数Float16量化三种。

一 动态范围量化

训练后量化最简单的形式是仅将权重从浮点静态量化为整数(具有8位精度),推断时,权重从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()

使用动态范围算子的加速小于全定点计算

二 全整数量化

通过确保所有模型数学均为整数量化,进一步改善延迟,减少峰值内存用量,以及兼容仅支持整数的硬件设备或加速器。使用默认浮点输入/输出仅整数输入和输出在内的所有算子强制执行全整数量化的实践如下:

①  ResNet50_fp32.tflite模型

  • 代码
import tensorflow as tf
model = tf.keras.applications.ResNet50(weights='imagenet')
converter = tf.lite.TFLiteConverter.from_keras_model(model)
# 执行模型转换
tflite_model = converter.convert()
# 将转换后的模型保存为.tflite文件
with open("ResNet50_fp32.tflite", 'wb') as f:
    f.write(tflite_model)
    pass
  • 查看模型结构等信息

使用默认浮点输入/输出

ResNet50_in8.tflite模型。为了与原始的全浮点模型具有相同的接口,此 tflite_quant_model 不兼容仅支持整数的设备和加速器,因为输入和输出仍为浮点

  • 代码
import tensorflow as tf
import numpy as np
# 出于测试目的,可以使用如下所示的虚拟数据集
def representative_dataset():
    for _ in range(100):
        data = np.random.rand(1, 224, 224, 3)
        yield [data.astype(np.float32)]

model = tf.keras.applications.ResNet50(weights='imagenet')
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
# 执行模型转换
tflite_model = converter.convert()
# 将转换后的模型保存为.tflite文件
with open('ResNet50_in8.tflite', 'wb') as f:
    f.write(tflite_model)
pass
  • 查看模型结构等信息

③ 仅整数

ResNet50_in8_all.tflite模型,输入和输出在内的所有算子强制执行全整数量化。

  • 代码
import tensorflow as tf
import numpy as np
# 出于测试目的,可以使用如下所示的虚拟数据集
def representative_dataset():
    for _ in range(100):
        data = np.random.rand(1, 224, 224, 3)
        yield [data.astype(np.float32)]

model = tf.keras.applications.ResNet50(weights='imagenet')
# 输入和输出在内的所有算子强制执行全整数量化
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
converter.representative_dataset = representative_dataset
# 执行模型转换
tflite_model = converter.convert()
# 将转换后的模型保存为.tflite文件
with open('ResNet50_in8_all.tflite', 'wb') as f:
    f.write(tflite_model)
pass
  • 查看模型结构等信息

④ MobileNet_fp32.tflite模型

  • 代码
import tensorflow as tf
model = tf.keras.applications.MobileNet(weights='imagenet')
converter = tf.lite.TFLiteConverter.from_keras_model(model)
# 执行模型转换
tflite_model = converter.convert()
# 将转换后的模型保存为.tflite文件
with open("MobileNet_fp32.tflite", 'wb') as f:
    f.write(tflite_model)
    pass
  • 查看模型结构等信息

⑤  仅整数(MobileNet_in8.tflite模型)

  • 代码
import tensorflow as tf
import numpy as np
# 出于测试目的,可以使用如下所示的虚拟数据集
def representative_dataset():
    for _ in range(100):
        data = np.random.rand(1, 224, 224, 3)
        yield [data.astype(np.float32)]

model = tf.keras.applications.MobileNet(weights='imagenet')
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
converter.representative_dataset = representative_dataset
# 执行模型转换
tflite_model = converter.convert()
# 将转换后的模型保存为.tflite文件
with open("MobileNet_int8_all.tflite", 'wb') as f:
    f.write(tflite_model)
    pass
  • 查看模型结构等信息

三 float16量化

可以通过将权重量化为 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 量化的优点包括:

  1. 将模型的大小缩减一半,模型更小了;
  2. 实现最小的准确率损失;
  3. 支持可直接对 float16数据进行运算的部分委托,从而使执行速度比float32计算更快。

float16 量化的缺点包括:

  1. 延迟比对定点数学进行量化多;
  2. 通常,float16 量化模型在CPU上运行时会将权重值“反量化”为 float32。
  3. 注意:GPU 委托不会执行此反量化,因为它可以对 float16 数据进行运算。

具有 8 位权重的 16 位激活(实验性)与“仅整数”方案类似,根据激活的范围将其量化为16位,权重会被量化为8位整数。这种量化的优点是可以显著提高准确率,相比于全整数量化,会增加模型的大小。由于缺少优化的内核实现,目前的推断速度明显比8位全整数慢。目前它不兼容现有的硬件加速TFLite 委托。

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)

converter.representative_dataset = representative_dataset

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

如果模型中的部分算子不支持这一量化,模型仍然可以进行量化处理。但是,不受支持的算子会保留为浮点。要允许这一操作,将以下这个选项添加到 target_spec 中即可。

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)

converter.representative_dataset = representative_dataset

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

量化

<think>好的,我需要回答用户关于PyTorch中QInt16数据类型的表示范围及其在模型量化中的应用的问题。首先,我得确认QInt16的具体参数,比如量化位数、是否有符号、量化范围的计算方法。 根据PyTorch的文档,QInt16是有符号的16整数类型。通常,有符号整数的范围是从-2^(n-1)到2^(n-1)-1),这里n是位数,所以16位的话应该是-32768到32767。但需要考虑量化参数scalezero_point的影响。scale是缩放因子,zero_point是偏移量,用来将浮点数映射到整数范围。 接下来是应用部分。用户可能想知道为什么选择QInt16而不是其他类型,比如QInt8。QInt16相比QInt8有更高的精度,因为它的动态范围更大,适合对精度要求较高的场景。但计算量内存占用也会增加,所以需要权衡。应用场景可能包括需要较高精度的模型推理,或者在量化模型精度下降过多时采用QInt16来缓解。 还需要检查引用内容。引用[3]提到使用torch.qint8进行动态量化,但用户问的是QInt16,所以需要指出PyTorch目前主要支持QInt8,而QInt16可能需要自定义实现或使用其他框架的支持。需要确认PyTorch是否原生支持QInt16,如果支持的话,应该给出具体的模块或方法;如果不支持,可能需要提到这一点,并解释可能的替代方案。 另外,用户的问题可能涉及到如何在实际代码中使用QInt16,但由于PyTorch的量化模块如DynamicQuantizedLinear默认使用QInt8,可能需要引用相关文档或说明。例如,在引用[1]中的示例代码使用的是torch.qint8,所以QInt16可能需要不同的处理方法,或者可能不被直接支持。 最后,生成相关问题时要围绕量化数据类型的选择、不同位数的权衡、PyTorch中的具体实现方法等方面展开,确保问题具有实际参考价值,帮助用户进一步探索。</think>### PyTorch中QInt16数据类型的表示范围 在PyTorch模型量化中,**QInt16**是一种16位有符号整数数据类型,其表示范围由量化参数(`scale``zero_point`)决定。具体范围如下: 1. **理论范围** 对于16位有符号整数,数值范围为: $$-2^{15} \leq x \leq 2^{15}-1$$ 即 **-32768 到 32767**。 2. **实际量化范围** 实际应用中,数值范围通过量化公式映射到浮点数: $$x_{\text{float}} = (x_{\text{int}} - \text{zero_point}) \times \text{scale}$$ 其中: - `scale`:浮点缩放因子,决定量化步长。 - `zero_point`:整数偏移量,通常用于对齐浮点数零点。 > 例如,若`scale=0.01`且`zero_point=0`,则QInt16可表示的浮点范围为: $$-327.68 \leq x_{\text{float}} \leq 327.67$$[^1] --- ### QInt16模型量化中的应用 1. **适用场景** - **高精度需求**:相比8位量化(QInt8),QInt16提供更大的动态范围,适合对数值精度敏感的层(如部分激活函数或残差连接)。 - **硬件兼容性**:某些嵌入式设备支持16整数运算,QInt16可适配此类硬件。 2. **PyTorch实现特点** - **动态量化**:PyTorch默认支持`torch.qint8`(如`quantize_dynamic`函数),而QInt16需自定义量化逻辑或依赖第三方库[^3]。 - **静态量化**:需手动定义量化配置(如`QConfig`),并校准模型以确定`scale``zero_point`。 3. **性能权衡** - **优点**:减少模型内存占用(相比FP32),同时保留较高精度。 - **缺点**:计算效率低于QInt8,且PyTorch原生支持的算子有限[^2]。 --- ### 示例代码(自定义QInt16量化) ```python import torch import torch.nn.quantized as nnq # 自定义量化参数 scale = 0.01 zero_point = 0 dtype = torch.qint16 # 量化张量 float_tensor = torch.randn(10) * 100 quantized_tensor = torch.quantize_per_tensor(float_tensor, scale, zero_point, dtype) # 反量化 dequantized_tensor = quantized_tensor.dequantize() ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jackilina_Stone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值