在转换后的 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 是这里的问题,因为根据文档应该支持 uint8
和 float32
。
好的,事实证明很容易修复。当使用具有未知输入维度的 CNN 时(即此处 shape_signature
中的 -1
,由输入层中设置 -1
引起),输入张量中的未知维度设置为 1
.要在使用这样的模型时正确分配模型,您必须做两件事:
- 手动设置输入张量的形状为输入数据的形状,例如
interpreter.resize_tensor_input(0, [1, input_shape[0], input_shape[1], 3], strict=True)
.
- 手动设置输入数据的
dtype
以匹配模型输入层的数据,在输入详细信息中的 'dtype'
条目中看到。
这似乎是在常规 TensorFlow 中自动完成的,但在 Lite 版本中必须像这样准备模型。
编辑:关于设置输入数据的 dtype
,这是在从图像格式导入后,在调用 allocate_tensors()
之前转换为 numpy.array
时完成的。您可以看到 TF implementation (line 332) and the TFLite implmentation (line 77).
之间的区别
我遵循 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 是这里的问题,因为根据文档应该支持 uint8
和 float32
。
好的,事实证明很容易修复。当使用具有未知输入维度的 CNN 时(即此处 shape_signature
中的 -1
,由输入层中设置 -1
引起),输入张量中的未知维度设置为 1
.要在使用这样的模型时正确分配模型,您必须做两件事:
- 手动设置输入张量的形状为输入数据的形状,例如
interpreter.resize_tensor_input(0, [1, input_shape[0], input_shape[1], 3], strict=True)
. - 手动设置输入数据的
dtype
以匹配模型输入层的数据,在输入详细信息中的'dtype'
条目中看到。
这似乎是在常规 TensorFlow 中自动完成的,但在 Lite 版本中必须像这样准备模型。
编辑:关于设置输入数据的 dtype
,这是在从图像格式导入后,在调用 allocate_tensors()
之前转换为 numpy.array
时完成的。您可以看到 TF implementation (line 332) and the TFLite implmentation (line 77).