使用 MobileNet 重新训练图像检测
Posted
技术标签:
【中文标题】使用 MobileNet 重新训练图像检测【英文标题】:Retrain image detection with MobileNet 【发布时间】:2019-09-14 21:18:04 【问题描述】:重新训练 MobileNet 以与 Tensorflow.js 一起使用的几种方法对我来说都失败了。有没有办法通过 Tensorflow.js 使用重新训练的模型?
使用基于中心的现代教程以及使用 retrain.py
似乎都失败了。
以及其他一些未解决的问题
Retrain an Image Classifier in tensorflow js Loading of mobilenet v2 works, but pretrained mobilenet v2 fails Can't convert TensorFlow saved model to tfjs_layers_model webmodel前两个问题显示了在这两种情况下都失败的代码,都没有解决。
目的是加载移动网络,使用自定义数据重新训练,并在 Tensorflow.js 中使用它。遵循这两个教程似乎都失败了。这可以在 node.js 中完成吗?还有其他方法吗?我在哪里犯了错误(或者软件无法使用重新训练的模型)?这怎么行?
编辑:latest github issue 和另外一个问题
【问题讨论】:
使用mobilenet进行图像检测进行迁移学习在this article进行了解释 @edkeveked:您的文章似乎使用 mobilenet 作为特征提取器。这个问题的目的是发布一个已经训练过的模型。 【参考方案1】:也许有人可以使用我的方式修改retain.py 以支持mobileV2。 原来的 retrain.py link。这个链接是谷歌的 GitHub 代码,不是我的链接。
我改变了retrain.py,下面是我的git diff:
diff --git a/scripts/retrain.py b/scripts/retrain.py
index 5fa9b0f..02a4f9a 100644
--- a/scripts/retrain.py
+++ b/scripts/retrain.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -112,6 +114,13 @@ from tensorflow.python.framework import graph_util
from tensorflow.python.framework import tensor_shape
from tensorflow.python.platform import gfile
from tensorflow.python.util import compat
+from tensorflow import saved_model as sm
+from tensorflow.python.saved_model import builder as saved_model_builder
+from tensorflow.python.saved_model import signature_constants
+from tensorflow.python.saved_model import signature_def_utils
+from tensorflow.python.saved_model import tag_constants
+from tensorflow.python.saved_model import utils as saved_model_utils
+
FLAGS = None
@@ -319,6 +328,7 @@ def maybe_download_and_extract(data_url):
Args:
data_url: Web location of the tar file containing the pretrained model.
"""
+ print(FLAGS.model_dir)
dest_directory = FLAGS.model_dir
if not os.path.exists(dest_directory):
os.makedirs(dest_directory)
@@ -827,6 +837,7 @@ def save_graph_to_file(sess, graph, graph_file_name):
sess, graph.as_graph_def(), [FLAGS.final_tensor_name])
with gfile.FastGFile(graph_file_name, 'wb') as f:
f.write(output_graph_def.SerializeToString())
+
return
@@ -971,6 +982,7 @@ def main(_):
# Prepare necessary directories that can be used during training
prepare_file_system()
+ sigs =
# Gather information about the model architecture we'll be using.
model_info = create_model_info(FLAGS.architecture)
@@ -1002,6 +1014,9 @@ def main(_):
FLAGS.random_brightness)
with tf.Session(graph=graph) as sess:
+ serialized_tf_example = tf.placeholder(tf.string, name='tf_example')
+ feature_configs = 'x': tf.FixedLenFeature(shape=[784], dtype=tf.float32),
+ tf_example = tf.parse_example(serialized_tf_example, feature_configs)
# Set up the image decoding sub-graph.
jpeg_data_tensor, decoded_image_tensor = add_jpeg_decoding(
model_info['input_width'], model_info['input_height'],
@@ -1133,6 +1148,73 @@ def main(_):
(test_filename,
list(image_lists.keys())[predictions[i]]))
+ """
+ # analyze SignatureDef protobuf
+ SignatureDef_d = graph.signature_def
+ SignatureDef = SignatureDef_d[sm.signature_constants.CLASSIFY_INPUTS]
+
+ # three TensorInfo protobuf
+ X_TensorInfo = SignatureDef.inputs['input_1']
+ scale_TensorInfo = SignatureDef.inputs['input_2']
+ y_TensorInfo = SignatureDef.outputs['output']
+
+ # Tensor details
+ # .get_tensor_from_tensor_info() to get default graph
+ X = sm.utils.get_tensor_from_tensor_info(X_TensorInfo, sess.graph)
+ scale = sm.utils.get_tensor_from_tensor_info(scale_TensorInfo, sess.graph)
+ y = sm.utils.get_tensor_from_tensor_info(y_TensorInfo, sess.graph)
+ """
+
+ """
+ output_graph_def = graph_util.convert_variables_to_constants(
+ sess, graph.as_graph_def(), [FLAGS.final_tensor_name])
+
+ X_TensorInfo = sm.utils.build_tensor_info(bottleneck_input)
+ scale_TensorInfo = sm.utils.build_tensor_info(ground_truth_input)
+ y_TensorInfo = sm.utils.build_tensor_info(output_graph_def)
+
+ # build SignatureDef protobuf
+ SignatureDef = sm.signature_def_utils.build_signature_def(
+ inputs='input_1': X_TensorInfo, 'input_2': scale_TensorInfo,
+ outputs='output': y_TensorInfo,
+ method_name='what'
+ )
+ """
+
+ #graph = tf.get_default_graph()
+ tensors_per_node = [node.values() for node in graph.get_operations()]
+ tensor_names = [tensor.name for tensors in tensors_per_node for tensor in tensors]
+ print(tensor_names)
+
+ export_dir = './tf_files/savemode'
+ builder = saved_model_builder.SavedModelBuilder(export_dir)
+
+ # name="" is important to ensure we don't get spurious prefixing
+ graph_def = tf.GraphDef()
+ tf.import_graph_def(graph_def, name="")
+ g = tf.get_default_graph()
+ inp1 = g.get_tensor_by_name("input:0")
+ inp2 = g.get_tensor_by_name("input_1/BottleneckInputPlaceholder:0")
+ inp3 = g.get_tensor_by_name("input_1/GroundTruthInput:0")
+ out = g.get_tensor_by_name("accuracy_1:0")
+
+ sigs[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY] = \
+ tf.saved_model.signature_def_utils.predict_signature_def(
+ 'input_1': inp1, 'input_2': inp3, "output": out)
+
+ builder.add_meta_graph_and_variables(sess,
+ tags=[tag_constants.SERVING],
+ signature_def_map=sigs)
+
+ """
+ builder.add_meta_graph_and_variables(
+ sess=sess,
+ tags=[tag_constants.SERVING],
+ signature_def_map=sm.signature_constants.CLASSIFY_INPUTS: SignatureDef)
+ """
+
+ builder.save()
+
# Write out the trained graph and labels with the weights stored as
# constants.
save_graph_to_file(sess, graph, FLAGS.output_graph)
使用我的差异,我可以生成 Tensorflow Served 模型。 然后我使用命令将 TensorFlow 服务模型转换为 Tfjs 模型。
tensorflowjs_converter \
--input_format=tf_saved_model \
--output_format=tfjs_graph_model \
./tf_files/savemode \
./tf_files/js_model
最后的 Tensorflow JS 版本仍然不支持 Ops。
我只是做了一个视频here来解释为什么我们不能将Tensorflow冻结模型转换为Tensorflow JS模型,告诉如何找到输入张量和输出张量。运行步骤和结果,最后给出不支持的 Ops ScalarSummary 和原因。
现在我无法将 Mobilenet 模型更改为 Tensorflow JS 模型,所以我的解决方法是在服务器端使用 Python tensorflow 和 flask 库,用户将图像上传到服务器然后返回结果。
【讨论】:
感谢您在 *** 上帮助用户。尽管您花时间制作了视频,但这里的答案应该保持独立的自包含解释,而不是依赖外部资源来理解。如果您在答案中添加足够的解释,则可以保留您的视频链接,这样您就不需要观看视频链接来获得答案。 你试过as @MahalovIvan suggested吗? @serv-inc 我已经尝试过了,但仍然无法得到正确的结果。 @LéaGris 谢谢,我会为这个答案添加更多解释。【参考方案2】:我遇到了同样的问题,似乎我们使用了错误的方法。 TF 转换模型有 loadGraphModel,Keras 有 loadLayersModel my comment about the issue
【讨论】:
【参考方案3】:要使用最新的 TFjs:
python retrain.py --tfhub_module https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/2 \
--image_dir /tmp/flower_photos --saved_model_dir /tmp/saved_retrained_model
tensorflowjs_converter --input_format=tf_saved_model \
--output_format=tfjs_graph_model \
--saved_model_tags=serve \
/tmp/saved_retrained_model/ /tmp/converted_model/
创建一个model.json
文件。 https://github.com/tensorflow/tfjs-converter#step-1-converting-a-savedmodel-keras-h5-tfkeras-savedmodel-or-tensorflow-hub-module-to-a-web-friendly-format中描述的命令。
然而,用tf.loadLayersModel("file:///tmp/web_model/model.json")
加载模型失败了
'className' 和 'config' 必须设置。
【讨论】:
你好,你能看看这个:***.com/questions/64621656/… 您好,application_mobilenet
定义在哪里?
我从 kera 的文档 keras.io/api/applications/mobilenet 中获取了那个 sn-p 【参考方案4】:
retrain.py
python 脚本不会生成保存的模型,它实际上会生成冻结的图模型。这就是您无法使用 tfjs 1.x 转换器对其进行转换的原因。您需要使用 tfjs 0.8.5 pip 进行转换。
此外,输出节点名称与 mobilenet 模型图不同,它是重新训练图的“final_result”。
要转换它,您需要使用 tensorflowjs 0.8.5 pip:
使用 virtualenv 创建一个空的 env。 pip install tensorflowjs==0.8.5 运行转换器tensorflowjs_converter \
--input_format=tf_frozen_model \
--output_node_names='final_result' \
--output_json=true /tmp/output_graph.pb \ /tmp/web_model
这应该会给你如下内容:
ls /tmp/web_model/
group1-shard10of21 group1-shard14of21 group1-shard18of21 group1-shard21of21 group1-shard5of21 group1-shard9of21
group1-shard11of21 group1-shard15of21 group1-shard19of21 group1-shard2of21 group1-shard6of21 model.json
group1-shard12of21 group1-shard16of21 group1-shard1of21 group1-shard3of21 group1-shard7of21
group1-shard13of21 group1-shard17of21 group1-shard20of21 group1-shard4of21 group1-shard8of21
【讨论】:
我认为 retrain.py 脚本有一个 --saved_model_dir=/tmp/saved_models/ 选项,它将生成保存的模型输出。您应该尝试一下,看看是否可以使用 1.x 转换器对其进行转换。谢谢。 使用tf.loadLayersModel("file:///tmp/web_model/model.json")
加载模型失败,“className”和“config”必须设置。”
转换器最新版本(1.3.2)现在支持冻结模型。
你好,你可以看看这个:***.com/questions/64621656/…以上是关于使用 MobileNet 重新训练图像检测的主要内容,如果未能解决你的问题,请参考以下文章
Google 对象检测 API - 使用 faster_rcnn_resnet101_coco 模型进行训练
图像分类任务不用冷启动,PaddlePaddle一口气发布十大预训练模型