You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Bootstrap Webpack示例加载Tensorflow.js模型遇变量重复注册错误

问题描述

我基于Bootstrap Webpack示例搭建项目,使用Tensorflow.js加载JSON格式的训练模型。此前在无Bootstrap的Webpack环境,或是直接通过script标签引入tfjs的非Node.js环境中,代码均能正常运行,但迁移到该Bootstrap Webpack示例的Node环境后,出现如下错误:

Uncaught (in promise) Error: Variable with name conv2d/kernel was already registered
at Engine.makeVariable (engine.ts:886:12)
at Module.variable (variable.ts:43:2)
at new LayerVariable (variables.ts:98:40)
at Conv2D.addWeight (topology.ts:1315:3)
at Conv2D.build (convolutional.ts:599:8)
at eval (topology.ts:1013:12)
at nameScope (common.ts:61:7)
at Conv2D.apply (topology.ts:998:48)
at Sequential.add (models.ts:557:3)
at fromConfig (models.ts:1048:3)

相关代码细节如下:

main.js

import { prepare } from "./prediction.js";
document.addEventListener("DOMContentLoaded", prepare);
...

prediction.js

import * as tf from "@tensorflow/tfjs";
import Plotly from "plotly.js-dist-min";

var TensorflowModels;
var predictConfigs;

export function prepare(){
  setTensorflowModels(pathOfRootFolder);
  ...
}

async function setTensorflowModels(pathOfRootFolder) {

  let Models = { p: 0 , wake: 0 , ct: 0 };
  let configs = { p: 0 , wake: 0 , ct: 0 };
  let path;
  // 加载Python Keras导出的Tensorflow.js训练模型
  for (let key in Models) {
    path = [pathOfRootFolder, key, "model.json"].join("/");
    Models[key] = await tf.loadLayersModel(path);

    path = [pathOfRootFolder, key, "config.json"].join("/");
    configs[key] = await getConfig(path);
  }
  TensorflowModels = Models;
  predictConfigs = configs;

}
...

webpack.config.js

'use strict'

const path = require('path')
const autoprefixer = require('autoprefixer')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: './src/js/main.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer:{
    static: path.resolve(__dirname, 'dist'),
    port: 8080,
    hot: true
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' })
  ],
  module: {
    rules: [
      {
        test: /\.(scss)$/,
        use: [
          {
            // 注入<style>标签到DOM中添加CSS
            loader: 'style-loader'
          },
          {
            // 将@import和url()解析为import/require()
            loader: 'css-loader'
          },
          {
            // 用PostCSS处理CSS的Webpack loader
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: () => [
                  autoprefixer
                ]
              }
            }
          },
          {
            // 加载并编译SASS/SCSS文件为CSS
            loader: 'sass-loader'
          }
        ]
      }
    ]
  }
}

错误原因及解决方案

错误原因

这个报错是TensorFlow.js变量命名空间冲突导致的。你的Webpack配置中开启了hot: true(热模块替换,HMR),在开发模式下,当文件修改后Webpack会重新加载模块,但TensorFlow.js的引擎实例不会自动重置;同时prepare函数可能在HMR更新时被多次触发,导致setTensorflowModels重复执行,多次加载相同结构的模型,相同名称的变量(比如conv2d/kernel)被多次注册,最终抛出错误。

解决方案

1. 临时关闭热模块替换(快速验证)

在webpack.config.js的devServer配置中,把hot: true改为hot: false,重启开发服务器后测试是否恢复正常。这种方式适合快速确认问题根源,但会失去HMR的开发便利。

2. 适配HMR,避免重复加载模型

修改代码逻辑,确保模块更新时先清理已加载的模型实例,再重新加载:

  • 修改main.js:
import { prepare } from "./prediction.js";

function initApp() {
  // 清理已存在的模型实例
  if (window.TensorflowModels) {
    for (const key in window.TensorflowModels) {
      window.TensorflowModels[key].dispose();
    }
  }
  prepare();
}

document.addEventListener("DOMContentLoaded", initApp);

// 处理HMR模块更新
if (module.hot) {
  module.hot.accept('./prediction.js', () => {
    initApp();
  });
}
  • 修改prediction.js:
import * as tf from "@tensorflow/tfjs";
import Plotly from "plotly.js-dist-min";

// 将模型挂载到window,方便跨模块清理
window.TensorflowModels = window.TensorflowModels || {};
window.predictConfigs = window.predictConfigs || {};

export function prepare(){
  setTensorflowModels(pathOfRootFolder);
  ...
}

async function setTensorflowModels(pathOfRootFolder) {
  // 先清理当前模型
  for (const key in window.TensorflowModels) {
    window.TensorflowModels[key].dispose();
  }

  let Models = { p: 0 , wake: 0 , ct: 0 };
  let configs = { p: 0 , wake: 0 , ct: 0 };
  let path;
  for (let key in Models) {
    path = [pathOfRootFolder, key, "model.json"].join("/");
    Models[key] = await tf.loadLayersModel(path);

    path = [pathOfRootFolder, key, "config.json"].join("/");
    configs[key] = await getConfig(path);
  }
  window.TensorflowModels = Models;
  window.predictConfigs = configs;
}
...

3. 用命名空间隔离模型变量

在加载每个模型时,使用tf.nameScope为模型创建独立的命名空间,避免变量名冲突:

async function setTensorflowModels(pathOfRootFolder) {
  let Models = { p: 0 , wake: 0 , ct: 0 };
  let configs = { p: 0 , wake: 0 , ct: 0 };
  let path;
  for (let key in Models) {
    // 为每个模型创建独立命名空间
    await tf.nameScope(`model-${key}`, async () => {
      path = [pathOfRootFolder, key, "model.json"].join("/");
      Models[key] = await tf.loadLayersModel(path);
    });

    path = [pathOfRootFolder, key, "config.json"].join("/");
    configs[key] = await getConfig(path);
  }
  window.TensorflowModels = Models;
  window.predictConfigs = configs;
}

内容的提问来源于stack exchange,提问作者y0o0ic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:37:26