我如何修改导出keras模型以接受b64字符串到RESTful API/Google Cloud ML的方式 [英] How do I need to modify exporting a keras model to accept b64 string to RESTful API/Google cloud ML

查看:75
本文介绍了我如何修改导出keras模型以接受b64字符串到RESTful API/Google Cloud ML的方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用于导出模型的完整代码:(我已经对其进行了训练,现在可以从权重文件中进行加载)

The complete code for exporting the model: (I've already trained it and now loading from weights file)

def cnn_layers(inputs):
  conv_base= keras.applications.mobilenetv2.MobileNetV2(input_shape=(224,224,3), input_tensor=inputs, include_top=False, weights='imagenet')
  for layer in conv_base.layers[:-200]:
    layer.trainable = False
  last_layer = conv_base.output
  x = GlobalAveragePooling2D()(last_layer)
  x= keras.layers.GaussianNoise(0.3)(x)
  x = Dense(1024,name='fc-1')(x)
  x = keras.layers.BatchNormalization()(x)
  x = keras.layers.advanced_activations.LeakyReLU(0.3)(x)
  x = Dropout(0.4)(x)
  x = Dense(512,name='fc-2')(x)
  x = keras.layers.BatchNormalization()(x)
  x = keras.layers.advanced_activations.LeakyReLU(0.3)(x)
  x = Dropout(0.3)(x)
  out = Dense(10, activation='softmax',name='output_layer')(x)
  return out

model_input = layers.Input(shape=(224,224,3))

model_output = cnn_layers(model_input)

test_model = keras.models.Model(inputs=model_input, outputs=model_output)

weight_path = os.path.join(tempfile.gettempdir(), 'saved_wt.h5')

test_model.load_weights(weight_path)

export_path='export'
from tensorflow.python.saved_model import builder as saved_model_builder
from tensorflow.python.saved_model import utils
from tensorflow.python.saved_model import tag_constants, signature_constants
from tensorflow.python.saved_model.signature_def_utils_impl import build_signature_def, predict_signature_def
from tensorflow.contrib.session_bundle import exporter

builder = saved_model_builder.SavedModelBuilder(export_path)

signature = predict_signature_def(inputs={'image': test_model.input},
                                  outputs={'prediction': test_model.output})

with K.get_session() as sess:
    builder.add_meta_graph_and_variables(sess=sess,
                                         tags=[tag_constants.SERVING],
                                         signature_def_map={'predict': signature})
    builder.save()

并且 的输出(dir 1具有saved_model.pbmodels dir):
python /tensorflow/python/tools/saved_model_cli.py show --dir /1 --all 是

And the output of  (dir 1 has saved_model.pb and models dir) :
python /tensorflow/python/tools/saved_model_cli.py show --dir /1 --all   is

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

signature_def['predict']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['image'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 224, 224, 3)
        name: input_1:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['prediction'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 107)
        name: output_layer/Softmax:0
  Method name is: tensorflow/serving/predict

接受b64字符串: 该代码是为(224, 224, 3) numpy数组编写的.因此,我对以上代码进行的修改是:

To accept b64 string: The code was written for (224, 224, 3) numpy array. So, the modifications I made for the above code are:

    作为b64传递时,应将
  • _bytes添加到输入中.因此,
  • _bytes should be added to input when passing as b64. So,

predict_signature_def(inputs={'image':......
          已更改为
predict_signature_def(inputs={'image_bytes':.....

predict_signature_def(inputs={'image':......
          changed to
predict_signature_def(inputs={'image_bytes':.....

  • 以前,type(test_model.input)是:(224, 224, 3)dtype: DT_FLOAT.所以,
  • Earlier, type(test_model.input) is : (224, 224, 3) and dtype: DT_FLOAT. So,

signature = predict_signature_def(inputs={'image': test_model.input},.....          更改为(参考)
temp = tf.placeholder(shape=[None], dtype=tf.string)
signature = predict_signature_def(inputs={'image_bytes': temp},.....

signature = predict_signature_def(inputs={'image': test_model.input},.....           changed to (reference)
temp = tf.placeholder(shape=[None], dtype=tf.string)
signature = predict_signature_def(inputs={'image_bytes': temp},.....

修改:
使用请求发送的代码为:(如评论中所述)

encoded_image = None
with open('/1.jpg', "rb") as image_file:
    encoded_image = base64.b64encode(image_file.read())
object_for_api = {"signature_name": "predict",
                  "instances": [
                      {
                           "image_bytes":{"b64":encoded_image}
                           #"b64":encoded_image (or this way since "image" is not needed)
                      }]
                  }

p=requests.post(url='http://localhost:8501/v1/models/mnist:predict', json=json.dumps(object_for_api),headers=headers)
print(p)

我遇到<Response [400]>错误.我认为我的发送方式没有错误.需要在代码中更改某些内容以导出模型,尤其是在
temp = tf.placeholder(shape=[None], dtype=tf.string).

I'm getting <Response [400]> error. I think there's no error in the way I'm sending. Something needs to be changed in the code for exporting the model and specifically in
temp = tf.placeholder(shape=[None], dtype=tf.string).

推荐答案

两个注意事项:

  1. 我建议您使用 tf.saved_model.simple_save
  2. 您可能会发现 model_to_estimator 很方便. /li>
  3. 虽然您的模型似乎可以满足请求的要求(saved_model_cli的输出显示输入和输出的外部尺寸均为None),但发送浮​​点数的JSON数组效率相当低
  1. I encourage you to use tf.saved_model.simple_save
  2. You may find model_to_estimator convenient.
  3. While your model seems like it will work for requests (the output of saved_model_cli shows the outer dimension is None for both inputs and outputs), it's fairly inefficient to send JSON arrays of floats

最后一点,修改代码以进行图像解码服务器端通常更容易,因此您将通过有线而不是浮点数数组发送以base64编码的JPG或PNG.这是Keras的一个示例(我打算用更简单的代码来更新该答案).

To the last point, it's often easier to modify the code to do the image decoding server side so you're sending a base64 encoded JPG or PNG over the wire instead of an array of floats. Here's one example for Keras (I plan to update that answer with simpler code).

这篇关于我如何修改导出keras模型以接受b64字符串到RESTful API/Google Cloud ML的方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆