无法在类型为 FLOAT32 的 TensorFlowLite 张量和 Java 对象之间进行转换

Cannot convert between a TensorFlowLite tensor with type FLOAT32 and a Java object

我正在尝试在 Android 上使用 TFlite 构建推荐系统。我已经成功地创建了模型并且还运行 推断了相同的,运行ning 非常好。但问题在于尝试将应用程序与模型集成。我正在尝试将模型集成到 tensorflow 团队提供的官方应用程序中。我已经完成了他们要求的所有步骤,但我面临的问题是关于模型的 input/output。我遇到错误说:

Cannot convert between a TensorFlowLite tensor with type FLOAT32 and a Java object of type [I (which is compatible with the TensorFlowLite type INT32).

我无法理解此错误的含义,也没有任何相关文档。 官方代码中用于输入输出的代码如下: 这是定义输入和输出的主要代码:

/** Given a list of selected items, and returns the recommendation results. */
  @WorkerThread
  public synchronized List<Result> recommend(List<MovieItem> selectedMovies) {
    Object[] inputs = preprocess(selectedMovies);

    // Run inference.
    float[] outputIds = new float[config.outputLength];
    float[] confidences = new float[config.outputLength];
    Map<Integer, Object> outputs = new HashMap<>();
    outputs.put(config.outputIdsIndex, outputIds);
    outputs.put(config.outputScoresIndex, confidences);
    tflite.runForMultipleInputsOutputs(inputs, outputs);

    return postprocess(outputIds, confidences, selectedMovies);
  }

这定义了预处理部分:


  int[] preprocessIds(List<MovieItem> selectedMovies, int length) {
    int[] inputIds = new int[length];
    Arrays.fill(inputIds, config.pad); // Fill inputIds with the default.
    int i = 0;
    for (MovieItem item : selectedMovies) {
      if (i >= inputIds.length) {
        break;
      }
      inputIds[i] = item.id;
      ++i;
    }
    return inputIds;
  }

  int[] preprocessGenres(List<MovieItem> selectedMovies, int length) {
    // Fill inputGenres.
    int[] inputGenres = new int[length];
    Arrays.fill(inputGenres, config.unknownGenre); // Fill inputGenres with the default.
    int i = 0;
    for (MovieItem item : selectedMovies) {
      if (i >= inputGenres.length) {
        break;
      }
      for (String genre : item.genres) {
        if (i >= inputGenres.length) {
          break;
        }
        inputGenres[i] = genres.containsKey(genre) ? genres.get(genre) : config.unknownGenre;
        ++i;
      }
    }
    return inputGenres;
  }

  /** Given a list of selected items, preprocess to get tflite input. */
  @WorkerThread
  synchronized Object[] preprocess(List<MovieItem> selectedMovies) {
    List<Object> inputs = new ArrayList<>();

    // Sort features.
    List<Feature> sortedFeatures = new ArrayList<>(config.inputs);
    Collections.sort(sortedFeatures, (Feature a, Feature b) -> Integer.compare(a.index, b.index));

    for (Feature feature : sortedFeatures) {
      if (Config.FEATURE_MOVIE.equals(feature.name)) {
        inputs.add(preprocessIds(selectedMovies, feature.inputLength));
      } else if (Config.FEATURE_GENRE.equals(feature.name)) {
        inputs.add(preprocessGenres(selectedMovies, feature.inputLength));
      } else {
        Log.e(TAG, String.format("Invalid feature: %s", feature.name));
      }
    }
    return inputs.toArray();
  }

要使建议生效,需要进行哪些更改?

编辑: 我能够解决上述问题。我发现 genres 所需的输入是 float 类型的,因此将 genres 的 float 数组作为输入传递,问题就解决了。 但是,出现了一个新错误:

java.lang.IllegalStateException: Internal error: Unexpected failure when preparing tensor allocations: tensorflow/lite/kernels/reshape.cc:66 num_input_elements != num_output_elements (10 != 32) Node number 0 (RESHAPE) failed to prepare.

问题与输入和输出元素不匹配有关。我无法找出相同的解决方案。


link到model.tflite可以在这里找到:

https://drive.google.com/file/d/1CZxlJRqLZmwrsmgcA8lBz6XCh2KG3lWa/view?usp=sharing

这个问题是完全混乱和被 colab 文件误导的结果。 tensorflow/examples/recommendation 中的 colab 文件指导创建具有三个输入的 tensorflow lite 模型,即 genre、rating 和 movie-id ,但同一存储库中的 android 应用程序实现了需要考虑的代码只有两个输入,即 movie id 和 genre 。 colab 可以在以下位置找到:

https://colab.research.google.com/github/tensorflow/examples/blob/master/lite/examples/recommendation/ml/ondevice_recommendation.ipynb#scrollTo=og0qkYavz3Nt

根据@Farmaker 给出的指导,我可视化了我的模型和存在于 tensorflow-recommendation 存储库中的 android 应用程序中的模型。它看起来像这样:

My-model :

Google's-model :

我没有考虑 android 中用于解释 .tflite 模型的代码,盲目地遵循了 Google colab 文件,其中它只是提到了 .tflite 与 android 的协作,而没有需要任何额外编码。

解决方案:
第一个错误:

Cannot convert between a TensorFlowLite tensor with type FLOAT32 and a Java object of type [I (which is compatible with the TensorFlowLite type INT32).

由于输入对象需要采用模型要求的特定格式,因此第二个输入应该是 float 类型,但我将其作为参数传递给它。这导致了特定错误,该错误在以特定顺序传递参数后得到解决,这是 .tflite 模型所需的格式。

第二个错误:

java.lang.IllegalStateException: Internal error: Unexpected failure when preparing tensor allocations: tensorflow/lite/kernels/reshape.cc:66 num_input_elements != num_output_elements (10 != 32) Node number 0 (RESHAPE) failed to prepare.

这个错误是由于 genres 参数要求浮点数组的大小为 32,但我只为模型提供了一个大小为 10 的浮点数组,根据观察错误可以很容易地说出来。我通过传递大小为 32 的流派浮点数组解决了这个问题。

我对推荐系统的 android 存储库进行了一些必要的更改,代码运行良好。