为什么来自 tensorflowjs 的 model.predict() 总是 return 相同的预测?
Why model.predict() from tensorflowjs always return same prediction?
我正在 ionic 3 框架中制作一个用于识别手写字符的应用程序,为此,我正在使用 tensorflowjs。问题是,当一切都解决后,预测总是 return 相同的值。
模型(使用 tensorflowjs-converter 从 keras 转换而来)本地存储在 assets/models/model.json
。
我试图预测的图像是从 HTMLCanvasElement 中提取的,您可以在其中绘制角色,然后函数 getCanvas()
从中检索 ImageData:
getCanvas() {
let photo = document.getElementById('MyCanvas') as HTMLCanvasElement;
let ctx = photo.getContext('2d');
const data: ImageData = ctx.createImageData(300,300);
return data;
}
然后,模型的输入张量 [1, 32, 32, 3]
是从 data
计算出来的,然后,我用 evaluateModel()
将它提供给模型。在该函数中,我用 tf.loadModel()
加载 model.json
并尝试预测图像的 class:
import * as tf from '@tensorflow/tfjs';
async evaluateModel() {
imageData: ImageData = this.getCanvas();
const modelURL: string = './../../assets/models/model.json';
let img: tf.Tensor<tf.Rank.R3> = tf.fromPixels(imageData);
img = tf.image.resizeBilinear(img, [32, 32]);
img = img.expandDims(0);
await tf.loadModel(modelURL).then(model => {
const output: any = model.predict(img);
const results: number = output.argMax(1).dataSync()[0];
console.log(results);
}
一切正常,没有任何错误,但是当将输出预测记录到控制台时,它总是 return 相同的值。此外,预测数组非常平坦,指出 python 中的模型在测试 :
中达到 99,01% 的准确度
console.log(Array.from(output.dataSync()));
17 /* Result of the argMax function on output */
[0.011652837507426739, 0.03457817807793617, 0.029257778078317642, 0.008851004764437675, 0.01691449247300625, 0.026485547423362732, 0.04974032938480377, 0.016473202034831047, 0.021701140329241753, 0.020724112167954445, 0.03173287212848663, 0.024661116302013397, 0.007072054781019688, 0.022814681753516197, 0.011404283344745636, 0.015105938538908958, 0.024694452062249184, 0.07453715801239014, 0.011547397822141647, 0.03946337103843689, 0.018134022131562233, 0.027423541992902756, 0.014102200977504253, 0.016702469438314438, 0.05513478443026543, 0.030478181317448616, 0.012863627634942532, 0.011269242502748966, 0.022525735199451447, 0.022545555606484413, 0.02840271405875683, 0.011758353561162949, 0.006561313755810261, 0.020660076290369034, 0.009705542586743832, 0.024312887340784073, 0.011940978467464447, 0.020643217489123344, 0.009319263510406017, 0.00957920216023922, 0.01844164915382862, 0.015434195287525654, 0.02170679345726967, 0.017867043614387512, 0.013763428665697575, 0.029312126338481903]
在尝试解决这个问题时,我想到的只有两件事:
- ImageData 未正确提取 canvas 绘图,因此预测总是 return 相同的值。
model.json
上的权重未被访问或加载,因此模型 return 具有相同的值。
有什么想法吗?
感谢任何帮助。
createImageData
创建一个带有透明黑色像素的新 ImageDate。因此,每次调用该方法时,都会返回相同的 ImageData。
您宁愿在另一个 canvas 上重新绘制初始图像,其尺寸(高度和宽度)与作为模型参数给出的张量的形状相匹配。
// create a new canvas on which the initial canvas will be redrawn
const canvas = document.createElement('canvas');
// draws on the first 32 * 32 pixels
canvas.drawImage(photos, 0, 0, 32, 32);
// returns the imageData corresponding to the part of the canvas we drew
return canvas.getImageData(0, 0, 32, 32);
有了这个新的 imageData,不再需要使用 tf.bilinear
,tf.reshape
足以给张量所需的形状。
img = tf.image.reshape(img, [1, 32, 32, 3]);
我正在 ionic 3 框架中制作一个用于识别手写字符的应用程序,为此,我正在使用 tensorflowjs。问题是,当一切都解决后,预测总是 return 相同的值。
模型(使用 tensorflowjs-converter 从 keras 转换而来)本地存储在 assets/models/model.json
。
我试图预测的图像是从 HTMLCanvasElement 中提取的,您可以在其中绘制角色,然后函数 getCanvas()
从中检索 ImageData:
getCanvas() {
let photo = document.getElementById('MyCanvas') as HTMLCanvasElement;
let ctx = photo.getContext('2d');
const data: ImageData = ctx.createImageData(300,300);
return data;
}
然后,模型的输入张量 [1, 32, 32, 3]
是从 data
计算出来的,然后,我用 evaluateModel()
将它提供给模型。在该函数中,我用 tf.loadModel()
加载 model.json
并尝试预测图像的 class:
import * as tf from '@tensorflow/tfjs';
async evaluateModel() {
imageData: ImageData = this.getCanvas();
const modelURL: string = './../../assets/models/model.json';
let img: tf.Tensor<tf.Rank.R3> = tf.fromPixels(imageData);
img = tf.image.resizeBilinear(img, [32, 32]);
img = img.expandDims(0);
await tf.loadModel(modelURL).then(model => {
const output: any = model.predict(img);
const results: number = output.argMax(1).dataSync()[0];
console.log(results);
}
一切正常,没有任何错误,但是当将输出预测记录到控制台时,它总是 return 相同的值。此外,预测数组非常平坦,指出 python 中的模型在测试 :
中达到 99,01% 的准确度console.log(Array.from(output.dataSync()));
17 /* Result of the argMax function on output */
[0.011652837507426739, 0.03457817807793617, 0.029257778078317642, 0.008851004764437675, 0.01691449247300625, 0.026485547423362732, 0.04974032938480377, 0.016473202034831047, 0.021701140329241753, 0.020724112167954445, 0.03173287212848663, 0.024661116302013397, 0.007072054781019688, 0.022814681753516197, 0.011404283344745636, 0.015105938538908958, 0.024694452062249184, 0.07453715801239014, 0.011547397822141647, 0.03946337103843689, 0.018134022131562233, 0.027423541992902756, 0.014102200977504253, 0.016702469438314438, 0.05513478443026543, 0.030478181317448616, 0.012863627634942532, 0.011269242502748966, 0.022525735199451447, 0.022545555606484413, 0.02840271405875683, 0.011758353561162949, 0.006561313755810261, 0.020660076290369034, 0.009705542586743832, 0.024312887340784073, 0.011940978467464447, 0.020643217489123344, 0.009319263510406017, 0.00957920216023922, 0.01844164915382862, 0.015434195287525654, 0.02170679345726967, 0.017867043614387512, 0.013763428665697575, 0.029312126338481903]
在尝试解决这个问题时,我想到的只有两件事:
- ImageData 未正确提取 canvas 绘图,因此预测总是 return 相同的值。
model.json
上的权重未被访问或加载,因此模型 return 具有相同的值。
有什么想法吗?
感谢任何帮助。
createImageData
创建一个带有透明黑色像素的新 ImageDate。因此,每次调用该方法时,都会返回相同的 ImageData。
您宁愿在另一个 canvas 上重新绘制初始图像,其尺寸(高度和宽度)与作为模型参数给出的张量的形状相匹配。
// create a new canvas on which the initial canvas will be redrawn
const canvas = document.createElement('canvas');
// draws on the first 32 * 32 pixels
canvas.drawImage(photos, 0, 0, 32, 32);
// returns the imageData corresponding to the part of the canvas we drew
return canvas.getImageData(0, 0, 32, 32);
有了这个新的 imageData,不再需要使用 tf.bilinear
,tf.reshape
足以给张量所需的形状。
img = tf.image.reshape(img, [1, 32, 32, 3]);