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

the*_*ode 11 python-3.x tensorflow tensorflow-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.
Run Code Online (Sandbox Code Playgroud)

它发生在我将图像调整为 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)
Run Code Online (Sandbox Code Playgroud)

Sus*_*nth 14

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

导致此错误的函数是:

def _ensure_safe(self)
Run Code Online (Sandbox Code Playgroud)

def _safe_to_run(self)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

interpreter.allocate_tensors()

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

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

要清除它们:

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

b)。或者简单地再次加载模型,即在您的 jupyter notebook 中再次运行此行:

interpreter = tf.lite.Interpreter(model_path="C:\\Users\\USER\\Documents\\python\\converted_quant_model_cnn_5_100.tflite")
Run Code Online (Sandbox Code Playgroud)

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

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

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