Greyfrog
Greyfrog

Reputation: 1016

Vue3 app with tensorflowjs throws TypeError: Cannot read property 'backend' of undefined

I build a simple tensorflowjs app with plain Jquery and it was working fine, although prediction wasn't that great but it worked.

Now, I started building a GUI for the app using Vue3 which I have create using @vue/cli. I have installed couple of other plugin such as tailwindcss, clmtrackr via npm and they are working fine.

Now I have installed the tensorflowjs using npm -

npm install @tensorflow/tfjs 

Everything installed without any error but when I ran the app after setting up code for model creation and training, I started getting error -

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)

First I thought I probably need to install - @tensorflow/tfjs-node which is made for NodeJs but I still went ahead and installed it. Ofcourse it didn't work because I had node v.14 so I started getting node-gyp error. I read that I need to install it with older version of node v12 so I install nvm and installed another version of nodejs and then run @tensorflow/tfjs-node and it worked. After that I started getting bunch of error which I expected already because this package is made for NodeJS.

Next, I deleted my node_modules folder and modified package.json to remove node version of tensorflow and ran

npm install

to install all fresh packages with their latest version. Everything installed without any error but the Cannot read property 'backend' didn't get resolved.

Surprisingly, when I ran the code in firefox I got info of undefined error and in chrome backed of undefined error which I don't understand.

The code which is causing the error was this -

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(.............
}

How do I know that? Well I returned null in tf.tidy() and I did get pass through to next code block. I went through so many github issues and they all had different issues with same error.

  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

So there might be doubt about my process for creating dataset which is described here in my other post.

Please someone help me. It has been almost entire week since I had this problem.

Edit 1 :

So any operation on imageArray causes backend error which might actually b related to how I am creating dataset and passing it to the class method.

How I figured this out? I tried

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}

I am adding my dataset creation method in vue3 app -

        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;
            });
        }

Edit 2 :

So I ran another test on getImage() method and logged the returned value. It return all the values mentioned below correctly but throws same backend of undefined error at the same time

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) 

Upvotes: 2

Views: 3211

Answers (5)

Jorge Guerra Pires
Jorge Guerra Pires

Reputation: 632

I have faced the same issue in Angular. By reading @Csabi, it occurred to me to try to remove the training from tidy. It worked.💕👌 Even though tidy may work well in pure JavaScript, it seems to be problematic in Angular.

Upvotes: 0

JinAquo123
JinAquo123

Reputation: 31

I've been in the same situation when I tried to use my model in Vue3. I managed to run predict on model by doing:

import { toRaw } from 'vue'

...

let raw_model = toRaw(this.model)
let result = raw_model.predict(img)

...

Upvotes: 3

Csabi
Csabi

Reputation: 1

I've hit the same error in CLI without anything to do with Vue.

In my case I've tried to use a tensor outside tf.tidy(() => {}) scope.

Upvotes: 0

Pierre Caillaud
Pierre Caillaud

Reputation: 31

In my case, the error seems to be caused by the fact that Vue3 wrapped my model attribute in a Proxy object. You can use Object.freeze() to prevent vue framework to modify your object.

Before:

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
    }
  }
}

After:

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)
    }
  }
}

Upvotes: 3

tomato
tomato

Reputation: 11

Success:

let model;
 
model = await tf.loadGraphModel(MODEL_URL)

Error:

let model = ref();
 
model.value = await tf.loadGraphModel(MODEL_URL);

Anyway, I solved this problem, and it can run normally now.

Upvotes: -1

Related Questions