为了继续使用 Tensorflow.js 进行预测,在 Vue.js 实例中有一个无限循环是错误的吗?

Is it wrong to have an infinite loop inside Vue.js instance in order to keep making predictions using Tensorflow.js?

我正在使用 Tensorflow.js 训练和预测食物,网络 API 访问我的笔记本网络摄像头,Vue.js 创建一个简单的页面。

我在 addExample() 方法中有一个无限循环,即 while(true),它负责要求模型预测每一帧我的网络摄像头前面的内容并重新渲染结果.

我想知道在我的 Vue 实例中的方法中是否存在无限循环问题。

async addExample() {
  const selector = document.getElementById('classSelector');
  const player = document.getElementById('player');

  // Get the intermediate activation of MobileNet 'conv_preds' and pass that
  // to the KNN classifier.
  const activation = this.net.infer(player, 'conv_preds');

  // Pass the intermediate activation to the classifier
  this.classifier.addExample(activation, selector.selectedIndex);

  console.log("Class '" + selector.value + "' added to the model");

  while (true) {
    if (this.classifier.getNumClasses() > 0) {
      const activation = this.net.infer(player, 'conv_preds');

      const result = await this.classifier.predictClass(activation);
      this.confidence = result.confidences[result.classIndex];
      this.label = this.foodClasses[result.classIndex].name;
    }
    await tf.nextFrame();
  }
}

这个方法是在我点击训练按钮的时候触发的,但是在方法内部一直是死循环。但是每次我需要训练同一个对象或一个新对象时,我都必须再次触发该方法,这导致再次进入同一个循环 - 但我认为旧的保持 运行.

<button type="button" @click="addExample()">Train class</button>

如果您想查看运行中的代码,这里是 fiddle

已编辑:谢谢您的回答。我能够以我期望的方式解决我的问题。现在,当我触发 addExample() 函数时,我只有一个循环 运行,而不是旧循环。我这么说是基于对任务管理器中我的 GPU 利用率百分比的非常浅薄的分析。

以旧方式,当我多次触发 addExample() 时,我可以看到 GPU 百分比利用率越来越高。

现在,利用率只增加了一倍。

这是最终代码:

async addExample() {
  const selector = document.getElementById('classSelector');
  const player = document.getElementById('player');
  this.infiniteLoopControler += 1;
  const internalLoopControler = this.infiniteLoopControler;

  // Get the intermediate activation of MobileNet 'conv_preds' and pass that
  // to the KNN classifier.
  const activation = this.net.infer(player, 'conv_preds');

  // Pass the intermediate activation to the classifier
  this.classifier.addExample(activation, selector.selectedIndex);

  console.log("Class '" + selector.value + "' added to the model");

  while (internalLoopControler === this.infiniteLoopControler) {
    if (this.classifier.getNumClasses() > 0) {
      const activation = this.net.infer(player, 'conv_preds');

      const result = await this.classifier.predictClass(activation);
      this.confidence = result.confidences[result.classIndex];
      this.label = this.foodClasses[result.classIndex].name;
    }
    await tf.nextFrame();
  }
}

再次感谢您对我的帮助!

删除 while(true) 的一种简单方法是改用递归。

async addExample() {
  const selector = document.getElementById('classSelector');
  const player = document.getElementById('player');

  // Get the intermediate activation of MobileNet 'conv_preds' and pass that
  // to the KNN classifier.
  const activation = this.net.infer(player, 'conv_preds');

  // Pass the intermediate activation to the classifier
  this.classifier.addExample(activation, selector.selectedIndex);

  console.log("Class '" + selector.value + "' added to the model");


  const cb = () => {
    if (this.classifier.getNumClasses() > 0) {
      const activation = this.net.infer(player, 'conv_preds');

      const result = await this.classifier.predictClass(activation);
      this.confidence = result.confidences[result.classIndex];
      this.label = this.foodClasses[result.classIndex].name;
    }
    tf.nextFrame().then(cb);
  }

  cb();
}

在(无限)循环中使用 await 没有错。使用 await 比使用 .then 更好,因为引擎不需要收集堆栈跟踪。有关更多信息,请查看这些主题:


如果您需要一种在循环开始后停止循环的方法(再次单击按钮时),您可以简单地更改循环以检查当前处于活动状态的迭代。

代码示例

let iteration = 0;

async function addExample() {
  iteration += 1;
  const myIteration = iteration;
  while (myIteration === iteration) {
    // ...
  }
}

这是一个(非常)简化的示例。每次调用 addExample 时,iteration 变量都会增加并存储当前迭代 运行。第二次点击该按钮时,将不再满足第一次迭代的条件,(第一次)循环将停止。