路径错误是TFLite转换失败的首要原因:from_saved_model必须指定含saved_model.pb的SavedModel目录,非.h5或检查点路径;需确认路径正确、无尾斜杠、Windows用原始字符串或正斜杠。

tf.lite.TFLiteConverter.from_saved_model 用错路径会直接报 FileNotFoundError
转换失败的第一大原因不是模型结构问题,而是路径不对——from_saved_model 接收的是 SavedModel 目录路径(含 saved_model.pb 和 variables/),不是 .h5 文件、不是检查点目录、也不是 Python 模块路径。
- 确认路径末尾不带斜杠,且该路径下能直接看到
saved_model.pb(不是saved_model.pbtxt) - 如果用 Keras
model.save("my_model"),默认保存的就是 SavedModel 格式,路径填"my_model"即可;若存成model.save("my_model.h5"),则不能用这个 API - Windows 下注意反斜杠转义:用原始字符串
r"C:\path\to\model"或正斜杠"C:/path/to/model",否则\t会被当制表符解析
量化时 missing input/output names 导致 converter.convert() 失败
TFLite 要求明确指定输入输出张量名,尤其在动态 shape 或多输入/输出模型中,不显式声明就容易卡在 convert() 报 KeyError 或 ValueError: Invalid tensors。
- 先用
saved_model_cli show --dir my_model --all查看真实 signature 名(常见是"serving_default")和 tensor names - 再在 converter 中指定:
converter.signature_keys = ["serving_default"] - 若需量化,必须同时设
converter.experimental_enable_resource_variables = True(TF 2.10+ 默认开启,但旧版不设会静默失败)
int8 量化后推理结果全为 0 或 nan
这不是模型坏了,而是校准数据没喂对——TFLite int8 量化依赖 representative_dataset 提供真实分布,喂空列表、单张图、或像素值没归一化到模型训练时的范围,都会让 scale 计算崩掉。
- representative_dataset 必须返回一个生成器,每次 yield 一个
(input_tensor,)元组(注意括号和逗号),输入 shape 和 dtype 必须与模型一致 - 图像类模型务必确保预处理一致:比如训练时用
tf.cast(img, tf.float32) / 127.5 - 1.0,这里就得照做,不能只除 255 - 至少提供 100–200 个样本;太少会导致 quantization parameters 偏差大,输出失真
converter.convert() 后模型体积没变小?检查是否漏了优化开关
TFLite Converter 默认不做任何优化,即使加了量化参数,若没显式启用,convert() 输出仍是 float32 的大模型。
- 必须手动开启:
converter.optimizations = [tf.lite.Optimize.DEFAULT],否则量化配置全被忽略 - int8 量化还需额外加:
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]和converter.inference_input_type = tf.int8(同理 output_type) - 某些 ops 不支持 int8(如 DynamicRNN、复杂 control flow),会 fallback 到 float32,此时模型里混有两类精度,体积下降有限——用
netron打开 .tflite 文件可直观查看 op 类型分布
最常被跳过的其实是 representative_dataset 的数据类型匹配:float32 模型喂 int8 数据、uint8 输入模型喂 float32,converter 不报错但量化完全失效。这点没法靠日志发现,得自己核对预处理链路每一步的 dtype。

















