我创建了一个Cloud ML模型,该模型可用于在线预测。该模型是基于重新训练初始v3的简单分类模型。我需要我的模型在每个请求中处理许多实例(在我的情况下为裁剪图像)。请求正文的格式如下:
instances = []
count = 0
for item in itemMap:
w = itemMap[item]['width']
h = itemMap[item]['height']
x1 = itemMap[item]['x']
y1 = itemMap[item]['y']
x2 = x1 + w
y2 = y1 + h
crop_x1 = int(x1-w/2)
crop_x2 = int(x2+w/2)
crop_y1 = int(y1-h/5)
crop_y2 = int(y2+h/5)
#cropped and resized image
cropped_image = frame.crop((crop_x1,crop_y1,crop_x2,crop_y2))
resized_crop = cropped_image.resize((299,299))
buffer = BytesIO()
resized_crop.save(buffer, format="JPEG")
img_str = base64.b64encode(buffer.getvalue())
instances.append({"key":str(count), "image_bytes": {"b64": img_str.decode('utf-8')}})
count += 1
以下是我的请求代码中的关键部分:
def predict_json(project, model, instances, version=None):
"""Send json data to a deployed model for prediction.
Args:
project (str): project where the Cloud ML Engine Model is deployed.
model (str): model name.
instances ([Mapping[str: Any]]): Keys should be the names of Tensors
your deployed model expects as inputs. Values should be datatypes
convertible to Tensors, or (potentially nested) lists of datatypes
convertible to tensors.
version: str, version of the model to target.
Returns:
Mapping[str: any]: dictionary of prediction results defined by the
model.
"""
# Create the ML Engine service object.
# To authenticate set the environment variable
# GOOGLE_APPLICATION_CREDENTIALS=<path_to_service_account_file>
service = googleapiclient.discovery.build('ml', 'v1')
name = 'projects/{}/models/{}'.format(project, model)
if version is not None:
name += '/versions/{}'.format(version)
response = service.projects().predict(
name=name,
body={'instances': instances}
).execute()
if 'error' in response:
raise RuntimeError(response['error'])
return response['predictions']
和:
Map = []
t = time.time()
chunk = instances[0:50]
Mapping = predict_json(project, model, chunk)
Map.extend(Mapping)
elapsed = time.time() - t
print(elapsed)
该模型有效,但无法缩放。发送请求和接收响应所花费的时间几乎是线性的。
1个实例:1.1077377796173096 s, 2个实例:1.763524055480957 s, 10次:8.115557432174683 s, 50个实例:44.36078429222107 s,
任何超过50个实例,我都会超时,这意味着我必须分块地执行请求。
我希望Cloud ML扩展节点,以便请求时间接近平坦(每个实例一个节点)。我尝试过一次发送许多请求,以查看Cloud-Ml是否会分配更多节点。我也不想使用批处理预测,因为响应必须是实时的。
如何获取Cloud-ML来扩展请求并减少推理时间?
更新(07/12/2018):我还尝试使用minNodes:5创建一个版本,请求时间没有变化。
答案 0 :(得分:2)
当您有多个需要处理的数据实例时,有两种选择:
两者都有优点和缺点。第一个选项(将它们全部发送到同一请求中)是最有效的,即每次预测的成本和每次预测的时间最低。但是,用于预测的挂钟时间会更长。例如,您可能发送50张图像,而处理这些图像可能需要50秒。因此,每张图像的时间为1秒,成本为50节点*秒。
您应该特别了解请求中的每个实例都在同一台计算机上处理-这就是为什么您没有观察到水平缩放的原因。
另一方面,如果为每个图像创建一个新线程并为每个请求发送一个图像,从而并行发送请求,则可能会在10秒之内获得所有响应(触发较大大量请求同时导致新服务器启动,这可能会增加处理时间)。每个请求的平均时间可能是2.5秒,您可能需要25台计算机来处理所有请求(花费25 * 2.5 = 62.5节点*秒)
因此,挂钟时间较短,但每次预测的时间和成本较高。每个项目都会根据自己的需求进行权衡。
对于您的用例,很明显,您期望水平缩放,所以我建议 请记住上述折衷,每个请求发送较少的图像,并行发送更多的请求。如果同时发出太多请求,则可能导致更多计算机旋转以处理负载,这会增加处理时间,因此,您需要平衡请求中放置的图像数量和“ min_nodes”数量“你继续。
最后,您可以考虑使用batch prediction service,它在并行处理(大量)数据方面非常有效。但是,该服务旨在用于相当数量的输入实例,并且具有相当长的启动时间(大约5分钟)。文件输入/文件输出接口也不总是每个项目的最佳接口。
答案 1 :(得分:0)
relevant documentation概述了服务预测的缩放行为。具体来说,有关在线预测的部分应该告诉您您需要了解的内容:
在线预测服务扩展了它使用的节点数量,以在不引入过多延迟的情况下最大化其可以处理的请求数量。为此,该服务:
- 长时间停顿后第一次请求预测时分配一些节点。
- 缩放节点数量以响应请求流量,在流量增加时添加节点,并在请求数量减少时将其删除。
- 在几分钟内至少要准备好一个节点,以处理请求,即使没有要处理的节点也是如此。就绪状态可确保服务可以迅速为每个预测提供服务。
- 您的模型版本在没有预测要求的情况下运行几分钟后,缩小为零。
因此,您遇到的延迟不一致可能是由于较慢的初始缩放(即“冷启动”)造成的。为了避免这种情况,他们建议:
服务缩减为零后,或者流量突然增加时,初始化节点来处理请求可能需要一些时间(几秒到几分钟)。初始化时间取决于您的模型版本大小,因此客户端超时可能会导致请求丢弃,直到新节点已初始化为止,并且/或者在这段时间内延迟增加。
要确保始终提供及时的服务,可以通过在模型版本上设置
minNodes
选项来指定服务应准备就绪的最小节点数。此设置可能会增加成本,因为即使没有提供任何预测,您也要为节点付费。
基本上,如果需要保持较低的延迟,则必须保留大量的节点来处理请求。代价是这样做的成本要高得多。通常,大多数无服务器SaaS产品都将遵循类似的定价模型。