javascript - 带有tensorflowjs的Vue3应用程序抛出TypeError : Cannot read property 'backend' of undefined

标签 javascript node.js vue.js tensorflow tensorflow.js

我用普通的 Jquery 构建了一个简单的 tensorflowjs 应用程序,它运行良好,尽管预测不是那么好,但它有效。

现在,我开始使用 Vue3 为应用程序构建一个 GUI,这是我使用 @vue/cli 创建的。我已经通过 npm 安装了几个其他插件,例如 tailwindcss、clmtrackr,它们工作正常。

现在我已经使用 npm 安装了 tensorflowjs -

npm install @tensorflow/tfjs 

一切安装都没有任何错误,但是当我在设置模型创建和训练代码后运行应用程序时,我开始出现错误 -

Uncaught (in promise) TypeError: Cannot read property 'backend' of undefined
    at Engine.moveData (engine.js?6ae2:288)
    at DataStorage.get (backend.js?8b87:29)
    at eval (backend_webgl.js?5edb:497)
    at Array.every (<anonymous>)
    at MathBackendWebGL.shouldExecuteOnCPU (backend_webgl.js?5edb:497)
    at concatImpl (Concat_impl.js?2cbf:39)
    at Object.concat [as kernelFunc] (Concat.js?b4c2:35)
    at kernelFunc (engine.js?6ae2:463)
    at eval (engine.js?6ae2:524)
    at Engine.scopedRun (engine.js?6ae2:337)

首先,我想我可能需要安装 - @tensorflow/tfjs-node,它是为 NodeJs 制作的,但我仍然继续安装它。当然它不起作用,因为我有 Node v.14,所以我开始收到 Node gyp 错误。我读到我需要使用旧版本的 Node v12 安装它,所以我安装了 nvm 并安装了另一个版本的 Nodejs,然后运行 ​​@tensorflow/tfjs-node 并且它起作用了。之后我开始收到一堆我预料到的错误,因为这个包是为 NodeJS 制作的。

接下来,我删除了我的node_modules文件夹并修改了package.json以删除tensorflow的 Node 版本并运行

npm install

安装所有最新版本的软件包。一切安装都没有任何错误,但无法读取属性“后端”没有得到解决。

令人惊讶的是,当我在 Firefox 中运行代码时,我得到了未定义错误的信息,而在 chrome 中则得到了我不明白的未定义错误的信息。

导致错误的代码是这样的 -

async trainModel(imageArray, labelArray) {
        // tf.getBackend()

        let imageSet = tf.tidy(() => {
            return tf.concat(imageArray); <--------------- Error 
        });

        let labelSet = tf.tidy(() => {
            return tf.oneHot(tf.tensor1d(labelArray, 'int32'), 3); 
        })

        this.model.fit(.............
}

我怎么知道呢?好吧,我在 tf.tidy() 中返回了 null,并且确实传递到了下一个代码块。我经历了很多 github 问题,它们都有不同的问题和相同的错误。

  1. Github: TypeError: Cannot read property 'backend' of undefined

  2. TypeError: Cannot read property 'backend' of undefined - tensor is already disposed when moveData is called

因此,我创建数据集的过程可能会产生疑问,即 described here在我的另一篇文章中。

请有人帮助我。自从我遇到这个问题以来已经几乎整整一周了。

编辑1:

因此,对 imageArray 的任何操作都会导致后端错误,这实际上可能与我创建数据集并将其传递给类方法的方式有关。

我是怎么想到这一点的?我试过了

console.log(imageArray.toString()) <--- this causes backend error  

console.log(imageArray) < -- this doesn't
|
---> console output <--------------------------------
Tensor {kept: false, isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 135000, …} (4) [1, 150, 300, 3]
Models.vue?2820:139 Tensor {kept: false, isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 135000, …} (4) [1, 150, 300, 3]
Models.vue?2820:139 Tensor {kept: false, isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 135000, …} (4) [1, 150, 300, 3]
Models.vue?2820:139 Tensor {kept: false, isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 135000, …} (4) [1, 150, 300, 3]
Models.vue?2820:139 Tensor {kept: false, isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 135000, …} (4) [1, 150, 300, 3]
TFModel.js?4fc1:71 Proxy {0: Tensor, 1: Tensor, 2: Tensor, 3: Tensor, 4: Tensor}

我正在 vue3 应用程序中添加数据集创建方法 -

        initCanvas() {
            this.mycan.canvas = this.$refs.mycan;
            this.mycan.context = this.mycan.canvas.getContext('2d')
            this.mycan.w = this.mycan.canvas.width
            this.mycan.h = this.mycan.canvas.height  
        },
        collectData() {
            const img = tf.tidy(() => {
                const captureImg = this.getImage();
                console.log(captureImg, captureImg.shape)
                return captureImg;
            })
            this.imageArray.push(img)
            this.label = parseInt(Math.random() * 3)
            this.labelArray.push(this.label) //--- labels are 0,1,2
        },
        getImage() {
            return tf.tidy(() => {
                const image = tf.browser.fromPixels(this.mycan.canvas);
                const batchedImage = image.expandDims(0);
                const norm = batchedImage.toFloat().div(tf.scalar(255)).sub(tf.scalar(1));
                return norm;
            });
        }

编辑2:

所以我对 getImage() 方法运行了另一个测试并记录了返回的值。它正确返回下面提到的所有值,但同时抛出相同的后端未定义错误

let imgData = this.getImage()
console.log(imgData)
console.log(imgData.shape)
console.log(imgData.toString())

<--- console output-->

Tensor {kept: false, isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 135000, …}
Models.vue?2820:119 (4) [1, 150, 300, 3]
Models.vue?2820:120 Tensor
    [[[[-0.6117647, -0.5411765, -0.3450981],
       [-0.6117647, -0.5411765, -0.3450981],
       [-0.6117647, -0.5411765, -0.3450981],
       ...,
       [-0.5333334, -0.5019608, -0.3176471],
       [-0.5333334, -0.5019608, -0.3176471],
       [-0.5333334, -0.5019608, -0.3176471]],

      [[-0.6039216, -0.5333334, -0.3372549],
       [-0.6078432, -0.5372549, -0.3411765],
       [-0.6078432, -0.5372549, -0.3411765],
       ...,
       [-0.5372549, -0.5019608, -0.3176471],
       [-0.5372549, -0.5019608, -0.3176471],
       [-0.5372549, -0.5019608, -0.3176471]],

      [[-0.6      , -0.5294118, -0.3333334],
       [-0.6      , -0.5294118, -0.3333334],
       [-0.6      , -0.5294118, -0.3333334],
       ...,
       [-0.5372549, -0.4980392, -0.3176471],
       [-0.5372549, -0.4980392, -0.3176471],
       [-0.5333334, -0.4941177, -0.3137255]],

      ...
      [[-0.4039216, -0.454902 , -0.3529412],
       [-0.4078432, -0.4588236, -0.3568628],
       [-0.4078432, -0.4588236, -0.3568628],
       ...,
       [-0.309804 , -0.3254902, -0.2352942],
       [-0.309804 , -0.3254902, -0.2352942],
       [-0.309804 , -0.3254902, -0.2352942]],

      [[-0.4039216, -0.454902 , -0.3529412],
       [-0.4039216, -0.454902 , -0.3529412],
       [-0.4039216, -0.454902 , -0.3529412],
       ...,
       [-0.3058824, -0.3215687, -0.2313726],
       [-0.309804 , -0.3254902, -0.2352942],
       [-0.309804 , -0.3254902, -0.2352942]],

      [[-0.4039216, -0.454902 , -0.3529412],
       [-0.4039216, -0.454902 , -0.3529412],
       [-0.4039216, -0.454902 , -0.3529412],
       ...,
       [-0.3058824, -0.3215687, -0.2313726],
       [-0.309804 , -0.3254902, -0.2352942],
       [-0.309804 , -0.3254902, -0.2352942]]]]

Uncaught TypeError: Cannot read property 'backend' of undefined
    at Engine.moveData (engine.js?6ae2:288)
    at DataStorage.get (backend.js?8b87:29)
    at reshape (Reshape.js?ad24:31)
    at conv2dWithIm2Row (Conv2D_impl.js?7600:157)
    at Object.fusedConv2d [as kernelFunc] (FusedConv2D.js?2d19:46)
    at kernelFunc (engine.js?6ae2:463)
    at eval (engine.js?6ae2:524)
    at Engine.scopedRun (engine.js?6ae2:337)
    at Engine.runKernelFunc (engine.js?6ae2:520)
    at Engine.runKernel (engine.js?6ae2:393) 

最佳答案

就我而言,该错误似乎是由于 Vue3 将我的模型属性包装在 Proxy object 中而引起的。 。您可以使用Object.freeze()防止 vue 框架修改你的对象。

之前:

export default {
  data: ()=>({
    prediction: null,
    model: null
  }),
  methods:{
    async initModel(){
      this.model = await tmImage.load(modelURL, metadataURL)
      // model is wrapped in a Proxy object
    },
    async predict(){
      this.prediction = await this.model.predict(canvas) // this line throwed error
    }
  }
}

之后:

export default {
  data: ()=>({
    prediction: null,
    model: null
  }),
  methods:{
    async initModel(){
      this.model = Object.freeze(await tmImage.load(modelURL, metadataURL))
    },
    async predict(){
      this.prediction = await this.model.predict(canvas)
    }
  }
}

关于javascript - 带有tensorflowjs的Vue3应用程序抛出TypeError : Cannot read property 'backend' of undefined,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67815952/

相关文章:

javascript - 在 JavaScript/ES6 中实现接口(interface)/插件方法

Javascript 和 JQuery - 将 DOM 插入 JQuery

javascript - 如何在 Node JS 应用程序中实现 cron 作业(使用 node-schedule)

node.js - 如何使用 mongoose 从数组字段中获取特定对象

javascript - 无法在node.js获取angularjs http请求消息数据

javascript - 希望计时器在页面加载时开始计时

javascript - 连接 MongoDB Native Driver Node JS 的正确方法

javascript - 如何将 Vue.js 与来自 CMS 的服务器端渲染内容结合起来?

javascript - 如果使用Vue.js显示="none",如何从数组中删除图像?

javascript - Vuejs : Vue. 组件似乎不起作用