模型转换基础:使用 TFLiteConverter 将 SavedModel 或 Keras 模型转换为 .tflite 格式
好,咱们今天聊聊模型转换。这是把训练好的模型搬到移动端的第一步,也是很多人容易踩坑的地方。
说白了,TensorFlow 训练出来的模型是给服务器用的,体积大、依赖多。而 .tflite 是专门为手机、嵌入式设备设计的轻量格式。怎么把前者变成后者?靠的就是 TFLiteConverter。
转换前的准备工作
动手之前,先确认两件事:
- 你的模型是 Keras 的
.h5或.keras格式 - 或者是 SavedModel 格式(一个文件夹,里面有
saved_model.pb)
我个人习惯用 Keras 格式,因为代码更简洁。但如果你从 TF Hub 下载模型,基本都是 SavedModel。
方法一:从 Keras 模型转换
这是最常用的方式。假设你有一个训练好的分类模型:
import tensorflow as tf
# 加载 Keras 模型
model = tf.keras.models.load_model('my_model.h5')
# 创建转换器
converter = tf.lite.TFLiteConverter.from_keras_model(model)
# 执行转换
tflite_model = converter.convert()
# 保存到文件
with open('model.tflite', 'wb') as f:
f.write(tflite_model)
嗯,就这么几行代码。但注意,converter.convert() 返回的是字节数据,不是文件对象。你得自己写文件。
方法二:从 SavedModel 转换
如果你拿到的是 SavedModel 格式:
converter = tf.lite.TFLiteConverter.from_saved_model('saved_model_dir')
tflite_model = converter.convert()
这里有个坑——SavedModel 目录里可能包含多个签名(SignatureDef)。默认情况下,转换器会选第一个。如果你想指定某个签名,可以传 signature_keys 参数。
量化:让模型更小更快
直接转换出来的 .tflite 模型,精度还是 float32。对于移动端来说,这太大了。我们通常要做量化。
最常用的是 动态范围量化:
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()
这样模型大小能减少约 4 倍,推理速度提升 2-3 倍。精度损失?一般不到 1%。
如果你需要更极致的压缩,可以用 全整数量化。但这需要校准数据:
def representative_dataset():
for _ in range(100):
data = np.random.randn(1, 224, 224, 3).astype(np.float32)
yield [data]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
tflite_quant_model = converter.convert()
验证转换结果
转换完别急着部署。先跑一下推理,看看结果对不对:
# 加载 TFLite 模型
interpreter = tf.lite.Interpreter(model_content=tflite_model)
interpreter.allocate_tensors()
# 获取输入输出张量
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
# 准备测试数据
test_input = np.random.randn(1, 224, 224, 3).astype(np.float32)
# 推理
interpreter.set_tensor(input_details[0]['index'], test_input)
interpreter.invoke()
output = interpreter.get_tensor(output_details[0]['index'])
print('推理结果:', output)
对比一下原始模型的输出。如果差异在可接受范围内,那就没问题。
常见问题与避坑
| 问题 | 原因 | 解决方法 |
|---|---|---|
转换时报错 Unsupported ops |
模型里用了 TFLite 不支持的算子 | 启用 converter.target_spec.supported_ops 添加 Flex 算子 |
| 转换后模型变大 | 没有启用量化 | 添加 converter.optimizations = [tf.lite.Optimize.DEFAULT] |
| 推理结果全为 0 | 输入数据没有归一化 | 检查输入范围,TFLite 模型通常期望 [0,1] 或 [-1,1] |
| 转换速度很慢 | 模型太大或校准数据集太大 | 减少校准数据量,100 张图片通常足够 |
总结一下
模型转换其实不复杂,核心就三步:
- 加载模型(Keras 或 SavedModel)
- 创建转换器并设置量化参数
- 保存 .tflite 文件
但细节决定成败。量化参数、输入输出类型、算子兼容性——这些都要心里有数。你想想看,如果转换后模型在手机上跑不起来,前面所有工作都白费了。
下一章咱们聊聊如何在 Android 上加载和运行这个 .tflite 模型。到时候我会分享一个我在项目里踩过的坑——关于内存泄漏的。