使用MobileNet重新训练图像检测

时间:2019-04-25 12:27:57

标签: tensorflow tensorflow.js tensorflowjs-converter mobilenet

重新培训MobileNet以用于Tensorflow.js的几种方法对我来说都是失败的。有什么办法可以在Tensorflow.js中使用重新训练的模型吗?

使用基于中心的现代教程以及使用retrain.py都似乎失败。

以及其他一些未解决的问题

另外两个问题显示了在两种情况下均失败的代码,均未解决。

目标是加载移动网络,使用自定义数据进行再训练,然后在Tensorflow.js中使用它。遵循这两个教程似乎都失败了。可以在node.js内部完成吗?还有另一种方法吗?我在哪里犯了错误(或者该软件无法使用经过重新训练的模型)?这怎么工作?

编辑:latest github issue和另外一个问题

4 个答案:

答案 0 :(得分:2)

retrain.py python脚本不会生成保存的模型,而是实际上生成了冻结的图形模型。这就是为什么您不能使用tfjs 1.x转换器对其进行转换的原因。您需要使用tfjs 0.8.5点进行转换。 另外,输出节点名称与mobilenet模型图不同,对于重新训练的图,它的名称为“ final_result”。

要转换它,您需要使用tensorflowjs 0.8.5点:

  • 使用virtualenv创建一个空的环境。
  • 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

答案 1 :(得分:1)

要使用最新的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”。

答案 2 :(得分:1)

我遇到了同样的问题,似乎我们使用了错误的方法。 有用于TF转换模型的loadGraphModel和用于Keras的loadLayersModel my comment about the issue

答案 3 :(得分:1)

也许有人可以使用我的方式修改keep.py以支持mobileV2。 原始的retrain.py link。此链接是Google的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的最新版本仍然不受支持。

我只是制作了一个视频here,解释了为什么我们无法将Tensorflow冻结模型转换为Tensorflow JS模型,并介绍了如何找到输入Tensor和输出Tensor。最后,运行步骤和结果给出了不受支持的Ops ScalarSummary 及其原因。

现在我无法将Mobilenet模型更改为Tensorflow JS模型,因此我的解决方法是在服务器端使用Python tensorflow和flask库,用户将图像上传到服务器,然后返回结果。