我在Google Chrome | 76.0.3809.132 (Official Build) (64-bit)上使用tfjs 1.0.0
我在项目中使用ML5来训练图像分类模型。我使用了特征提取器进行迁移学习。我使用mobilenet_v1_0.25
作为基础模型。我希望将其整合,以便在Chrome扩展程序中进行预测。我不得不使用tfjs,因为我发现ML5无法在扩展的后台页面运行。我使用tfjs加载由ML5训练的模型,然后开始预测。然而,与在ML5本身使用相同模型进行预测相比,tfjs的预测准确率非常低。
我尝试通过抓取ML5特征提取器的源代码在tfjs中重现ML5的预测,但预测准确率在使用tfjs进行预测时仍然大幅下降。
我首先加载mobilenet和自定义模型以创建联合模型
load() { console.log("ML Data loading.."); // ! ========================================== // ! This is a work around and will only work for default version and alpha values that were used while training model. this.mobilenet = await tf.loadLayersModel("https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_0.25_224/model.json"); const layer = this.mobilenet.getLayer('conv_pw_13_relu'); // ! ========================================== this.mobilenetFeatures = await tf.model({ inputs: this.mobilenet.inputs, outputs: layer.output }); this.customModel = await tf.loadLayersModel("./model.json"); this.model.add(this.mobilenetFeatures); this.model.add(this.customModel);}
然后我将图像传递给一个函数,该函数在预测后获取前几类
let result = this.getTopKClasses(this.predict(image), 5)
getTopKClasses(logits, topK) { const predictions = logits; const values = predictions.dataSync(); predictions.dispose(); let predictionList = []; for (let i = 0; i < values.length; i++) { predictionList.push({ value: values[i], index: i }); } predictionList = predictionList .sort((a, b) => { return b.value - a.value; }) .slice(0, topK); console.log(predictionList); let site = predictionList[0]; let result = { type: 'custom', site: IMAGENET_CLASSES[site.index] } console.log('ML Result: Site: %s, Probability: %i%', result.site, (site.value * 100)); if (site.value > ML_THRESHOLD) { return result; } else { return null; }}predict(image) { const preprocessed = this.imgToTensor(image, [224, 224]) console.log(preprocessed); var result = this.model.predict(preprocessed); return result;}
辅助函数:
imgToTensor(input, size = null) { return tf.tidy(() => { let img = tf.browser.fromPixels(input); if (size) { img = tf.image.resizeBilinear(img, size); } const croppedImage = this.cropImage(img); const batchedImage = croppedImage.expandDims(0); return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1)); });}cropImage(img) { const size = Math.min(img.shape[0], img.shape[1]); const centerHeight = img.shape[0] / 2; const beginHeight = centerHeight - (size / 2); const centerWidth = img.shape[1] / 2; const beginWidth = centerWidth - (size / 2); return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);};
回答:
为了从使用迁移学习训练的模型(即在另一个预训练模型上训练的模型)进行预测,你需要首先从基础模型进行预测,然后通过将基础模型预测的张量传递给自定义模型的输入来进行自定义模型的预测。
async load(options = {}) { // 加载基础模型的层。 this.mobilenet = await tf.loadLayersModel(`${BASE_URL}${this.config.version}_${this.config.alpha}_${IMAGE_SIZE}/model.json`); const layer = this.mobilenet.getLayer(this.config.layer); // 将基础模型的层转换为模型。 this.mobilenetFeatures = await tf.model({ inputs: this.mobilenet.inputs, outputs: layer.output }); // 加载我们训练的自定义模型。 this.customModel = await tf.loadLayersModel(CUSTOM_MODEL_FILE_URL);}
现在从这些模型中进行预测:
predict(image) { // 将图像转换为张量 const preprocessed = this.imgToTensor(image, [224, 224]) // * 首先从Mobilenet(基础)模型对图像进行预测。 const embeddings = this.mobilenetFeatures.predict(preprocessed); // * 使用自定义训练的模型过滤Mobilenet模型的预测。 const result = this.customModel.predict(embeddings); return result;}