调用tf.loadGraphModelSync([ModelJSON, ArrayBuffer])报错求助
问题描述
我想制作一个能运行TensorFlow.js模型的独立HTML文档,操作流程如下:
- 在Python中将模型保存为
.h5文件 - 通过
tensorflowjs_convert --input_format keras ...命令转换模型,得到包含model.json(确认可正常加载)和单权重文件group1-shard1of1.bin的目录 - 将两个文件内容做Base64编码后,以Data URI嵌入HTML,代码如下:
const modelURI = "data:application/json;base64,<Data Here>"; const weightsURI = "data:application/octet-stream;base64,<Data Here>"; Promise.all([fetch(modelURI), fetch(weightsURI)]) .then(function(resp) { return Promise.all([resp[0].json(), resp[1].arrayBuffer()]); }) .then(function(data) { tf.loadGraphModelSync([data[0], data[1]]); });
但loadGraphModelSync持续报错:
Uncaught (in promise) TypeError: n is null value graph_model.js:212 value graph_model.js:180 value graph_model.js:167 loadGraphModelSync graph_model.js:699
我确定问题出在传入的ArrayBuffer,但对TensorFlow.js不熟悉无法定位原因。查阅相关PR得知ArrayBuffer是权重串联列表,但没有具体格式信息。求问权重格式或Base64数据加载的替代方法。
编辑1:使用未压缩TensorFlow.js包得到详细错误:
32091 | if (metadata.structuredOutputKeys != null) { 32092 | this.structuredOutputKeys = metadata.structuredOutputKeys; 32093 | } 32094 | } 32095 | this.signature = signature; 32096 | this.version = "".concat(graph.versions.producer, ".").concat(graph.versions.minConsumer); ^ TypeError: null is not an object (evaluating 'graph.versions') at .../node_modules/@tensorflow/tfjs-converter/dist/tf-converter.node.js:32096:34 at .../node_modules/@tensorflow/tfjs-converter/dist/tf-converter.node.js:32063:16 at .../node_modules/@tensorflow/tfjs-converter/dist/tf-converter.node.js:32053:16 at loadGraphModelSync (.../node_modules/@tensorflow/tfjs-converter/dist/tf-converter.node.js:32577:5) at .../src/index.ts:14:9
解决方法
核心问题解析
- 模型类型不匹配:用
tensorflowjs_convert转换Keras.h5模型得到的是Layers模型,而非Graph模型。loadGraphModelSync是针对TensorFlow GraphDef格式模型的加载方法,强行调用会因为Layers模型结构中没有Graph模型的graph字段,导致graph.versions为空报错。 - 参数格式错误:
loadGraphModelSync不支持直接传入[模型JSON, 权重Buffer]的数组组合,需要符合特定的参数结构。
正确实现代码
const modelBase64 = "<你的model.json的Base64字符串>"; const weightsBase64 = "<你的group1-shard1of1.bin的Base64字符串>"; // 直接解码Base64得到模型JSON const modelJson = JSON.parse(atob(modelBase64)); // 解码Base64得到权重ArrayBuffer const weightsBuffer = Uint8Array.from(atob(weightsBase64), c => c.charCodeAt(0)).buffer; // 构造符合要求的模型工件对象 const artifacts = { modelTopology: modelJson.modelTopology, weightsManifest: modelJson.weightsManifest, weightData: weightsBuffer }; // 用Layers模型的同步加载方法加载模型 const model = tf.loadLayersModelSync({ load: () => Promise.resolve(artifacts) }); // 验证模型加载成功 console.log("模型加载完成"); console.log(model.summary());
关键说明
- 无需通过
fetch处理Data URI,直接用atob解码Base64字符串更高效,避免异步请求的额外开销。 tensorflowjs_convert生成的权重文件是按照weightsManifest中的描述顺序拼接的,直接传入解码后的Buffer即可匹配加载要求。- 如果需要异步加载,可将
loadLayersModelSync替换为loadLayersModel,并调整相关同步逻辑。
内容的提问来源于stack exchange,提问作者Generic
相关产品推荐
相关产品推荐

