Обнаружение изображения с помощью MobileNet
Несколько способов переобучения MobileNet для использования с Tensorflow.js потерпели неудачу для меня. Есть ли способ использовать переобученную модель с Tensorflow.js?
Как с использованием современного, основанного на хабе учебника, так и с использованием retrain.py
Кажется, не удалось.
- Преобразовать вывод retrain.py в tenorflow.js
- Ошибка преобразования модели keras в tfjs: дублированное имя веса Переменная
а также некоторые другие открытые вопросы
- Восстановить классификатор изображений в tenorflow js
- Загрузка mobilenet v2 работает, но предварительно обученная mobilenet v2 не работает
- Не удается преобразовать сохраненную модель TensorFlow в веб-модель tfjs_layers_model
Два верхних вопроса показывают код, который не удалось в обоих случаях, оба не решены.
Цель состоит в том, чтобы загрузить мобильную сеть, переобучаться с использованием пользовательских данных и использовать их в Tensorflow.js. Следование обоим учебным пособиям кажется неудачным. Может ли это быть сделано внутри node.js? Есть ли другой способ? Где я допустил ошибки (или программное обеспечение не может использовать переобученные модели)? Как это может работать?
РЕДАКТИРОВАТЬ: последний выпуск GitHub и еще один вопрос
2 ответа
Я столкнулся с той же проблемой, и кажется, что мы использовали неправильный метод. Есть loadGraphModel для моделей, преобразованных в TF, и loadLayersModel для Keras - мой комментарий по проблеме.
retrain.py
Скрипт python не генерирует сохраненную модель, он фактически генерирует замороженную модель графа. Вот почему вы не можете конвертировать его с помощью конвертера tfjs 1.x. Вам необходимо использовать tfjs 0.8.5 pip для конвертации. Кроме того, имя выходного узла отличается от графа модели мобильной сети, это "final_result" для переобученного графа.
Чтобы конвертировать его, вам нужно использовать tenorflowjs 0.8.5 pip:
- использовать virtualenv для создания пустого окружения.
- pip install tenorflowjs==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
Чтобы использовать последние 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-формат.
Тем не менее, загрузка модели с tf.loadLayersModel("file:///tmp/web_model/model.json")
не удалось с
'className' и 'config' должны быть установлены.
Может быть, кто-нибудь может изменить keep.py для поддержки использования mobileV2 по-моему. Оригинальная ссылка retrain.py. Эта ссылка является кодом 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)
Используя свой diff, я могу создать модель, обслуживаемую Tensorflow. Затем я использую команду для преобразования модели, обслуживаемой TensorFlow, в модель Tfjs.
tensorflowjs_converter \
--input_format=tf_saved_model \
--output_format=tfjs_graph_model \
./tf_files/savemode \
./tf_files/js_model
По-прежнему не поддерживается Ops для последней версии Tensorflow JS.
Я просто делаю видео здесь, чтобы объяснить, почему мы не можем преобразовать замороженную модель Tensorflow в модель Tensorflow JS, рассказывает, как найти входной тензор и выходной тензор. Шаги и результат выполнения, наконец, дают неподдерживаемое Ops ScalarSummary и причину.
Теперь, когда я не могу изменить модель Mobilenet на модель Tensorflow JS, я использую тензорный поток Python и библиотеку флаконов на стороне сервера, пользователь загружает изображение на сервер и затем возвращает результат.