首页 > 解决方案 > 运行tflite模型时出现如下错误:input->params.scale != output->params.scale in MAX_POOL_2D Node

问题描述

我用tensorflow 1.12.0版本的量化感知训练方法训练了人脸识别模型。网络使用inception-resnet_v1(代码来源为tensorflow/models/research/slim/nets/)。训练完成后得到ckpt,然后新建freeze.py文件生成eval.pb,然后用toco成功生成tflite模型。但是当我最终用图像测试 tflite 模型时,我得到了以下错误:

File "src/test_tflite.py", line 21, in <module>
    Interpreter.allocate_tensors()
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/contrib/lite/python/interpreter.py", line 71, in allocate_tensors
    Return self._interpreter.AllocateTensors()
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/contrib/lite/python/interpreter_wrapper/tensorflow_wrap_interpreter_wrapper.py", line 106, in AllocateTensors
    Return _tensorflow_wrap_interpreter_wrapper.InterpreterWrapper_AllocateTensors(self)
RuntimeError: tensorflow/contrib/lite/kernels/pooling.cc:103 input->params.scale != output->params.scale (102483008 != 102482528)Node number 116 (MAX_POOL_2D) failed to prepare.

我尝试更换网络,inception-v3,inception-resnet-v2,但都得到了类似的错误。

我的训练代码是基于 facenet 框架的,我在原始训练的基础上做了一些小改动。定义total_loss_op后,添加以下两行代码:

train_graph = tf.get_default_graph()
tf.contrib.quantize.create_training_graph(input_graph=train_graph, quant_delay=20000)

在 freeze.py 文件中,当定义推理图时,我添加以下代码:</p>

g = tf.get_default_graph()
tf.contrib.quantize.create_eval_graph(input_graph=g)

然后加载之前训练好的ckpt,最后保存为pb文件。代码如下:

saver = tf.train.Saver(tf.global_variables())
sess = tf.Session()
with sess.as_default():
   saver.restore(sess, ckpt_model_path)
   frozen_graph_def = graph_util.convert_variables_to_constants(
             sess, sess.graph_def, ['embeddings'])
   tf.train.write_graph(
             frozen_graph_def,
             os.path.dirname(save_pb_path),
             os.path.basename(save_pb_path),
             as_text=False)

然后我用tensorflow1.12.0 toco工具转换pb文件,成功生成tflite。具体命令如下:

./bazel-bin/tensorflow/contrib/lite/toco/toco \
--input_file=inception_resnet_v1_fake_quantized_eval.pb \
--output_file=tflite_model.tflite \
--input_format=TENSORFLOW_GRAPHDEF \
--output_format=TFLITE \
--inference_type=QUANTIZED_UINT8 \
--input_shape="1,160,160,3" \
--input_array=input \
--output_array=embeddings \
--std_value=127.5 \
--mean_value=127.5 \
--default_ranges_min=-1.0 \
--default_ranges_max=1.0

最后,我使用生成的tflite模型来测试图像,我得到了以下错误。

RuntimeError: tensorflow/contrib/lite/kernels/pooling.cc:103 input->params.scale != output->params.scale (102483008 != 102482528)Node number 116 (MAX_POOL_2D) failed to prepare.

我的测试代码如下:

import numpy as np
import tensorflow as tf
import scipy

#Load TFLite model and allocate tensors.
interpreter = tf.contrib.lite.Interpreter(model_path="tensorflow-1.12.0/tflite_model.tflite")

interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
image = scipy.misc.imread("src/1511.jpg")
image_ = np.array([image.astype('uint8')])
print(image_.shape)
print(type(image_))
print(input_details)
print(output_details)
interpreter.set_tensor(input_details[0]['index'], image_)
interpreter.invoke()
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

标签: tensorflowtensorflow-litequantization

解决方案


在转换模型时,hardcode_min_max.cc中的函数HardcodeMinMaxForConcatenation将输入数组的 minmax 和连接层的输出数组调整为相同。

然后在同一个文件中的函数HardcodeMinMaxForAverageOrMaxPool将找到最大池化层的输出数组获取最小最大信息并跳过将其更改为与输入数组相同。

原来池化层的输入数组和输出数组的最小值不一样。

我相信这是一个错误。


推荐阅读