python-3.x - 如何修复“在解释器中至少有 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)
解决方案
在 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
推荐阅读
- c# - 如何使用 C# 在带有 Appium 的 iPhone 上单击视频播放按钮?
- typescript - 检查打字稿中的可选属性
- python - 如何在python3中打印/输出重叠的钻石
- python - Wait for and then click an item?
- typescript - 打字稿中带有raycaster的three.js(鼠标悬停)
- excel - 如何以某种方式拆分单元格?
- .htaccess - http://www.www.example.com 重定向到 https://www.example.com
- c# - 错误 CS0029 无法隐式转换类型“System.Collections.Generic.IEnumerable”
'到'字符串' - c# - ChildActionOnly 输出缓存未禁用
- c# - Azure 文件共享使用引发 Int32 错误