我正在尝试使用TF Lite的C API来循环执行推理,比如我设置了解释器,每隔一秒左右给他输入一次,以获得预测结果。
为此,我建立了 libtensorflowlite_c.so
通过巴塞尔。如文件所述 此处我尝试像这样做推理,但在for循环中模拟循环执行。
#include "tensorflow/lite/c/c_api.h"
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[]) {
for(int i = 0; i < 3; i++)
{
printf("Iteration: %d\n", i);
float input[49] = { 0.0 };
TfLiteModel* model = TfLiteModelCreateFromFile("model.tflite");
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
TfLiteInterpreterOptionsSetNumThreads(options, 2);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
TfLiteInterpreterAllocateTensors(interpreter);
TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);
TfLiteTensorCopyFromBuffer(input_tensor, input, 49 * sizeof(float));
TfLiteInterpreterInvoke(interpreter);
const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);
float output[49];
TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));
printf("Output: \n\n");
for (int j = 0; j < 49; j++) {
printf("%d: %f\n", j, output[j]);
}
TfLiteInterpreterDelete(interpreter);
TfLiteInterpreterOptionsDelete(options);
TfLiteModelDelete(model);
}
return 0;
}
第一次迭代运行良好,并返回了一些东西。但在第二次迭代时,当我呼叫 TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));
. 原因是之前的函数 TfLiteInterpreterGetOutputTensor
返回一个nullpointer。
我期望多次运行这个函数而不会出现任何问题,因为我在for-loop结束时销毁了所有变量的旧实例,因此每次都会启动一个新的解释器。显然,事实并非如此。
谁能提供一些指导?另外,我知道我可能不需要在每次迭代时都创建一个解释器,但我想确保当我重新开始时,所有的东西都是新创建的。
EDIT.我试着重写了代码,使之成为一个新的解释器,但我想确保当我重新开始时,所有的东西都是新创建的。
我试着重写了代码,以排除实际循环中不必要的部分。
#include "tensorflow/lite/c/c_api.h"
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[]) {
float input[49] = {0.0};
float output[49] = {[0 ... 48] = 2.5};
TfLiteModel* model = TfLiteModelCreateFromFile("VariationalAutoencoder_440.tflite");
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
TfLiteInterpreterOptionsSetNumThreads(options, 2);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
TfLiteInterpreterAllocateTensors(interpreter);
TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);
const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);
for(int i = 0; i < 3; i++)
{
printf("\nIteration: %d\n", i);
TfLiteTensorCopyFromBuffer(input_tensor, input, 49 * sizeof(float));
TfLiteInterpreterInvoke(interpreter);
TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));
printf("Output: \n");
for (int j = 0; j < 49; j++)
{
printf("%02d: %f\n", j, output[j]);
}
}
TfLiteInterpreterDelete(interpreter);
TfLiteInterpreterOptionsDelete(options);
TfLiteModelDelete(model);
return 0;
}
删除所有变量声明外和之前的 for
循环,例如
int main (int argc, char* argv[]) {
float input[49] = { 0.0 };
float output[49] = {0.0};//also needs to be initialized
//and others...
for(int i = 0; i < 3; i++)
{
printf("Iteration: %d\n", i);
....
对任何创建可重用对象或分配内存的调用也要这样做。 在循环中重新声明可重用的对象(在重新声明之前不释放它们),其结果与调用 malloc
循环,而不是使用 realloc
的后续调用。
您的代码片段显示您有 创建 和 删除 在循环中调用以下内容。
TfLiteInterpreterDelete(interpreter);
TfLiteInterpreterOptionsDelete(options);
TfLiteModelDelete(model);
在循环中调用它也可能会有问题。
TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);
input_tensor
我认为应该先创建一次,然后在循环中根据需要调整大小。
从你提供的链接来看。
// NOTE: After a resize, the client *must* explicitly allocate tensors before
// attempting to access the resized tensor data or invoke the interpreter.
// REQUIRES: 0 <= input_index < TfLiteInterpreterGetInputTensorCount(tensor)
TFL_CAPI_EXPORT extern TfLiteStatus TfLiteInterpreterResizeInputTensor(
TfLiteInterpreter* interpreter, int32_t input_index, const int* input_dims,
int32_t input_dims_size);
编辑: 还有一个奇怪的地方
const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);
这个修饰词 const
蹇蹇 output_tensor
. 如果这个变量在循环中会发生变化,那么就不应该修改为 const
.
你的代码运行良好,如果 TfLiteInterpreterGetOutputTensor
下标 TfLiteInterpreterGetOutputTensorCount
.
也许张量指数14应该是13,但这取决于你的模型。
添加一些检查,如:
int count = TfLiteInterpreterGetOutputTensorCount(interpreter);
printf("output tensor count:%d\n", count);
if (count > 14) {
const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);
float output[49];
TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));
printf("Output: \n\n");
for (int j = 0; j < 49; j++) {
printf("%d: %f\n", j, output[j]);
}
}