Как реализовать функцию входного обслуживания TensorFlow для изображений в виде строк в кодировке base64 и получить прогноз на Cloud ML Engine
Я планирую развернуть модель на движке Cloud Machine Learning (ML) после предварительного обучения, но не знаю, как реализовать функцию обслуживания ввода .
Кроме того, я старался избегать низкоуровневых API TensorFlow и сосредоточился только на высокоуровневых API TensorFlow ( TensorFlow Estimator ). Ниже здесь в блоках кода приведен пример кода, над которым я работаю.
import numpy as np
import tensorflow as tf
import datetime
import os
# create model
from tensorflow.python.keras.applications.vgg16 import VGG16
from tensorflow.python.keras import models
from tensorflow.python.keras import layers
conv_base = VGG16(weights='imagenet',
include_top=False,
input_shape=(150, 150, 3))
model = models.Sequential()
model.add(conv_base)
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
conv_base.trainable = False
model.compile(loss='binary_crossentropy',
optimizer=tf.keras.optimizers.RMSprop(lr=2e-5),
metrics=['acc'])
dt = datetime.datetime.now()
datetime_now = dt.strftime("%y%m%d_%H%M%S")
model_dir = 'models/imageclassifier_'+datetime_now
model_dir = os.path.join(os.getcwd(), model_dir)
if not os.path.exists(model_dir):
os.makedirs(model_dir)
print ("model_dir: ",model_dir)
est_imageclassifier = tf.keras.estimator.model_to_estimator(keras_model=model, model_dir=model_dir)
# input layer name
input_name = model.input_names[0]
input_name
Этот раздел предназначен для функции ввода изображения.
def imgs_input_fn(filenames, labels=None, perform_shuffle=False, repeat_count=1, batch_size=1):
def _parse_function(filename, label):
image_string = tf.read_file(filename)
image = tf.image.decode_image(image_string, channels=3)
image.set_shape([None, None, None])
image = tf.image.resize_images(image, [150, 150])
image = tf.subtract(image, 116.779) # Zero-center by mean pixel
image.set_shape([150, 150, 3])
image = tf.reverse(image, axis=[2]) # 'RGB'->'BGR'
d = dict(zip([input_name], [image])), label
return d
if labels is None:
labels = [0]*len(filenames)
labels=np.array(labels)
# Expand the shape of "labels" if necessary
if len(labels.shape) == 1:
labels = np.expand_dims(labels, axis=1)
filenames = tf.constant(filenames)
labels = tf.constant(labels)
labels = tf.cast(labels, tf.float32)
dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.map(_parse_function)
if perform_shuffle:
# Randomizes input using a window of 256 elements (read into memory)
dataset = dataset.shuffle(buffer_size=256)
dataset = dataset.repeat(repeat_count) # Repeats dataset this # times
dataset = dataset.batch(batch_size) # Batch size to use
iterator = dataset.make_one_shot_iterator()
batch_features, batch_labels = iterator.get_next()
return batch_features, batch_labels
Я хотел бы создать функцию ввода обслуживания , что
Получение изображений в виде строк в кодировке base64 в формате JSON
Преобразуйте их в тензоры и уменьшите размер до (?, 150, 150, 3) для прогноза
Как показано ниже,
def serving_input_receiver_fn():
''' CODE HERE!'''
return tf.estimator.export.ServingInputReceiver(feature_placeholders, feature_placeholders)
Чтобы обучить и оценить модель,
train_spec = tf.estimator.TrainSpec(input_fn=lambda: imgs_input_fn(train_files,
labels=train_labels,
perform_shuffle=True,
repeat_count=1,
batch_size=20),
max_steps=500)
exporter = tf.estimator.LatestExporter('Servo', serving_input_receiver_fn)
eval_spec = tf.estimator.EvalSpec(input_fn=lambda: imgs_input_fn(val_files,
labels=val_labels,
perform_shuffle=False,
batch_size=1),
exporters=exporter)
tf.estimator.train_and_evaluate(est_imageclassifier, train_spec, eval_spec)
Если я правильно понимаю, пример входного файла для получения прогноза на Cloud ML Engine должен выглядеть примерно так:
request.json
{"b64": "9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHJC...”}
{"b64": "9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHJC...”}
И
gcloud ml-engine predict --model MODEL_NAME \
--version MODEL_VERSION \
--json-instances request.json
Если вы читаете до здесь и у вас есть идея, не могли бы вы подсказать, как реализовать функцию входного ввода для этого конкретного случая.
Заранее большое спасибо,
2nd Post - Чтобы обновить то, что я сделал до сих пор.
Согласно комментарию sdcbr, ниже приведен мой serve_input_receiver_fn ().
Для функции _img_string_to_tensor () или (функции prepare_image), я предполагаю, что Я должен выполнить подготовку изображения так же, как я обучил модель , которую вы можете увидеть
imgs_input_fn () => _parse_function ().
def serving_input_receiver_fn():
def _img_string_to_tensor(image_string):
image = tf.image.decode_image(image_string, channels=3)
image.set_shape([None, None, None])
image = tf.image.resize_images(image, [150, 150])
image = tf.subtract(image, 116.779) # Zero-center by mean pixel
image.set_shape([150, 150, 3])
image = tf.reverse(image, axis=[2]) # 'RGB'->'BGR'
return image
input_ph = tf.placeholder(tf.string, shape=[None])
images_tensor = tf.map_fn(_img_string_to_tensor, input_ph, back_prop=False, dtype=tf.float32)
return tf.estimator.export.ServingInputReceiver({model.input_names[0]: images_tensor}, {'image_bytes': input_ph})
После того, как я обучил модель и развернул сохраненную модель на Cloud ML Engine. Мое входное изображение было подготовлено в формате, показанном ниже.
{"image_bytes": {"b64": "YQ=="}}
Но я обнаружил ошибку после получения прогноза через gcloud.
gcloud ml-engine predict --model model_1 \
--version v1 \
--json-instances request.json
{"error": "Ошибка прогноза: ошибка во время выполнения модели:
Ошибка AbortionError (code = StatusCode.INVALID_ARGUMENT, details = \ "утверждение
не удалось: [невозможно декодировать байты в формате JPEG, PNG, GIF или BMP] \ n \ t
[[{{узел
map / while / decode_image / cond_jpeg / cond_png / cond_gif / Assert_1 / Assert}} =
Утвердите [T = [DT_STRING], суммируйте = 3,
_device = \ "/ работа: локальный / реплика: 0 / задача: 0 / устройства: CPU: 0 \"] (отображение /, а / decode_image / cond_jpeg / cond_png / cond_gif / is_bmp,
карта / во время / decode_image / cond_jpeg / cond_png / cond_gif / Assert_1 / Утверждай / data_0)]] \ ")"
}
Я что-то не так сделал в функции _img_string_to_tensor?
и не могли бы вы разъяснить мне больше об этом tf.placeholder?
input_ph = tf.placeholder(tf.string, shape=[None])
В приведенном выше коде вы используете shape = [1], но я думаю, что оно должно быть shape = [None].