gpt4 book ai didi

python - 在 cloudml 上使用部署的模型时,在 base64 中发现无效字符

转载 作者:行者123 更新时间:2023-12-01 01:52:15 26 4
gpt4 key购买 nike

为了获得更好的上下文,我在 cloud ml 上上传了一个预训练模型。这是一个从 keras 转换为 tensorflow 中可接受的格式的 inceptionV3 模型。

from keras.applications.inception_v3 import InceptionV3
model = InceptionV3(weights='imagenet')
from keras.models import Model
intermediate_layer_model = Model(inputs=model.input,outputs=model.layers[311].output)
with tf.Graph().as_default() as g_input:
input_b64 = tf.placeholder(shape=(1,),
dtype=tf.string,
name='input')
input_bytes = tf.decode_base64(input_b64[0])
image = tf.image.decode_image(input_bytes)
image_f = tf.image.convert_image_dtype(image, dtype=tf.float32)
input_image = tf.expand_dims(image_f, 0)
output = tf.identity(input_image, name='input_image')
g_input_def = g_input.as_graph_def()
K.set_learning_phase(0)
sess = K.get_session()
from tensorflow.python.framework import graph_util
g_trans = sess.graph
g_trans_def = graph_util.convert_variables_to_constants(sess,
g_trans.as_graph_def(),
[intermediate_layer_model.output.name.replace(':0','')])
with tf.Graph().as_default() as g_combined:
x = tf.placeholder(tf.string, name="input_b64")

im, = tf.import_graph_def(g_input_def,
input_map={'input:0': x},
return_elements=["input_image:0"])

pred, = tf.import_graph_def(g_trans_def,
input_map={intermediate_layer_model.input.name: im,
'batch_normalization_1/keras_learning_phase:0': False},
return_elements=[intermediate_layer_model.output.name])

with tf.Session() as sess2:
inputs = {"inputs": tf.saved_model.utils.build_tensor_info(x)}
outputs = {"outputs":tf.saved_model.utils.build_tensor_info(pred)}
signature =tf.saved_model.signature_def_utils.build_signature_def(
inputs=inputs,
outputs=outputs,
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME
)

# save as SavedModel
b = tf.saved_model.builder.SavedModelBuilder('inceptionv4/')
b.add_meta_graph_and_variables(sess2,
[tf.saved_model.tag_constants.SERVING],
signature_def_map={'serving_default': signature})
b.save()

生成的pb文件在我本地使用时工作正常。但是当我将其部署在 cloud ml 上时,出现以下错误。

RuntimeError: Prediction failed: Error during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details="Invalid character found in base64.
[[Node: import/DecodeBase64 = DecodeBase64[_output_shapes=[<unknown>], _device="/job:localhost/replica:0/task:0/device:CPU:0"](import/strided_slice)]]")

以下是我用于获取本地预测的代码。

import base64
import json

with open('MEL_BE_0.jpg', 'rb') as image_file:
encoded_string = str(base64.urlsafe_b64encode(image_file.read()),'ascii')

import tensorflow as tf

with tf.Session(graph=tf.Graph()) as sess:
MetaGraphDef=tf.saved_model.loader.load(
sess,
[tf.saved_model.tag_constants.SERVING],
'inceptionv4')
input_tensor = tf.get_default_graph().get_tensor_by_name('input_b64:0')
print(input_tensor)
avg_tensor = tf.get_default_graph().get_tensor_by_name('import_1/avg_pool/Mean:0')
print(avg_tensor)
predictions = sess.run(avg_tensor, {input_tensor: [encoded_string]})

最后,下面是我用来将编码字符串包装在发送到 cloud-ml 引擎的请求中的代码片段。

request_body= json.dumps({"key":"0", "image_bytes": {"b64": [encoded_string]}})

最佳答案

看起来您正在尝试在 TensorFlow 中进行 Base64 解码并且使用 {"b64": ...} JSON 格式。你需要做其中之一;我们通常推荐后者。

顺便说明一下,您的输入占位符的外部尺寸必须为 None 。这可能会让一些事情变得棘手,例如,您要么必须将维度重新调整为大小 1(这将阻止您在当前状态下使用批量预测服务),要么您必须使用 tf.map_fn将相同的一组转换应用于输入“批处理”的每个元素。您可以在 this example 中找到该技术的示例。 。

最后,我推荐使用tf.saved_model.simple_save .

总而言之,这是一些修改后的代码。请注意,我正在内联您的输入函数(而不是将其序列化为图形定义并重新导入):

HEIGHT = 299
WIDTH = 299

# Get Keras Model
from keras.applications.inception_v3 import InceptionV3
model = InceptionV3(weights='imagenet')
from keras.models import Model
intermediate_layer_model = Model(inputs=model.input,outputs=model.layers[311].output)
K.set_learning_phase(0)
sess = K.get_session()
from tensorflow.python.framework import graph_util
g_trans = sess.graph
g_trans_def = graph_util.convert_variables_to_constants(sess,
g_trans.as_graph_def(),
[intermediate_layer_model.output.name.replace(':0','')])

# Create inputs to model and export
with tf.Graph().as_default() as g_combined:

def decode_and_resize(image_bytes):
image = tf.image.decode_image(image_bytes)
# Note resize expects a batch_size, but tf_map supresses that index,
# thus we have to expand then squeeze. Resize returns float32 in the
# range [0, uint8_max]
image = tf.expand_dims(image, 0)
image = tf.image.resize_bilinear(
image, [HEIGHT, WIDTH], align_corners=False)
image = tf.squeeze(image, squeeze_dims=[0])
image = tf.cast(image, dtype=tf.uint8)
return image

input_byes = tf.placeholder(shape=(None,),
dtype=tf.string,
name='input')

images = tf.map_fn(
decode_and_resize, input_bytes, back_prop=False, dtype=tf.uint8)
images = tf.image.convert_image_dtype(images, dtype=tf.float32)

pred, = tf.import_graph_def(g_trans_def,
input_map={intermediate_layer_model.input.name: images,
'batch_normalization_1/keras_learning_phase:0': False},
return_elements=[intermediate_layer_model.output.name])

with tf.Session() as sess2:
tf.saved_model.simple_save(
sess2,
model_dir='inceptionv4/'
inputs={"inputs": input_bytes},
outputs={"outputs": pred})

注意:我不能 100% 确定 intermediate_layer_model 的形状和images是兼容的。形状images将是[无,高度,宽度,num_channels]。

另请注意,您的本地预测代码将会发生一些变化。您不对图像进行 Base64 编码,并且需要发送“批量”/图像列表而不是单个图像。像这样的东西:

with open('MEL_BE_0.jpg', 'rb') as image_file:
encoded_string = image_file.read()

input_tensor = tf.get_default_graph().get_tensor_by_name('input:0')
print(input_tensor)
avg_tensor = tf.get_default_graph().get_tensor_by_name('import_1/avg_pool/Mean:0')
print(avg_tensor)
predictions = sess.run(avg_tensor, {input_tensor: [encoded_string]})

您没有指定您是进行批量预测还是在线预测,它们的输入“格式”相似但略有不同。无论哪种情况,您的模型都不会导出“关键”字段(您是故意的吗?这可能对批量预测有帮助,但对在线预测没有帮助)。

对于批量预测,文件格式为JSON行;每一行包含一个示例。每行都可以像这样从 Python 生成:

example = json.dumps({"image_bytes": {"b64": ENCODED_STRING}})

(请注意现在省略“key”)。由于您只有一个输入,因此有一种简写:

example = json.dumps({"b64": ENCODED_STRING})

如果你想进行在线预测,你会注意到如果你使用gcloud要发送请求,您实际上使用与批量预测相同的文件格式。

事实上,我们强烈建议使用 gcloud ml-engine local predict --json-instances=FILE --model-dir=...在部署到云端之前帮助调试。

如果您打算使用 gcloud 之外的其他客户端,例如在网络应用程序、移动应用程序、前端服务器等中,那么您将不会发送文件,并且需要自己构建完整的请求。它与上面的文件格式非常相似。基本上,将 JSON 行文件的每一行放入一个名为“instances”的数组中,即,

request_body= json.dumps({"instances": [{"image_bytes": {"b64": [encoded_string]}}]})

如果愿意,您可以使用相同的语法糖:

request_body= json.dumps({"instances": [{"b64": [encoded_string]}]})

希望这会有所帮助!

关于python - 在 cloudml 上使用部署的模型时,在 base64 中发现无效字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50597376/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com