tensorflow-onnx
将 TensorFlow、Keras、TFLite 和 TFJS 模型转换为通用 ONNX 格式的桥
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
将 TensorFlow、Keras、TFLite 和 TFJS 模型转换为通用 ONNX 格式的桥
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。

图1:ONNX 项目官方标识
2017年,Facebook 和微软联合推出了 ONNX(Open Neural Network Exchange)标准,试图解决 AI 领域的一个老大难问题:模型训练框架和部署框架之间的困境。数据科学家们喜欢用 PyTorch、TensorFlow 等灵活的框架做实验,但生产环境往往需要 TensorRT、ONNX Runtime、OpenVINO 这类高度优化的推理引擎。tf2onnx 就是在这个背景下诞生的——它由微软工程师发起,后贡献给 ONNX 组织,专门负责将 TensorFlow 系列模型转换为通用的 ONNX 格式。
对于国内很多企业来说,这个工具解决了一个非常现实的问题:很多业务模型是基于 TensorFlow 训练的,但生产环境需要跨平台部署。tf2onnx 让这个过程变得简单可控,不需要重写模型代码,也不需要在每个平台单独维护一套训练流程。
tf2onnx 的功能远比"把 .pb 文件转成 .onnx 文件"要丰富。它支持的输入格式包括:
转换过程并非简单的"一一映射"。TensorFlow 和 ONNX 的算子集合存在差异,某些 TensorFlow 算子在 ONNX 中没有直接对应的实现。tf2onnx 内部维护了一个算子映射表(Handler Registry),对于无法直接映射的复杂算子,会尝试分解为多个基础 ONNX 算子的组合。同时,项目内置了 150+ 预置的重写规则(Rewriter),用于处理常量折叠、算子融合、布局转换(NHWC 到 NCHW)等优化。

图2:tf2onnx 项目官方标识
tf2onnx 的核心转换流程分为两个阶段:
第一阶段:Protobuf 解析。TensorFlow 的 SavedModel 和 Frozen GraphDef 都是 Protobuf 序列化格式。tf2onnx 首先将 TensorFlow 的 Protobuf 结构解析为自己内部的中间表示(IR)——一个以 Node 为节点、Tensor 为边的有向无环图(DAG)。这一阶段不做任何算子级别转换,只是把底层数据结构转成 tf2onnx 的抽象语法树。
第二阶段:图优化与算子映射。这是 tf2onnx 最复杂的部分。它首先运行一系列 Rewriter 对图进行预处理(如删除无用的 Identity 节点、常量折叠),然后遍历每个节点,在 Handler 注册表中查找对应的 ONNX 转换函数。如果找到了,就生成对应的 ONNX 算子;如果找不到,tf2onnx 会记录警告,但仍然尝试用通用算子近似或跳过该节点。这一设计保证了转换过程的韧性——即使模型中包含少量不支持的算子,整体转换仍可能成功。
从源码结构来看,tf2onnx/ 目录是整个项目的核心:
convert.py:CLI 入口和 Python API,定义了 tf2onnx.convert() 函数graph.py / graph_builder.py:图结构的定义与构建handler.py:ONNXOpsetsHandler 基类,所有算子转换器的注册与调度rewriter/:预置的重写规则(60+ 个)onnx_opset/:ONNX 各版本(opset 8~18)支持的算子定义optimizer/:ONNX 级别的图优化器tf2onnx 提供了两种使用方式。对于集成到生产流水线中,tf2onnx.convert() 是更推荐的选择:
import tensorflow as tf
import tf2onnx
model = tf.keras.applications.ResNet50(weights='imagenet')
spec = (tf.TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32, name='input'),)
onnx_model, _ = tf2onnx.convert.from_keras(model, input_signature=spec, opset=13)
with open('resnet50.onnx', 'wb') as f:
f.write(onnx_model.SerializeToString())
CLI 方式适合快速验证:
python -m tf2onnx.convert \
--saved-model /path/to/savedmodel \
--output model.onnx \
--opset 13 \
--target luono, caffe2
--target 参数是一个强大的选项,指定转换时需要兼容的运行时。tf2onnx 会根据目标运行时的特性自动调整转换策略。
tf2onnx 并不是万能的。以下几点在实际使用中需要特别注意:
算子覆盖不完整。TensorFlow 的算子远超 ONNX 支持的范围。对于使用 TensorFlow 特有自定义算子的模型,转换过程可能失败或产生精度损失。项目在 README 中明确标注了"Looking for a new maintainer",维护力量不足可能导致对新 TensorFlow 特性的跟进滞后。
动态shape问题。ONNX 在某些版本对动态shape的支持有限,如果模型包含动态尺寸的输入(如 batch size 为 None 或序列长度可变),转换后可能需要额外处理。
TFLite 和 TFJS 实验性支持。README 明确标注这两项为 experimental,生产环境使用前务必做端到端的输出验证。
tf2onnx 在 ONNX 生态中扮演着"上游入口"的角色。根据 GitHub 的数据,该项目有 2532 个 star、463 个 fork,被超过 1000 个其他开源项目依赖。每周 pip 下载量持续增长,反映了模型格式互操作需求的持续旺盛。
对于开发者来说,tf2onnx 的最佳使用场景包括:
上手建议:先从 Keras 预训练模型(如 ResNet50)开始练手,验证转换精度后再处理复杂自定义模型。转换后务必做数值比对测试,确保输出结果与原始模型一致。