Развертывание модели TensorFlow в Google Cloud, которая получает строку в кодировке base64 в качестве входных данных модели - PullRequest
2 голосов
/ 12 июня 2019

Я успешно настроил Google Cloud и развернул предварительно обученную модель ML, которая принимает входной тензор (изображение) shape=(?, 224, 224, 3) и dtype=float32.Это работает хорошо, но это неэффективно при выполнении запросов REST и должно действительно использовать строку в кодировке base64.Задача состоит в том, что я использую трансферное обучение и не могу контролировать ввод исходной предварительно обученной модели.Чтобы обойти это с добавлением дополнительной инфраструктуры, я создал небольшой граф (обертку), который обрабатывает преобразование base64 в массив, и соединил его с моим предварительно обученным графом модели, получив новый единственный граф.Маленький граф принимает входной тензор с shape=(), dtype=string и возвращает тензор с shape=(224, 224, 3), dtype=float32, который затем может быть передан исходной модели.Модель компилируется в .pb файл без ошибок и успешно развертывается, но я получаю следующую ошибку при выполнении моего почтового запроса:

{'error': 'Prediction failed: Error during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details="Index out of range using input dim 0; input has only 0 dims\n\t [[{{node lambda/map/while/strided_slice}}]]")'}

Тело почтового запроса:

{'instances': [{'b64': 'iVBORw0KGgoAAAANSUhEUgAAAOAA...'}]}`

Эта ошибка заставляет меня полагать, что почтовый запрос неправильно отформатирован для обработки строки base64 или неправильно настроен ввод моего базового графика конверсии.Я могу запустить код локально, вызвав предикат в моей комбинированной модели, и передать ему тензор в форме shape=(), dtype=string, построенного локально, и успешно получить результат.

Вот мой код для объединения двух графиков:

import tensorflow as tf

# Local dependencies
from myProject.classifier_models import mobilenet
from myProject.dataset_loader import dataset_loader
from myProject.utils import f1_m, recall_m, precision_m

with tf.keras.backend.get_session() as sess:    

    def preprocess_and_decode(img_str, new_shape=[224,224]):
        #img = tf.io.decode_base64(img_str)
        img = tf.image.decode_png(img_str, channels=3)
        img = (tf.cast(img, tf.float32)/127.5) - 1
        img = tf.image.resize_images(img, new_shape, method=tf.image.ResizeMethod.AREA, align_corners=False)
        # If you need to squeeze your input range to [0,1] or [-1,1] do it here
        return img

    InputLayer = tf.keras.layers.Input(shape = (1,),dtype="string")
    OutputLayer = tf.keras.layers.Lambda(lambda img : tf.map_fn(lambda im : preprocess_and_decode(im[0]), img, dtype="float32"))(InputLayer)
    base64_model = tf.keras.Model(InputLayer,OutputLayer)

    tf.keras.backend.set_learning_phase(0)  # Ignore dropout at inference
    transfer_model = tf.keras.models.load_model('./trained_model/mobilenet_93.h5', custom_objects={'f1_m': f1_m, 'recall_m': recall_m, 'precision_m': precision_m})
    sess.run(tf.global_variables_initializer())

    base64_input = base64_model.input
    final_output = transfer_model(base64_model.output)
    new_model = tf.keras.Model(base64_input,final_output)

    export_path = '../myModels/001'

    tf.saved_model.simple_save(
        sess,
        export_path,
        inputs={'input_class': new_model.input},
        outputs={'output_class': new_model.output})

Технология: TensorFlow 1.13.1 & Python 3.5

Я просмотрел несколько похожих сообщений, таких как:

https://stackoverflow.com/a/50606625

https://stackoverflow.com/a/42859733

http://www.voidcn.com/article/p-okpgbnul-bvs.html (щелкните правой кнопкой мыши перевод на английский)

https://cloud.google.com/ml-engine/docs/tensorflow/online-predict

Любые предложения или отзывы будут с благодарностью!

Обновление 12/12/2019:

Проверка 3 графических сводок все выглядит правильно слитыми

enter image description here

Обновление 14/14/2019:

Закончено использование этой альтернативной стратегии вместо реализации tf.estimator

...