这篇文章描述了如何在Amazon SageMaker中使用TensorFlow对象检测模型API来实现这一点。

首先,基于AWS示例笔记本,将解释如何使用SageMaker端点在单个图像上运行模型。对于较小的图像,这种方法可行,但对于较大的图像,我们会遇到问题。

为了解决这些问题,改用批处理转换作业。

起点:使用SageMaker TensorFLow对象检测API进行模型推断

AWS提供了一些关于GitHub如何使用SageMaker的好例子。

使用此示例使用TensorFlow对象检测API对对象检测模型进行预测:

image.png

将模型部署为端点时,可以通过调用端点,使用该模型一次推断一个图像。此代码取自示例笔记本,显示了如何定义TensorFlowModel并将其部署为模型端点:

import cv2

import sagemaker

from sagemaker.utils import name_from_base

from sagemaker.tensorflow import TensorFlowModel

role = sagemaker.get_execution_role()

model_artefact = '<your-model-s3-path>'

model_endpoint = TensorFlowModel(

name=name_from_base('tf2-object-detection'),

model_data=model_artefact,

role=role,

framework_version='2.2',

predictor = model_endpoint.deploy(initial_instance_count=1, instance_type='ml.m5.large')

然后,将图像加载为NumPy数组,并将其解析为列表,以便将其传递给端点:

def image_file_to_tensor(path):

cv_img = cv2.imread(path,1).astype('uint8')

cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)

return cv_img

img = image_file_to_tensor('test_images/22673445.jpg')

input = {

'instances': [img.tolist()]

最后,调用端点:

detections = predictor.predict(input)['predictions'][0]

问题:端点请求负载大小太大

这在使用小图像时很好,因为API调用的请求负载足够小。然而,当使用较大的图片时,API返回413错误。这意味着有效负载超过了允许的大小,即6 MB。

当然,我们可以在调用端点之前调整图像的大小,但我想使用批处理转换作业。

解决方案:改用批处理转换作业

使用SageMaker批量转换作业,你可以定义自己的最大负载大小,这样我们就不会遇到413个错误。其次,这些作业可用于一次性处理全套图像。

图像需要存储在S3存储桶中。所有图像都以批处理模式(名称中的内容)进行处理,预测也存储在S3上。

为了使用批处理转换作业,我们再次定义了TensorFlowModel,但这次我们还定义了入口点和源目录:

model_batch = TensorFlowModel(

name=name_from_base('tf2-object-detection'),

model_data=model_artifact,

role=role,

framework_version='2.2',

entry_point='inference.py',

source_dir='.',

inference.py代码转换模型的输入和输出数据,如文档中所述。此代码需要将请求负载(图像)更改为NumPy数组,并将其解析为列表对象。

从这个示例开始,我更改了代码,使其加载图像并将其转换为NumPy数组。inference.py中input_handler函数更改为以下内容:

import io

import json

import numpy as np

from PIL import Image

def input_handler(data, context):

""" Pre-process request input before it is sent to TensorFlow Serving REST API

Args:

data (obj): the request data, in format of dict or string

context (Context): an object containing request and configuration details

Returns:

(dict): a JSON-serializable dict that contains request body and headers

"""

if context.request_content_type == "application/x-image":

payload = data.read()
image = Image.open(io.BytesIO(payload))
array = np.asarray(image)
return json.dumps({'instances': [array.tolist()]})
raise ValueError('{{"error": "unsupported content type {}"}}'.format(
context.request_content_type or "unknown"))

注意,在上面的代码中排除了output_handler函数。

此函数需要Python包NumPy和Pillow,它们未安装在运行批处理推断作业的机器上。

我们可以创建自己的镜像并使用该镜像(在TensorFlowModel对象初始化时使用image_uri关键字)。

也可以提供requirements.txt并将其存储在笔记本所在的文件夹中(称为source_dir=“.”)。该文件在镜像引导期间用于使用pip安装所需的包。内容为:

numpy

pillow

首先,想使用OpenCV(就像在endpoint示例中一样),但该软件包不太容易安装。

我们现在使用模型创建transformer对象,而不是将模型部署为模型端点:

input_path = "s3://bucket/input"

output_path = "s3://bucket/output"

tensorflow_serving_transformer = model_batch.transformer(

instance_count=1,

instance_type="ml.m5.large",

max_concurrent_transforms=1,

max_payload=5,

output_path=output_path,

最后,使用transform:

tensorflow_serving_transformer.transform(

input_path,

content_type="application/x-image",

图像由模型处理,结果将作为JSON文件最终在output_path bucket中。命名等于输入文件名,后跟.out扩展名。你还可以调整和优化实例类型、最大负载等。

最后

这很可能不是最具成本效益的方法,因为我们将图像作为NumPy数组传递给转换器。

此外,我们还可以在inference.py中调整output_handler函数压缩并存储在S3上的JSON,或仅返回相关检测。

Loading

作者 yinhua