Tensorflow.js predictClass 未返回 classIndex (NaN)
Tensorflow.js predictClass not returning classIndex (NaN)
我正在尝试将 "Teachable machine" 用于自己的目的。我想将它用作训练模型的样板,该模型对来自两个 类 的图像进行分类。开始使用 github 中的示例 - https://github.com/googlecreativelab/teachable-machine-boilerplate
更改了一些内容以在 nodeJS 上使用本地图像。解决了随之而来的一些问题和错误。现在它似乎没有错误地工作,但它没有预测任何东西。
来自 git 的示例非常容易理解,我几乎按原样使用它(除了加载图像不是来自网络摄像头,而是来自文件)。
部分在训练每张图像后立即输出:
Processed image cat.10.jpg
{ classIndex: -1, confidences: { '1': NaN } }
来到另一个目录后:
Processed image dog.1.jpg
{ classIndex: -1, confidences: { '1': 0, '2': NaN } }
当涉及到预测时,它输出这个:
EXAMPLES:
{ '1': 14, '2': 14 }
PREDICTING
{ classIndex: -1, confidences: { '1': 0, '2': NaN } }
{ classIndex: -1, confidences: { '1': 0, '2': NaN } }
图像大小调整为 227x227
玩过更大的火车数据集(最多 50 张照片),但这没有任何意义,示例甚至从 1 张照片开始工作。
尝试更改 TOPK 值 - 没有成功。
getOffsets - 这只是一个函数,如果图像有其他尺寸,则仅使用图像的中心 227x227 部分。也不是问题。
setTimeout - 只是一个蹩脚的解决方案,它帮助我在训练后进行 运行 预测。不知道为什么它不等待它,但它有帮助。至于它说的例子数是正确的 - 我假设训练是完整的。
你们知道我做错了什么吗?
const tf = require("@tensorflow/tfjs");
require("@tensorflow/tfjs-node");
const mobilenetModule = require("@tensorflow-models/mobilenet");
const knnClassifier = require("@tensorflow-models/knn-classifier");
const fs = require("fs");
const { createCanvas, Image } = require("canvas");
global.fetch = require("node-fetch");
class NN {
constructor() {
this.IMAGE_SIZE = 227;
this.TOPK = 10;
this.loadModel();
}
async loadModel() {
this.knn = await knnClassifier.create();
this.mobilenet = await mobilenetModule.load();
await this.trainData();
await this.predictData();
}
async predictData() {
setTimeout(() => {
const exampleCount = this.knn.getClassExampleCount();
console.log(`EXAMPLES:`);
console.log(exampleCount);
console.log("PREDICTING");
this.predictPath("./dataset/test/a");
}, 0);
}
async trainData() {
await this.trainPath("./dataset/train/a", 1);
console.log("TRAINED A");
await this.trainPath("./dataset/train/b", 2);
console.log("TRAINED B");
}
async trainPath(path, idx) {
await fs.readdir(path, async (err, imageNames) => {
for (let i = 0; i < imageNames.length; i++) {
const img = await this.processImage(`${path}/${imageNames[i]}`);
const imgTf = tf.fromPixels(img);
const inferLocal = img => this.mobilenet.infer(img, "conv_preds");
const logits = inferLocal(imgTf);
this.knn.addExample(logits, idx);
imgTf.dispose();
if (logits != null) {
logits.dispose();
}
console.log(`Processed image ${imageNames[i]}`);
// Try to predict after adding
const numClasses = this.knn.getNumClasses();
if (numClasses > 0) {
const prediction = await this.predictImage(
`${path}/${imageNames[i]}`
);
console.log(prediction);
}
}
});
}
async predictPath(path) {
fs.readdir(path, async (err, imageNames) => {
for (let i = 0; i < imageNames.length; i++) {
const prediction = await this.predictImage(`${path}/${imageNames[i]}`);
console.log(prediction);
}
});
}
async predictImage(imagePath) {
const img = await this.processImage(imagePath);
const imgTf = tf.fromPixels(img);
const inferLocal = () => this.mobilenet.infer(imgTf, "conv_preds");
const logits = inferLocal();
const prediction = await this.knn.predictClass(logits, this.TOPK);
imgTf.dispose();
if (logits != null) {
logits.dispose();
}
return prediction;
}
async processImage(imagePath) {
const canvas = createCanvas(this.IMAGE_SIZE, this.IMAGE_SIZE);
const ctx = canvas.getContext("2d");
const img = new Image();
const promise = new Promise((resolve, reject) => {
img.crossOrigin = "";
img.onload = () => {
const { x, y } = this.getOffsets(img);
ctx.drawImage(img, x, y);
resolve(canvas);
};
});
img.src = `${imagePath}`;
return promise;
}
getOffsets(img) {
let x, y;
if (Number(img.width) > this.IMAGE_SIZE) {
x = -(img.width - this.IMAGE_SIZE) / 2;
} else {
x = (this.IMAGE_SIZE - img.width) / 2;
}
if (Number(img.height) > this.IMAGE_SIZE) {
y = -(img.height - this.IMAGE_SIZE) / 2;
} else {
y = (this.IMAGE_SIZE - img.height) / 2;
}
return { x, y };
}
}
new NN();
啊啊啊啊。看起来我解决了它。我们不能使用 1 中的 class 索引(我使用了 1 和 2)
他们需要从0开始。
await this.trainPath("./dataset/train/a", 0);
await this.trainPath("./dataset/train/b", 1);
我正在尝试将 "Teachable machine" 用于自己的目的。我想将它用作训练模型的样板,该模型对来自两个 类 的图像进行分类。开始使用 github 中的示例 - https://github.com/googlecreativelab/teachable-machine-boilerplate
更改了一些内容以在 nodeJS 上使用本地图像。解决了随之而来的一些问题和错误。现在它似乎没有错误地工作,但它没有预测任何东西。
来自 git 的示例非常容易理解,我几乎按原样使用它(除了加载图像不是来自网络摄像头,而是来自文件)。
部分在训练每张图像后立即输出:
Processed image cat.10.jpg
{ classIndex: -1, confidences: { '1': NaN } }
来到另一个目录后:
Processed image dog.1.jpg
{ classIndex: -1, confidences: { '1': 0, '2': NaN } }
当涉及到预测时,它输出这个:
EXAMPLES:
{ '1': 14, '2': 14 }
PREDICTING
{ classIndex: -1, confidences: { '1': 0, '2': NaN } }
{ classIndex: -1, confidences: { '1': 0, '2': NaN } }
图像大小调整为 227x227 玩过更大的火车数据集(最多 50 张照片),但这没有任何意义,示例甚至从 1 张照片开始工作。 尝试更改 TOPK 值 - 没有成功。
getOffsets - 这只是一个函数,如果图像有其他尺寸,则仅使用图像的中心 227x227 部分。也不是问题。
setTimeout - 只是一个蹩脚的解决方案,它帮助我在训练后进行 运行 预测。不知道为什么它不等待它,但它有帮助。至于它说的例子数是正确的 - 我假设训练是完整的。
你们知道我做错了什么吗?
const tf = require("@tensorflow/tfjs");
require("@tensorflow/tfjs-node");
const mobilenetModule = require("@tensorflow-models/mobilenet");
const knnClassifier = require("@tensorflow-models/knn-classifier");
const fs = require("fs");
const { createCanvas, Image } = require("canvas");
global.fetch = require("node-fetch");
class NN {
constructor() {
this.IMAGE_SIZE = 227;
this.TOPK = 10;
this.loadModel();
}
async loadModel() {
this.knn = await knnClassifier.create();
this.mobilenet = await mobilenetModule.load();
await this.trainData();
await this.predictData();
}
async predictData() {
setTimeout(() => {
const exampleCount = this.knn.getClassExampleCount();
console.log(`EXAMPLES:`);
console.log(exampleCount);
console.log("PREDICTING");
this.predictPath("./dataset/test/a");
}, 0);
}
async trainData() {
await this.trainPath("./dataset/train/a", 1);
console.log("TRAINED A");
await this.trainPath("./dataset/train/b", 2);
console.log("TRAINED B");
}
async trainPath(path, idx) {
await fs.readdir(path, async (err, imageNames) => {
for (let i = 0; i < imageNames.length; i++) {
const img = await this.processImage(`${path}/${imageNames[i]}`);
const imgTf = tf.fromPixels(img);
const inferLocal = img => this.mobilenet.infer(img, "conv_preds");
const logits = inferLocal(imgTf);
this.knn.addExample(logits, idx);
imgTf.dispose();
if (logits != null) {
logits.dispose();
}
console.log(`Processed image ${imageNames[i]}`);
// Try to predict after adding
const numClasses = this.knn.getNumClasses();
if (numClasses > 0) {
const prediction = await this.predictImage(
`${path}/${imageNames[i]}`
);
console.log(prediction);
}
}
});
}
async predictPath(path) {
fs.readdir(path, async (err, imageNames) => {
for (let i = 0; i < imageNames.length; i++) {
const prediction = await this.predictImage(`${path}/${imageNames[i]}`);
console.log(prediction);
}
});
}
async predictImage(imagePath) {
const img = await this.processImage(imagePath);
const imgTf = tf.fromPixels(img);
const inferLocal = () => this.mobilenet.infer(imgTf, "conv_preds");
const logits = inferLocal();
const prediction = await this.knn.predictClass(logits, this.TOPK);
imgTf.dispose();
if (logits != null) {
logits.dispose();
}
return prediction;
}
async processImage(imagePath) {
const canvas = createCanvas(this.IMAGE_SIZE, this.IMAGE_SIZE);
const ctx = canvas.getContext("2d");
const img = new Image();
const promise = new Promise((resolve, reject) => {
img.crossOrigin = "";
img.onload = () => {
const { x, y } = this.getOffsets(img);
ctx.drawImage(img, x, y);
resolve(canvas);
};
});
img.src = `${imagePath}`;
return promise;
}
getOffsets(img) {
let x, y;
if (Number(img.width) > this.IMAGE_SIZE) {
x = -(img.width - this.IMAGE_SIZE) / 2;
} else {
x = (this.IMAGE_SIZE - img.width) / 2;
}
if (Number(img.height) > this.IMAGE_SIZE) {
y = -(img.height - this.IMAGE_SIZE) / 2;
} else {
y = (this.IMAGE_SIZE - img.height) / 2;
}
return { x, y };
}
}
new NN();
啊啊啊啊。看起来我解决了它。我们不能使用 1 中的 class 索引(我使用了 1 和 2) 他们需要从0开始。
await this.trainPath("./dataset/train/a", 0);
await this.trainPath("./dataset/train/b", 1);