【问题标题】:How to upload image and pass in to tensorflowjs model to get prediction using reactjs?如何上传图像并传入 tensorflowjs 模型以使用 reactjs 进行预测?
【发布时间】:2021-07-15 11:50:30
【问题描述】:

编辑 使用图形模型格式和更新的代码示例,我设法让它返回一个预测。问题是现在它总是返回 1,无论我输入哪个图像,所以想知道我是否没有传递正确的图像数据?

第二次编辑:改变了我传递 img 对象的方式,但我输入的每张图片仍然得到 1。

我才刚刚开始研究 tensorflowjs,并且正在使用我已经获得访问权限的预构建 keras 模型。该模型是一个二元分类器。该模型已保存为.h5 文件,我被要求使用 tensorflowjs 在浏览器中运行它并做出反应。本质上,我想从本地存储或 sd 卡中选择图像并将其提供给模型以获得 yesno 分类。

我已按照 tensorflowjs docs 将 keras 模型转换为 TF.js 层格式,但无法加载模型。我收到关于 unknown layer: RandomFlip 的错误。因此,我尝试将模型转换为图形模型,因为我找不到错误的解决方案,并想尝试一下。这加载了模型,但是在给它提供图像时出现了更多问题。 The shape of dict['image_tensor'] provided in model.execute(dict) must be [-1,380,380,1], but was [380, 380] 。然后我搜索了它并将其调整为 [-1,380,380,1] ,但后来它抱怨尺寸不是预期的,所以我想我可能在前面的一些步骤中搞砸了。

为了转换为图形模型,我使用了以下命令:tensorflowjs_converter --input_format keras --output_format tfjs_layers_model /Users/myUser/Documents/save_at_45.h5 /Users/myUser/Documents/convert-keras-model,并在我的代码中使用loadGraphModel 方法加载它。遵循这条路径至少允许我加载模型。

我还尝试使用tensorflowjs_converter --input_format keras --output_format tfjs_layers_model /Users/myUser/Documents/save_at_45.h5 /myUser/mariomendes/Documents/convert-keras-model 将其转换为图层格式,并在我的代码中使用loadLayersModel 加载它。这将返回错误 Unknown layer: RandomFlip。我已经尝试寻找解决方案,但一直找不到。

知道它是.h5 文件是否意味着我应该知道它是否需要转换为 tf Graph 格式或 Layers 格式,或者是否有其他东西可以确定它应该转换为哪种格式?

我已将转换后的模型以两种格式存储,它的权重在 S3 中,并从那里获取。

对于我的反应代码,我做了以下事情:

import React, { useState, useEffect } from "react";
import "./index.css";
import * as tf from "@tensorflow/tfjs";

function ImgImporter() {
  const [file, setFile] = useState(null);
  const [model, setModel] = useState(null);
  const [processing, setProcessing] = useState(false);
  const [prediction, setPrediction] = useState(null);
  const [imageLoaded, setImageLoaded] = useState(false);

  function readImage(file) {
    return new Promise((rs, rj) => {
      const fileReader = new FileReader();
      fileReader.onload = () => rs(fileReader.result);
      fileReader.onerror = () => rj(fileReader.error);
      fileReader.readAsDataURL(file);
    });
  }

  async function handleImgUpload(event) {
    const {
      target: { files },
    } = event;

    const _file = files[0];
    const fileData = await readImage(_file);
    setFile(fileData);
    setProcessing(true);
  }

  useEffect(() => {
    async function loadModel() {
      if (!model) {
        const _model = await tf.loadGraphModel("/model.json");
        setModel(_model);
      }
    }

    loadModel();
  });

  useEffect(() => {
    async function predict() {
      if (imageLoaded && file) {
        const imageElement = document.createElement("img");
        imageElement.src = file;

        imageElement.onload = async () => {
          const tensor = tf.browser
            .fromPixels(imageElement, 1)
            .resizeNearestNeighbor([380, 380])
            .expandDims()
            .toFloat();

          const prediction = await model.predict(tensor).data();

          setPrediction(parseInt(prediction, 10));
          setProcessing(false);
          setImageLoaded(false);
        };
      }
    }

    predict();
  }, [imageLoaded, model, file]);

  return (
    <div className="File-input-container">
      <form className="Form">
        <label htmlFor="upload-image">Upload image</label>
        <input
          id="image-selector"
          type="file"
          name="upload-image"
          accept="image/*"
          className="File-selector"
          onChange={handleImgUpload}
          disabled={!model || processing}
        />
      </form>
      <div className="Img-display-container">
        <img
          onLoad={() => {
            setImageLoaded(true);
          }}
          alt=""
          src={file}
        />
      </div>
      <div className="Img-processing-container">
        {processing ? (
          <p>Loading ...</p>
        ) : prediction !== null ? (
          <div>
            <p>{prediction === 1 ? "Yes" : "No"}</p>
          </div>
        ) : null}
      </div>
    </div>
  );
}

export default ImgImporter;

当我上传图片时,这将在控制台中返回以下结果作为预测值:

dataId: {id: 195}
dtype: "float32"
id: 94
isDisposedInternal: false
kept: false
rankType: "2"
scopeId: 6
shape: (2) [1, 1]
size: 1
strides: [1]

如果有人能对此有所了解或帮助我找到正确的方向,那就太好了。

【问题讨论】:

    标签: reactjs tensorflow keras tensorflow.js


    【解决方案1】:

    如果你想获得价值,你可以使用prediction.dataSync()或者它的promise对应的await prediction.data()

    【讨论】:

    • 谢谢。我这样做了。它仍然没有解释我应该将模型转换为哪种格式,或者它背后的原因。
    • 但是,鉴于图形格式是唯一似乎可行的格式,我想可以安全地假设它应该转换为格式?
    • 如果你有一个图模型,那么你需要使用图格式转换它。同样,如果你有一个分层模型,那么你需要使用层格式来转换它
    【解决方案2】:

    关于您的第二次编辑。您正在将图像转换为浮点数,但模型是否需要标准化浮点数?您可能需要附加 .div(255) 或任何需要的规范化。请发布您的型号的规格。

    此外,正如 edkeveked 所述,您可以使用 dataSync() 获取数据,但值得注意的是,您也可以使用 arraySync,这将保持返回的张量深度。

    另外,我注意到你没有做任何清理工作。因此,您的张量将在 GPU 内存中建立。不要忘记丢弃。

    我希望这些事情有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-11-11
      • 1970-01-01
      • 2020-04-22
      • 2023-03-24
      • 2021-11-03
      • 2020-11-15
      • 2014-09-12
      • 1970-01-01
      • 2022-11-06
      相关资源
      最近更新 更多