TensorFlow Lite 使用方式与典型场景:三个可运行示例
TensorFlow Lite 使用方式与典型场景:三个可运行示例
示例一:从 Keras / SavedModel 到 INT8 量化模型
import numpy as np
import tensorflow as tf
# 1. 准备模型:这里演示从 SavedModel 目录加载
# 也可以直接用 tf.keras.models.load_model 加载 .keras 文件
converter = tf.lite.TFLiteConverter.from_saved_model('saved_model_dir')
# 2. 打开默认优化,得到动态范围量化(权重 int8,激活运行时量化)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
# 3. 校准集:形状必须与模型输入一致,通常取几百条真实样本
def representative_dataset():
for _ in range(200):
# 演示用随机数,真实项目必须换成真实输入
data = np.random.rand(1, 224, 224, 3).astype(np.float32)
yield [data]
converter.representative_dataset = representative_dataset
# 4. 强制全整数算子集,并让端侧输入输出也用 uint8
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
# 5. 转换并落盘
tflite_model = converter.convert()
with open('model_int8.tflite', 'wb') as f:
f.write(tflite_model)
print('size:', len(tflite_model), 'bytes')
提示:真实项目里校准集不能用随机数,必须喂真实图片或真实特征,并且覆盖低照度、过曝、遮挡这类难例;否则量化参数会偏向训练集的平均样子,遇到边缘样本直接崩。上面这段随机数只是为了让脚本能直接跑通。
示例二:用 tflite-runtime 在树莓派上推理
import numpy as np
from tflite_runtime.interpreter import Interpreter
interpreter = Interpreter(model_path='model_int8.tflite', num_threads=4)
interpreter.allocate_tensors()
in_detail = interpreter.get_input_details()[0]
out_detail = interpreter.get_output_details()[0]
print('输入:', in_detail['shape'], in_detail['dtype'])
print('输出:', out_detail['shape'], out_detail['dtype'])
# 按模型要求准备输入:先缩放归一化,再按 dtype 转换
img = np.random.rand(224, 224, 3).astype(np.float32) # 真实项目里从摄像头取
img = (img * 255.0).astype(np.uint8)
batch = np.expand_dims(img, axis=0)
interpreter.set_tensor(in_detail['index'], batch)
interpreter.invoke()
pred = interpreter.get_tensor(out_detail['index'])
print('输出形状:', pred.shape, '最大值索引:', int(np.argmax(pred)))
这段代码最容易踩的坑是输入类型:全整数模型的输入是 uint8,如果直接塞 float32,会得到类型不匹配的报错。正确做法是先读 get_input_details() 里的 dtype,再决定是否乘 255 并取整。反过来,输出若也是 uint8,还要按量化参数(quantization 里的 scale 与 zero_point)反算回浮点,否则概率值没有意义。
示例三:Android 端挂 GPU delegate
// Kotlin 片段:先探测兼容性,再决定是否启用 GPU
val compatList = CompatibilityList()
val options = Interpreter.Options().apply {
setNumThreads(4)
if (compatList.isDelegateSupportedOnThisDevice) {
addDelegate(GpuDelegate(compatList.bestOptionsForThisDevice))
}
}
val interpreter = Interpreter(loadModelFile('model_int8.tflite'), options)
interpreter.run(inputBuffer, outputBuffer)
interpreter.close()
注意 GpuDelegate 与 Interpreter 都要在合适时机 close(),否则反复创建会泄漏显存。另外模型放在 assets 里时,不要按文件路径直接打开,应通过 AssetManager 或 Support Library 的 FileUtil.loadMappedFile 拿到 MappedByteBuffer,这样才能用上零拷贝加载。
适合与不适合的场景
- 适合:图像分类、目标检测、姿态估计、语音唤醒、关键词识别、文本向量化——这些模型结构相对固定,算子集小,量化收益明显;
- 适合:网络不稳定,或涉及隐私、数据不允许出设备的场景,离线推理是硬需求;
- 不适合:输入形状频繁变化、或含大量自定义算子的模型,端侧适配成本会远高于收益;
- 不适合:模型体积超过设备可用内存,或需要频繁整体重算的端侧大模型场景,这类需求应换用专门的端侧 LLM 运行时。

