Tensorflow 2.0:在保存的模型中添加图像预处理步骤

Tensorflow 2.0: Add image preprocessing step in a saved model

我是 TF 和 GCP 部署的新手。非常感谢您的帮助!

目前我正在尝试使用 TensorFlow Serving 在 Google 云平台 (GCP) 上部署我的 Mnist-handwriting flask 应用程序。我已经在 TF 服务上部署了我的模型,并使用自定义 MySimpleScaler class 对图像进行预处理和调整大小,然后再将其输入我的模型。我的问题是,是否有办法在我的保存模型class中添加预处理和调整大小class,以便我的烧瓶应用程序没有任何张量流依赖性。原因是 TF 库对于应用引擎来说太大了。

我的应用程序流程如下:

1) 我的 Flask 应用部署在 App Engine 上。它有一个 MySimpleScaler class 来调整来自 canvas 的图像输入的大小。我允许用户从前端的 canvas 中提取 --> 使用 jquery 获取数据 --> 使用 parse_image 函数将其写为 output.jpg --> 从本地驱动器读取 output.jpg 并将其提供给 MySimpleScaler 进行预处理

2) 我的模型使用 TF 服务部署在 AI 平台上。我在步骤 1 中使用 MysimpleScaler 的输出发送了一个预测请求。预测值然后被推送到 Flask 后端,然后我使用 Jinja

将它推送到前端

这是我用来获取和预处理数据的两个函数:

def parse_image(imgData):
    # imgData fetch img from canvas using request.get_data()
    imgstr = re.search(b"base64,(.*)", imgData).group(1)
    img_decode = base64.decodebytes(imgstr)
    with open("output.jpg", "wb") as file:
        file.write(img_decode)
    return img_decode
class MySimpleScaler(object):

    def preprocess_img(self, img_decode):
        # img_decode from parse_image
        img_raw = img_decode
        image = tf.image.decode_jpeg(img_raw, channels=1)
        image = tf.image.resize(image, [28, 28])
        image = (255 - image) / 255.0  # normalize to [0,1] range
        image = tf.reshape(image, (1, 28, 28, 1))

        return image

TL;DR:我想在将其部署到 TF 服务之前将 preprocess_img 函数添加为我的保存模型中的层之一。 非常感谢您的参与!

如果您同意batch_size=1,应该直接在图表中添加预处理函数,我会这样做,

代码:

import tensorflow as tf
import numpy as np

print('TensorFlow:',tf.__version__)

def preprocess_single_image(image_bytes, h=299, w=299):
    image = tf.image.decode_jpeg(image_bytes[0], channels=3)
    image = tf.image.resize(image, size=[h, w])
    image = (image - 127.5) / 127.5
    image = tf.expand_dims(image, axis=0)
    return image

image_bytes = tf.keras.Input(shape=[], batch_size=1, name='image_bytes', dtype=tf.string)
preprocessed_image = preprocess_single_image(image_bytes)
model = tf.keras.applications.Xception(weights='imagenet')
predictions = model(preprocessed_image)
new_model = tf.keras.Model(image_bytes, predictions)
new_model.save('export/1', save_format='tf')
print('Model Input Shape:', new_model.input_shape)

### !wget -q -O "cat.jpg" "https://images.pexels.com/photos/617278/pexels-photo-617278.jpeg?cs=srgb&dl=adorable-animal-blur-cat-617278.jpg&fm=jpg"
loaded_model = tf.saved_model.load('export/1')
cat_bytes = tf.expand_dims(tf.io.read_file('cat.jpg'), axis=0)
preds = loaded_model(cat_bytes).numpy()
print(tf.keras.applications.xception.decode_predictions(preds, top=3)[0])

输出:

TensorFlow: 2.0.0
WARNING:tensorflow:From /tensorflow-2.0.0/python3.6/tensorflow_core/python/ops/resource_variable_ops.py:1781: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
INFO:tensorflow:Assets written to: export/1/assets

Model Input Shape: (1,)
[('n02123045', 'tabby', 0.5762127), ('n02123159', 'tiger_cat', 0.24783427), ('n02124075', 'Egyptian_cat', 0.09435685)]

PS:如果你想扩展它以支持,你可以使用 tf.map_fn batch_size > 1