在转换后的 tflite 模型上调用 `allocate_tensors()` 时出现 RuntimeError

RuntimeError when calling `allocate_tensors()` on converted tflite model

我遵循 great tutorial 使用 TF-Lite 部署 TensorFlow 模型,一切正常。但是,当我尝试使用自己的模型(从保存的 keras 模型转换而来)时,调用 allocate_tensors() 方法时出现以下错误:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-73-6b4d64de8090> in <module>
      1 #interpreter = tflite.Interpreter(model_path='model.tflite')
      2 interpreter = tflite.Interpreter(model_path=lite_model_location)
----> 3 interpreter.allocate_tensors()

~/pyenv/srcnn/lib/python3.6/site-packages/tflite_runtime/interpreter.py in allocate_tensors(self)
    257   def allocate_tensors(self):
    258     self._ensure_safe()
--> 259     return self._interpreter.AllocateTensors()
    260 
    261   def _safe_to_run(self):

RuntimeError: external/org_tensorflow/tensorflow/lite/core/subgraph.cc BytesRequired number of elements overflowed.
Node number 0 (CONV_2D) failed to prepare.

我认为这与我转换模型的方式有关,但 tf.lite.TFLiteConverter 中描述的选项中的 none 有帮助。

可以找到我要加载的 tflite 模型 here, which is a converted version of the saved keras model found here

model from the tutorial 没有问题。我注意到这些模型的 tflite 版本在输入细节上存在差异。例如教程模型(working):

{'name': 'input',
 'index': 88, 
 'shape': array([  1, 224, 224,   3], dtype=int32),
 'shape_signature': array([  1, 224, 224,   3], dtype=int32),
 'dtype': <class 'numpy.uint8'>, 
 'quantization': (0.0078125, 128), 
 'quantization_parameters': {'scales': array([0.0078125], dtype=float32),
 'zero_points': array([128], dtype=int32),
 'quantized_dimension': 0},
 'sparsity_parameters': {}}

虽然我的非工作 tflite 模型的输入详细信息是:

{'name': 'input_1',
 'index': 0,
 'shape': array([1, 1, 1, 3], dtype=int32),
 'shape_signature': array([-1, -1, -1,  3], dtype=int32),
 'dtype': <class 'numpy.float32'>,
 'quantization': (0.0, 0),
 'quantization_parameters': {'scales': array([], dtype=float32),
 'zero_points': array([], dtype=int32),
 'quantized_dimension': 0}, 
 'sparsity_parameters': {}}

会不会是转换的问题?该模型在使用 keras 的开发中运行良好,并且应该能够接受可变 x 和 y 维度(图像大小)的输入。我不认为 dtypes 是这里的问题,因为根据文档应该支持 uint8float32

好的,事实证明很容易修复。当使用具有未知输入维度的 CNN 时(即此处 shape_signature 中的 -1,由输入层中设置 -1 引起),输入张量中的未知维度设置为 1.要在使用这样的模型时正确分配模型,您必须做两件事:

  1. 手动设置输入张量的形状为输入数据的形状,例如interpreter.resize_tensor_input(0, [1, input_shape[0], input_shape[1], 3], strict=True).
  2. 手动设置输入数据的 dtype 以匹配模型输入层的数据,在输入详细信息中的 'dtype' 条目中看到。

这似乎是在常规 TensorFlow 中自动完成的,但在 Lite 版本中必须像这样准备模型。

编辑:关于设置输入数据的 dtype,这是在从图像格式导入后,在调用 allocate_tensors() 之前转换为 numpy.array 时完成的。您可以看到 TF implementation (line 332) and the TFLite implmentation (line 77).

之间的区别