首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修改导出keras模型以接受b64字符串到RESTful API/Google

如何修改导出keras模型以接受b64字符串到RESTful API/Google
EN

Stack Overflow用户
提问于 2018-07-05 08:55:37
回答 2查看 999关注 0票数 1

导出模型的完整代码:(我已经训练过它,现在从权重文件加载)

代码语言:javascript
复制
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 1saved_model.pbmodels dir):

python /tensorflow/python/tools/saved_model_cli.py show --dir /1 --all

代码语言:javascript
复制
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

接受字符串:代码是为(224, 224, 3) numpy数组编写的。因此,我对上述代码所做的修改如下:

  • 在作为_bytes传递时,应该将_bytes添加到输入中。所以,

predict_signature_def(inputs={'image':......

变到

predict_signature_def(inputs={'image_bytes':.....

  • 早些时候,type(test_model.input)是:(224, 224, 3)dtype: DT_FLOAT。所以,

signature = predict_signature_def(inputs={'image': test_model.input},.....改为(reference)

temp = tf.placeholder(shape=[None], dtype=tf.string)

signature = predict_signature_def(inputs={'image_bytes': temp},.....

编辑:

使用请求发送的代码是:(如注释中提到的)

代码语言:javascript
复制
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)

EN

回答 2

Stack Overflow用户

发布于 2018-07-05 10:10:05

查看您提供的文档,您想要做的是获取图像并将其发送到API中。如果您对图像进行编码,则可以轻松地以文本格式传输图像,base64基本上是标准的。因此,我们要做的是创建一个json对象,在正确的位置将图像作为base64,然后将这个json对象发送到REST。python有一个请求库,这使得将python字典作为JSON发送非常容易。

因此,获取图像,对其进行编码,将其放入字典并使用请求将其发送出去:

代码语言:javascript
复制
import requests
import base64

encoded_image = None
with open("image.png", "rb") as image_file:
    encoded_image = base64.b64encode(image_file.read())

object_for_api = {"signature_name": "predict",
                  "instances": [
                      {
                          "image": {"b64": encoded_image}
                      }]
                  }

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

您也可以将numpy数组编码到JSON中,但是API文档似乎并不需要这样做。

票数 0
EN

Stack Overflow用户

发布于 2018-07-16 13:57:33

两个边注:

  1. 我鼓励你使用tf.saved_model.simple_save
  2. 你会发现model_to_estimator很方便。
  3. 虽然您的模型似乎可以用于请求( saved_model_cli的输出显示输入和输出的外部维度都是None ),但是发送浮点数的JSON数组是相当低效的

最后一点,修改代码以完成图像解码服务器端的操作通常更容易,因此您将通过有线发送一个base64编码的JPG或PNG,而不是一个浮动数组。以下是Keras的一个示例(我计划用更简单的代码更新这个答案)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51187140

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档