Когда апплет WeChat встречает TensorFlow: получение данных изображения в кодировке base64

искусственный интеллект TensorFlow сервер Апплет WeChat

ЭтоКогда апплет WeChat встречается с TensorFlowЧетвертая статья цикла, прочитав эту статью, вы узнаете:

  1. Как просмотреть подпись тензорного потока SavedModel
  2. Как загрузить тензорный поток SavedModel
  3. Как изменить существующую модель TensorFlow, чтобы добавить входной слой

Если вы хотите узнать больше об этом проекте, вы можете обратиться к первым трем статьям этой серии:

  1. Когда апплет WeChat встречается с TensorFlow: реализация на стороне сервера
  2. Когда мини-программы WeChat встречаются с TensorFlow: дополнения к реализации на стороне сервера
  3. Когда апплет WeChat встречается с TensorFlow: реализация апплета

Для обработки модели формата Tensorflow SavedModel вы можете обратиться к предыдущей статье:

  1. Сохранение и загрузка моделей Tensorflow SavedModel
  2. Как просмотреть информацию о модели в формате tensorflow SavedModel
  3. Как объединить две модели TensorFlow

проблема

На данный момент мы внедрили простой апплет WeChat и развернули сервер с помощью Simple TensorFlow Serving с открытым исходным кодом. Однако в этой схеме реализации по-прежнему существует серьезная проблема: данные изображения, передаваемые между апплетом и сервером, представляют собой JSON-представление двоичного массива (299, 299, 3).Самый большой недостаток этой JSONизации двоичных данных заключается в том, что объем данных слишком велик , простое изображение размером 299 x 299, что соответствует от 3 до 4 МБ. Фактически, общая схема передачи двоичных данных по протоколу HTTP заключается в кодировании двоичных данных в формате base64.После кодирования в формате base64, хотя объем данных больше, чем в двоичном формате, он все же намного меньше, чем представление JSON.

Итак, теперь вопрос в том, как заставить сервер получать данные изображения в кодировке base64?

Посмотреть подпись модели

Чтобы решить эту проблему, давайте сначала посмотрим на вход и выход модели, чтобы увидеть, как выглядит ее подпись? Подпись здесь не является электронной подписью, чтобы гарантировать, что модель не будет изменена. Мое понимание похоже на ввод и вывод информации модулей в языках программирования, таких как имена функций, типы входных параметров, типы выходных параметров и так далее. С помощью инструмента save_model_cli.py, предоставленного Tensorflow, мы можем четко просмотреть сигнатуру модели:

python ./tensorflow/python/tools/saved_model_cli.py show --dir /data/ai/workspace/aiexamples/AIDog/serving/models/inception_v3/ --all

MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['image'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 299, 299, 3)
        name: Placeholder:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['prediction'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 120)
        name: final_result:0
  Method name is: tensorflow/serving/predict

Из этого мы видим, что входной параметр модели называется изображением, а его форма (-1, 299, 299, 3), где -1 означает, что его можно вводить партиями, обычно мы вводим только одно изображение, поэтому это измерение обычно равно 1. Выходной параметр называется прогнозом, и его форма (-1, 120), -1 соответствует входу, а 120 представляет вероятность 120 групп категорий собак.

Вопрос теперь в том, можем ли мы добавить слой перед вводом модели для base64 и декодирования?

Возможно, вы думаете, что можете написать кусок кода на стороне сервера, декодировать строку base64, а затем передать ее в Simple Tensorflow Serving для обработки или изменить логику обработки Simple TensorFlow Serving, но такая схема модификации увеличивает нагрузку на сервер. серверная сторона, создание сервера Схема развертывания больше не универсальна, бросьте ее!

Измените модель и добавьте входной слой

Собственно, в предыдущей статье "Как объединить две модели TensorFlow", мы уже говорили о том, как соединить две модели, вот небольшой повтор, первый - написать модель для декодирования base64, декодирования png и масштабирования изображения:

  base64_str = tf.placeholder(tf.string, name='input_string')
  input_str = tf.decode_base64(base64_str)
  decoded_image = tf.image.decode_png(input_str, channels=input_depth)
  # Convert from full range of uint8 to range [0,1] of float32.
  decoded_image_as_float = tf.image.convert_image_dtype(decoded_image,
                                                        tf.float32)
  decoded_image_4d = tf.expand_dims(decoded_image_as_float, 0)
  resize_shape = tf.stack([input_height, input_width])
  resize_shape_as_int = tf.cast(resize_shape, dtype=tf.int32)
  resized_image = tf.image.resize_bilinear(decoded_image_4d,
                                           resize_shape_as_int)
  tf.identity(resized_image, name="DecodePNGOutput")

Затем загрузите модель переобучения:

  with tf.Graph().as_default() as g2:
    with tf.Session(graph=g2) as sess:
      input_graph_def = saved_model_utils.get_meta_graph_def(
          FLAGS.origin_model_dir, tag_constants.SERVING).graph_def

      tf.saved_model.loader.load(sess, [tag_constants.SERVING], FLAGS.origin_model_dir)

      g2def = graph_util.convert_variables_to_constants(
          sess,
          input_graph_def,
          ["final_result"],
          variable_names_whitelist=None,
          variable_names_blacklist=None)

Здесь вызывается graph_util.convert_variables_to_constants для преобразования переменных в модели в константы, что является так называемой операцией замораживания графа.

Используя метод tf.import_graph_def, мы можем импортировать граф в существующий граф.Обратите внимание на второй import_graph_def, вход которого является выходом первого graph_def.Благодаря этой операции два вычислительных графа соединяются и, наконец, сохраняются. код показывает, как показано ниже:

  with tf.Graph().as_default() as g_combined:
    with tf.Session(graph=g_combined) as sess:
      x = tf.placeholder(tf.string, name="base64_string")
      y, = tf.import_graph_def(g1def, input_map={"input_string:0": x}, return_elements=["DecodePNGOutput:0"])
      z, = tf.import_graph_def(g2def, input_map={"Placeholder:0": y}, return_elements=["final_result:0"])

      tf.identity(z, "myOutput")

      tf.saved_model.simple_save(sess,
                                 FLAGS.model_dir,
                                 inputs={"image": x},
                                 outputs={"prediction": z})

Если вы не знаете, что такое входной узел повторно обученной модели (обратите внимание, что вы не можете использовать информацию о подписи развертывания модели)? Имена узлов графа можно просмотреть с помощью следующего кода:

for n in g2def.node:
  print(n.name)

Развертывание и тестирование модели

Обратите внимание, что мы можем сохранить подключенную модель в каталоге ./models/inception_v3/2/, а исходный ./models/inception_v3/1/ удалять не нужно, чтобы две версии модели могли предоставлять услуги одновременно. то же время, что удобно от V1. Модель плавно переходит к модели версии V2.

Давайте изменим исходный код test_client.py и добавим параметр model_version, чтобы мы могли решить, с какой версией модели взаимодействовать:

  with open(file_name, "rb") as image_file:
    encoded_string = str(base64.urlsafe_b64encode(image_file.read()), "utf-8")

  if enable_ssl :
    endpoint = "https://127.0.0.1:8500"
  else:
    endpoint = "http://127.0.0.1:8500"

  json_data = {"model_name": model_name,
               "model_version": model_version,
               "data": {"image": encoded_string}
              }
  result = requests.post(endpoint, json=json_data)

резюме

После более чем недели исследований и неоднократных попыток я, наконец, решил проблему передачи данных изображения в кодировке base64. Сложность в том, что хотя модель и переобучается путем написания скрипта переобучения, этот код не так прост для понимания, и попытка добавить входной слой при переобучении также не дает результата. Наконец, я получил вдохновение от замораживания графа, когда модель Tensorflow была перенесена в модель Tensorflow Lite, и преобразовал переменные в графе в константы, что решило проблему загрузки переменных модели слиянием. Хотя некоторые методы восстановления переменных представлены в Интернете, на практике они не работают, возможно, Tensorflow развивается слишком быстро, а некоторые из предыдущих методов устарели.

Полный код этой статьи можно найти по адресу:GitHub.com/mogo Web/голодание…

нажмитечитать оригиналВы можете перейти непосредственно к проекту на github.

На данный момент основные проблемы решены.Дальше нам нужно продолжать улучшать отображение апплета WeChat и обеспечивать скорость распознавания.Пожалуйста, обратите внимание на мой публичный аккаунт WeChat: Yunshuimushi для получения последних новостей.

image

Ссылаться на

  1. How to Show Signatures of Tensorflow Saved Model
  2. Обслуживание моделей глубокого обучения на основе изображений с помощью RESTful API TensorFlow-Serving
  3. Tensorflow: How to replace a node in a calculation graph?