无法在类型为 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 可以在以下位置找到:
根据@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 存储库进行了一些必要的更改,代码运行良好。
我正在尝试在 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 可以在以下位置找到:
根据@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 存储库进行了一些必要的更改,代码运行良好。