将 Facenet 模型 .pb 文件转换为 TFLITE 格式时出错

Posted

技术标签:

【中文标题】将 Facenet 模型 .pb 文件转换为 TFLITE 格式时出错【英文标题】:Error converting Facenet model .pb file to TFLITE format 【发布时间】:2019-05-04 21:51:05 【问题描述】:

我正在尝试使用以下命令在 Ubuntu 上使用 Tensorflow Lite 转换器转换基于我从 David Sandbergs Github 获得的 Inception ResNet 的预训练冻结 .pb:

/home/nils/.local/bin/tflite_convert
--output_file=/home/nils/Documents/frozen.tflite
--graph_def_file=/home/nils/Documents/20180402-114759/20180402-114759.pb 
--input_arrays=input 
--output_arrays=embeddings 
--input_shapes=1,160,160,3

但是,我收到以下错误:

2018-12-03 15:03:16.807431: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
Traceback (most recent call last):
File "/home/nils/.local/bin/tflite_convert", line 11, in <module>
sys.exit(main())
File "/home/nils/.local/lib/python3.6/site-packages/tensorflow/contrib/lite/python/tflite_convert.py", line 412, in main
app.run(main=run_main, argv=sys.argv[:1])
File "/home/nils/.local/lib/python3.6/site-packages/tensorflow/python/platform/app.py", line 125, in run
_sys.exit(main(argv))
File "/home/nils/.local/lib/python3.6/site-packages/tensorflow/contrib/lite/python/tflite_convert.py", line 408, in run_main
_convert_model(tflite_flags)
File "/home/nils/.local/lib/python3.6/site-packages/tensorflow/contrib/lite/python/tflite_convert.py", line 162, in _convert_model
output_data = converter.convert()
File "/home/nils/.local/lib/python3.6/site-packages/tensorflow/contrib/lite/python/lite.py", line 453, in convert
**converter_kwargs)
File "/home/nils/.local/lib/python3.6/site-packages/tensorflow/contrib/lite/python/convert.py", line 342, in toco_convert_impl
input_data.SerializeToString())
File "/home/nils/.local/lib/python3.6/site-packages/tensorflow/contrib/lite/python/convert.py", line 135, in toco_convert_protos
(stdout, stderr))
RuntimeError: TOCO failed see console for info.
b'2018-12-03 15:03:26.006252: I tensorflow/contrib/lite/toco/import_tensorflow.cc:1080] Converting unsupported operation: FIFOQueueV2\n2018-12-03 15:03:26.006322: I tensorflow/contrib/lite/toco/import_tensorflow.cc:1127] Op node missing output type attribute: batch_join/fifo_queue\n2018-12-03 15:03:26.006339: I tensorflow/contrib/lite/toco/import_tensorflow.cc:1080] Converting unsupported operation: QueueDequeueUpToV2\n2018-12-03 15:03:26.006352: I tensorflow/contrib/lite/toco/import_tensorflow.cc:1127] Op node missing output type attribute: batch_join\n2018-12-03 15:03:27.496676: I tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] Before Removing unused ops: 5601 operators, 9399 arrays (0 quantized)\n2018-12-03 15:03:28.603936: I tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] After Removing unused ops pass 1: 3578 operators, 6254 arrays (0 quantized)\n2018-12-03 15:03:29.418074: I tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] Before general graph transformations: 3578 operators, 6254 arrays (0 quantized)\n2018-12-03 15:03:29.420354: F tensorflow/contrib/lite/toco/graph_transformations/resolve_batch_normalization.cc:42] 
Check failed: IsConstantParameterArray(*model, bn_op->inputs[1]) && IsConstantParameterArray(*model, bn_op->inputs[2]) && IsConstantParameterArray(*model, bn_op->inputs[3]) Batch normalization resolution requires that mean, multiplier and offset arrays be constant.\nAborted (core dumped)\n'
None

如果我做对了,这可能是因为两个不受支持的操作,QueueDequeueUpToV2 和 FIFOQueueV2,但我不确定。 你有什么想法可能是什么问题或我该如何解决这个错误?这个错误甚至意味着什么?我希望这个模型在移动 android 设备上运行,还有其他选择吗? 版本: TensorFlow V1.12 Python 3.6.7 Ubuntu 18.04.1 LTS 在 VirtualBox 上 提前致谢!

【问题讨论】:

您是否在网络中使用了 BatchNormalization 层 我真的不知道,因为它是我刚从 David Sandbergs Github 下载的预训练模型。 This 似乎是架构。 this 是我正在使用的确切型号。非常感谢,Shubham,我迷路了。 你是如何冻结 TF 图的?您似乎遇到了与here 描述的类似问题。您是否尝试过加载模型并保存它,以确保其正确完成?另一种选择可能是 DL4J(Java 深度学习) 感谢您的回复!是的,它看起来确实像一些(尚未)支持的操作或层。与此同时,我找到了一个适合我的解决方案。 Google Firebase 的机器学习套件提供了一个可以使用的人脸(地标)检测 NN,效果很好。至于 David Sandberg 网络的 SVM 部分,我使用了 libsvm 的 Android 包装器。但是 DL4J 听起来确实很有趣,谢谢:) 【参考方案1】:

我已经解决了这个问题here,在这里也添加了sn-p:

我可以将 FaceNet .pb 转换为 .tflite 模型,以下是这样做的说明:

我们将量化预训练的 Facenet model,嵌入大小为 512。该模型在量化前的大小约为 95MB。

$ ls -l model_pc
total 461248
-rw-rw-r--@ 1 milinddeore  staff   95745767 Apr  9  2018 20180402-114759.pb

使用以下代码创建文件inference_graph.py

import tensorflow as tf
from src.models import inception_resnet_v1
import sys
import click
from pathlib import Path

@click.command()
@click.argument('training_checkpoint_dir', type=click.Path(exists=True, file_okay=False, resolve_path=True))
@click.argument('eval_checkpoint_dir', type=click.Path(exists=True, file_okay=False, resolve_path=True))

def main(training_checkpoint_dir, eval_checkpoint_dir):
    traning_checkpoint = Path(training_checkpoint_dir) / "model-20180402-114759.ckpt-275"
    eval_checkpoint = Path(eval_checkpoint_dir) / "imagenet_facenet.ckpt"
    data_input = tf.placeholder(name='input', dtype=tf.float32, shape=[None, 160, 160, 3])
    output, _ = inception_resnet_v1.inference(data_input, keep_probability=0.8, phase_train=False, bottleneck_layer_size=512)
    label_batch= tf.identity(output, name='label_batch')
    embeddings = tf.identity(output, name='embeddings')
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        saver = tf.train.Saver()
        saver.restore(sess, traning_checkpoint.as_posix())
        save_path = saver.save(sess, eval_checkpoint.as_posix())
        print("Model saved in file: %s" % save_path)

if __name__ == "__main__":
     main()

在预训练模型上运行此文件,将生成模型进行推理。下载预训练模型并将其解压缩到 model_pre_trained/ 目录。 确保你有 python ≥ 3.4 版本。

python3 eval_graph.py model_pre_trained/ model_inference/

FaceNet 提供了freeze_graph.py 文件,我们将使用它来冻结推理模型。

python3  src/freeze_graph.py model_inference/  my_facenet.pb

生成冻结模型后,将其转换为.tflite

$ tflite_convert --output_file model_mobile/my_facenet.tflite --graph_def_file my_facenet.pb  --input_arrays "input" --input_shapes "1,160,160,3" --output_arrays embeddings --output_format TFLITE --mean_values 128 --std_dev_values 128 --default_ranges_min 0  --default_ranges_max 6 --inference_type QUANTIZED_UINT8 --inference_input_type QUANTIZED_UINT8

让我们检查量化后的模型大小:

$ ls -l model_mobile/
total 47232
-rw-r--r--@ 1 milinddeore  staff  23667888 Feb 25 13:39 my_facenet.tflite

拦截器代码:

 import numpy as np
 import tensorflow as tf


 # Load TFLite model and allocate tensors.
 interpreter = tf.lite.Interpreter(model_path="/Users/milinddeore/facenet/model_mobile/my_facenet.tflite")
 interpreter.allocate_tensors()

 # Get input and output tensors.
 input_details = interpreter.get_input_details()
 output_details = interpreter.get_output_details()

 # Test model on random input data.
 input_shape = input_details[0]['shape']
 input_data = np.array(np.random.random_sample(input_shape), dtype=np.uint8)
 interpreter.set_tensor(input_details[0]['index'], input_data)

 interpreter.invoke()
 output_data = interpreter.get_tensor(output_details[0]['index'])

 print('INPUTS: ')
 print(input_details)
 print('OUTPUTS: ')
 print(output_details)

解释器输出:

$ python inout.py
INPUTS:
['index': 451, 'shape': array([  1, 160, 160,   3], dtype=int32), 'quantization': (0.0078125, 128L), 'name': 'input', 'dtype': <type 'numpy.uint8'>]
OUTPUTS:
['index': 450, 'shape': array([  1, 512], dtype=int32), 'quantization': (0.0235294122248888, 0L), 'name': 'embeddings', 'dtype': <type 'numpy.uint8'>]

希望这会有所帮助!

【讨论】:

谢谢米林德!它也对我有用。只是为了扩展您的答案,它也适用于 Python2.7。 pip install pathlib will enable inference_graph 运行。 谢谢 Milind,我会在确认后尽快选择您的答案。与此同时,我使用了谷歌的 firebase ML 库。它为面部识别提供了一个非常相似的神经网络,而且效果很好:) 我有同样的问题,但使用了不同的模型 (mobilenet_v2 for openpose),因为您的解决方案依赖于 inception_resnet_v1.inference(),我无法真正将其转换为我的问题。有人知道,一般如何解决这个问题?我认为它涉及在冻结图形之前修复所有批处理规范参数,但我不知道该怎么做。【参考方案2】:

我对@milind-deore 的建议不满意。 该模型确实减少到 23 MB,但嵌入似乎被破坏了。

我找到了另一种方式:TF -> Keras -> TF Lite

David Sandberg 的 FaceNet 实现可以转换为 TensorFlow Lite,首先将从 TensorFlow 转换为 Keras,然后从 Keras 转换为 TensorFlow Lite

我创建了进行转换的this Google Colab。 大部分代码取自from here。

它的作用如下:

    下载Hiroki Taniai's Keras FaceNet implementation 用 my patched version 覆盖 inception_resnet_v1.py 文件(这确实为模型添加了一个额外的层以将标准化嵌入作为输出) 从here 下载 Sandberg 的预训练模型 (20180402-114759) 并解压缩 从检查点文件中提取张量并将权重写入磁盘上的 numpy 数组,映射每个相应层的名称。 使用随机权重创建一个新的 Keras 模型(重要提示:使用 512 个类)。 为从 numpy 数组中读取的每个对应层写入权重。 以 Keras 格式 .h5 存储模型

    使用命令“tflite_convert”将 Keras 转换为 TensorFlow Lite。

    tflite_convert --post_training_quantize --output_file facenet.tflite --keras_model_file /content/keras-facenet/model/keras/model/facenet_keras.h5

另外,在我的 Colab 中,我提供了一些代码来证明转换效果很好,并且 TFLite 模型确实有效。

distance bill vs bill 0.7266881 distance bill vs larry 1.2134411

因此,即使我没有对齐人脸,大约 1.2 的阈值也会有利于识别。

希望对你有帮助!

【讨论】:

感谢您的详细说明!我会调查的!

以上是关于将 Facenet 模型 .pb 文件转换为 TFLITE 格式时出错的主要内容,如果未能解决你的问题,请参考以下文章

将 tensorflow .pb 模型转换为 .mlmodel 时出错

facenet训练后模型使用tensorflow量化

将保存的 EfficientDet 模型 saved_model.pb 转换为 tflite 格式失败

TensorFlow:有没有办法将冻结图转换为检查点模型?

使用重新训练的 Tensorflow 对象检测模型使用 snpe 进行 pb 到 dlc 转换失败

TensorFlow 自定义模型导出:将 .ckpt 格式转化为 .pb 格式