首页 > 解决方案 > 如何修复“在解释器中至少有 1 个以 numpy 数组或切片的形式引用的内部数据”并在 tf.lite 上运行推理

问题描述

我正在尝试在 mnist keras 模型上使用 tf.lite 运行推理,该模型我通过根据此进行训练后量化进行了优化

RuntimeError: There is at least 1 reference to internal data
in the interpreter in the form of a numpy array or slice. Be sure to
only hold the function returned from tensor() if you are using raw
data access.

它发生在我将图像调整为 4 维或解释器本身的大小(如注释行中所示)之后;因为在此之前的错误类似于“预期 4 个维度但发现 3 个”。这是代码:

import tensorflow as tf
tf.enable_eager_execution()
import numpy as np
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt
%matplotlib inline

mnist_train, mnist_test = tf.keras.datasets.mnist.load_data()
images, labels = tf.cast(mnist_test[0], tf.float32)/255.0, mnist_test[1]
images = np.reshape(images,[images.shape[0],images.shape[1],images.shape[2],1])
mnist_ds = tf.data.Dataset.from_tensor_slices((images, labels)).batch(1, drop_remainder = True)

interpreter = tf.lite.Interpreter(model_path="C:\\Users\\USER\\Documents\\python\\converted_quant_model_cnn_5_100.tflite")
#tf.lite.Interpreter.resize_tensor_input(interpreter, input_index="index" , tensor_size=([1,28,28,1]) )

interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
input_index = interpreter.get_input_details()[0]["index"]
output_index = interpreter.get_output_details()[0]["index"]

for img, label in mnist_ds.take(1):
  break
#print(img.get_shape)
interpreter.set_tensor(input_index, img)
interpreter.invoke()
predictions = interpreter.get_tensor(output_index)

标签: python-3.xtensorflowtensorflow-lite

解决方案


在 tflite 模型上运行推理时,我遇到了同样的问题。回溯时,我最终阅读了发生此运行时错误的函数。

导致此错误的函数是:

def _ensure_safe(self)

def _safe_to_run(self)

从函数“_ensure_safe()”中调用函数“_safe_to_run()”。_safe_to_run() 函数返回 True 或 False。当它返回 False 时,会发生上述运行时错误。

当存在 numpy 数组缓冲区时,它返回 False。这意味着运行可能会破坏(或更改)内部分配的内存的 tflite 调用是不安全的。

因此,为了使“_ensure_safe()”函数不引发此运行时错误,我们必须确保没有指向内部缓冲区的 numpy 数组处于活动状态。

此外,为了更清楚起见,应从任何将调用 _interpreter 上可能重新分配内存的函数的函数调用函数“_ensure_safe()”。因此,当您调用该函数时

interpreter.allocate_tensors()

正如您在上面的代码中提到的,这个“interpreter.allocate_tensors()”函数在内部执行的第一件事是调用“_ensure_safe()”函数,因为“interpreter.allocate_tensors()”涉及更改内部分配的内存(在顾名思义,这种情况改变意味着“分配”)。另一个同时调用“_ensure_safe()”的示例是调用“invoke()”函数时。并且有很多这样的功能,但你明白了。

既然知道了根本原因和工作原理,为了克服这个运行时错误,即没有指向内部缓冲区的 numpy 数组,我们必须清除它们。

要清除它们:

一个)。关闭您的 jupyter notebook 并重新启动内核,因为这将清除所有 numpy 数组/切片

乙)。或者简单地再次加载模型,即在你的 jupyter notebook 中再次运行这一行:

interpreter = tf.lite.Interpreter(model_path="C:\\Users\\USER\\Documents\\python\\converted_quant_model_cnn_5_100.tflite")

这希望能解决你的问题,我向你保证它对我有用。

如果这两个选项都没有,那么在上面的解释中我已经指出了“为什么”会发生这个错误。因此,如果您发现“没有指向内部缓冲区的 numpy 数组”的其他方法,请分享。

参考:https ://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/python/interpreter.py


推荐阅读