TensorFlow.js加载模型时出现TypeError: Cannot read property 'concat' of undefined错误求助
TypeError: Cannot read property 'concat' of undefined when running TensorFlow.js frozen model (Emoji Scavenger Hunt reproduction)
我在复现谷歌的Emoji Scavenger Hunt项目时,运行代码出现了如下错误:TypeError: Cannot read property 'concat' of undefined
当前运行的代码如下:
import * as tf from '@tensorflow/tfjs'; import { loadFrozenModel, FrozenModel } from '@tensorflow/tfjs-converter'; export default class MobileNet { constructor() { } async load() { const MODEL_URL = '/assets/project-gaea/models/web_model.pb'; const WEIGHTS_URL = '/assets/project-gaea/models/weights_manifest.json'; const model = await loadFrozenModel(MODEL_URL, WEIGHTS_URL); const cat = document.getElementById('cat'); model.execute({input: tf.fromPixels(cat)}); } }
问题分析与解决方案
这个错误本质是模型的输入张量不符合预期,导致后续层的计算输出为undefined,触发了concat操作的报错。咱们从几个关键点入手修复:
1. 确认DOM元素存在
首先要确保document.getElementById('cat')能正确获取到图像元素,如果元素不存在或者还没加载完成,tf.fromPixels会生成无效张量,进而导致后续计算出错。
2. 调整输入图像尺寸与模型匹配
Emoji Scavenger Hunt使用的MobileNet变体,训练时的输入尺寸通常是224x224,直接用tf.fromPixels获取的图像尺寸可能和这个不符,导致模型层的形状不匹配,引发计算错误。需要把图像张量调整到正确尺寸。
3. 添加批量维度
几乎所有TensorFlow模型都是为批量数据设计的,模型期望的输入形状是[批量大小, 高度, 宽度, 通道数],而tf.fromPixels返回的是[高度, 宽度, 通道数]的单个样本张量,必须添加一个批量维度。
4. 确认模型的输入节点名称
你的代码里用了input作为输入节点名,但冻结模型的实际输入节点名可能不是这个(比如常见的input_1)。如果名称不匹配,模型无法找到输入,后续层的输出就会是undefined,最终触发concat错误。可以用Netron工具打开你的web_model.pb文件查看准确的输入节点名称。
修改后的代码示例
import * as tf from '@tensorflow/tfjs'; import { loadFrozenModel, FrozenModel } from '@tensorflow/tfjs-converter'; export default class MobileNet { constructor() { } async load() { const MODEL_URL = '/assets/project-gaea/models/web_model.pb'; const WEIGHTS_URL = '/assets/project-gaea/models/weights_manifest.json'; // 先检查图像元素是否存在 const cat = document.getElementById('cat'); if (!cat) { console.error('无法找到id为"cat"的图像元素!'); return; } const model = await loadFrozenModel(MODEL_URL, WEIGHTS_URL); // 使用tf.tidy清理中间张量,避免内存泄漏 tf.tidy(() => { // 将图像转为张量并调整尺寸到模型预期的224x224 let inputTensor = tf.fromPixels(cat); inputTensor = tf.image.resizeBilinear(inputTensor, [224, 224]); // 添加批量维度,符合模型输入要求 inputTensor = inputTensor.expandDims(0); // 替换成你实际模型的输入节点名,这里假设是input_1 const predictions = model.execute({input_1: inputTensor}); // 打印预测结果验证 predictions.print(); }); } }
额外提示
- 如果你不确定模型的输入尺寸和节点名,用Netron可视化模型结构是最直接的方法,能清晰看到模型的输入输出节点信息。
- 运行代码时可以打开浏览器的TensorFlow.js控制台(在开发者工具的Console里输入
tf.ENV.set('DEBUG', true)),查看更详细的模型计算日志,方便定位问题。
内容的提问来源于stack exchange,提问作者oninross
相关产品推荐
相关产品推荐

