2. 模型转换与量化基础

任务目标

本案例将完成一个最小可复现的模型转换闭环:使用Keras训练一个简单的二分类模型(基于合成数据),将其转换为TensorFlow Lite格式,并应用动态范围量化。最终产出两个文件:model_fp32.tflite(浮点模型)与model_quant.tflite(动态范围量化模型),并验证两者在相同输入下的输出一致性。

环境依赖

  • Python 3.8+
  • TensorFlow 2.12+(包含Keras与TFLiteConverter)
  • NumPy

完整实现代码

import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

# 1. 生成合成二分类数据(固定随机种子保证可复现)
np.random.seed(42)
X = np.random.randn(2000, 4).astype(np.float32)
y = (X[:, 0] + X[:, 1] - X[:, 2] * X[:, 3] > 0).astype(np.float32)

# 2. 训练一个简单Keras模型
model = Sequential([
    Dense(8, activation='relu', input_shape=(4,)),
    Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X, y, epochs=5, batch_size=32, verbose=0)

# 3. 转换为TFLite浮点模型
converter_fp32 = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_fp32 = converter_fp32.convert()
with open('model_fp32.tflite', 'wb') as f:
    f.write(tflite_fp32)

# 4. 转换为TFLite动态范围量化模型
converter_quant = tf.lite.TFLiteConverter.from_keras_model(model)
converter_quant.optimizations = [tf.lite.Optimize.DEFAULT]  # 动态范围量化
tflite_quant = converter_quant.convert()
with open('model_quant.tflite', 'wb') as f:
    f.write(tflite_quant)

# 5. 验证:使用相同输入比较两个TFLite模型的输出
def run_tflite(interpreter, input_data):
    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()
    interpreter.set_tensor(input_details[0]['index'], input_data)
    interpreter.invoke()
    return interpreter.get_tensor(output_details[0]['index'])

# 准备验证输入(取前5个训练样本)
test_input = X[:5]

# 加载并运行两个模型
interp_fp32 = tf.lite.Interpreter(model_path='model_fp32.tflite')
interp_fp32.allocate_tensors()
out_fp32 = run_tflite(interp_fp32, test_input)

interp_quant = tf.lite.Interpreter(model_path='model_quant.tflite')
interp_quant.allocate_tensors()
out_quant = run_tflite(interp_quant, test_input)

# 打印输出对比(预期输出:两组数值接近,差异在0.05以内)
print("FP32 输出:", out_fp32.flatten())
print("量化输出:", out_quant.flatten())
print("最大差异:", np.max(np.abs(out_fp32 - out_quant)))

运行方式

  1. 将上述代码保存为 convert_quant.py。
  2. 在命令行执行:python convert_quant.py。
  3. 脚本运行结束后,当前目录下应生成 model_fp32.tflite 与 model_quant.tflite 两个文件。

验证方法与通过条件

  • 文件生成验证:确认两个 .tflite 文件已生成,且 model_quant.tflite 的文件大小明显小于 model_fp32.tflite(动态范围量化通常可减小约75%的模型大小)。
  • 输出一致性验证:脚本打印的FP32与量化模型输出应数值接近。由于动态范围量化仅将权重转为int8,激活仍为浮点,因此输出差异通常小于0.05。若最大差异超过0.1,说明量化精度损失异常,需检查模型是否过大或数据分布是否异常。
  • 预期输出示例(基于固定随机种子与训练过程,实际数值可能略有不同,但差异应处于同一量级):
FP32 输出: [0.9999 0.0012 0.9987 0.0021 0.9995]
量化输出: [0.9987 0.0015 0.9979 0.0028 0.9989]
最大差异: 0.0012

关键说明

  • 动态范围量化(tf.lite.Optimize.DEFAULT)在转换时仅将权重从float32量化为int8,推理时激活值仍以浮点计算,因此无需校准数据集,适合快速压缩模型。
  • 若需进一步压缩或部署到纯整数硬件,需使用全整数量化(需提供代表性数据集进行校准),本案例不涉及。
  • 本案例使用合成数据训练模型,仅用于演示转换流程,模型本身不具备实际业务价值。