DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

超过 2GB 的 ONNX 模型能读入,为什么 check_model 仍然失败?

超过 2GB 的 ONNX external data 模型应按文件路径调用 check_model,避免把完整权重序列化成单个 ModelProto。保持外部数据文件布局,并用目标运行时做推理验收。

超过 2GB 的 ONNX 模型能读入,为什么 check_model 仍然失败?

对于已经使用 external data 保存的大模型,校验时优先传模型路径:

import onnx

onnx.checker.check_model("model.onnx")

如果先用 onnx.load() 读入全部外部权重,再把得到的对象传给 checker,可能遇到:

ModelProto exceeds maximum protobuf size of 2GB

原因在于对象形式的校验路径会序列化 ModelProto。外部权重被装回对象后,单个 protobuf 消息可能超过大小限制。ONNX 官方 issue #3273 在 ONNX 1.8.0 中给出了这一复现;当前文档仍要求超过 2GB 的模型使用路径校验。问题记录、大模型 external data 文档

两种调用看似相近,经过的路径不同

下面的代码在小模型中很常见,但大模型会在对象序列化时出问题:

import onnx

model = onnx.load("model.onnx")
onnx.checker.check_model(model)

将最后两行换成直接传路径的调用。ONNX checker 源码对文件路径使用独立入口,对模型对象则调用 SerializeToString()。checker 源码

如果只是查看图结构或 external data 引用,可以不加载权重:

import onnx

model = onnx.load("model.onnx", load_external_data=False)
for tensor in model.graph.initializer:
    if tensor.data_location == onnx.TensorProto.EXTERNAL:
        details = {entry.key: entry.value for entry in tensor.external_data}
        print(tensor.name, details.get("location"))

这段代码只列出顶层 initializer 的引用,不负责复制权重,也不构成完整校验。

部署目录必须带上外部数据

external data 模型的 .onnx 文件可能很小,大量权重保存在其他文件中。迁移时应保持文件与其引用路径对应,不能只复制 .onnx。校验路径按官方文档布局组织模型及外部数据,先确认没有缺文件或权限问题,再调用 checker。

如果当前模型把所有权重都嵌入了一个超大 protobuf,需要回到保存或导出步骤,使用工具支持的 external data 方式重新输出。仅把文件切成几块,无法替代模型内的张量引用信息。

校验通过后仍需运行验收

从同一部署目录用目标推理运行时加载模型,固定输入检查输出形状和数值误差。这样才能同时覆盖文件布局和实际执行。

这里处理的是 check_model 的大对象序列化问题。某个 optimizer、转换器或模型抽取工具如果内部仍然把完整模型序列化,改外层 checker 调用未必能修好它,应继续查看对应堆栈与工具支持范围。不要通过关闭校验或截断权重来消除错误。