根据业务需求创建一种或几种 ML 模型,然后根据模型的推理获得业务所需的决策依据,这种做法想必大家都很熟悉了。然而具体到特定应用场景,这种做法可能会存在一些弊端。
举例来说,如果我们需要通过一个 ML 模型来预测某个地区的未来市场趋势,那么只要模型本身足够优秀,并且有必要的数据,这个目标还是很好实现的。但如果我们希望通过 ML 模型来学习用户在线听歌时候的喜好,然后给用户提供个性化的音乐推荐,那么为所有用户使用同一个模型,很明显,并不能获得最好的结果。
此时的问题就变成了:我们能否不要基于群组或细分市场来建立模型,而是基于个体用户的数据来建立,以便获得更准确的结果。这也是可以做到的,但必须注意成本问题。
虽然构建自定义机器学习模型较好地提高了单个使用案例推理的准确性,但缺点在于部署模型的成本大幅提高,而且在生产中管理如此多的模型很困难。当我们不用同时访问所有模型,但仍然需要可以随时使用这些模型时,这些问题变得尤为突出。Amazon SageMaker 的多模型终端节点可以解决这些痛点,并且能为企业提供一个可扩展但经济高效的解决方案用于部署多个机器学习模型。
Amazon SageMaker 是一项模块化的端到端服务,可用于轻松地大规模构建、训练和部署机器学习模型。在训练得到一个机器学习模型后,我们可以将它部署到完全托管的 Amazon SageMaker 终端节点上,该终端节点可以实时提供低延迟的推理。而在多模型终端节点功能的帮助下,我们可以在一个公共终端节点中部署多个模型,并通过一个使用多模型终端节点的服务容器向外提供服务。如此一来,便可以轻松地大规模管理机器学习模型的部署,并通过提高终端节点及其下层的基础计算实例的使用率来降低模型部署成本。
下文将介绍 Amazon SageMaker 多模型终端节点,并演示如何应用这项新功能通过 XGBoost 来预测各个细分市场的房屋价格。下文演示了在多模型终端节点上同时部署10个模型,也演示了在10个独立的终端节点上分别部署10个模型,并对这两种使用情形进行了对比。如下图所示,前者相比后者每月节省了3000美元的成本。
多模型终端节点可以轻松扩展到数百至数千个模型。下文还将讨论终端节点配置和监控需要考虑的因素,并将重点介绍在1000个模型规模的部署样例中,如何节省超过90%的成本。
Amazon SageMaker 多模型终端节点概述
Amazon SageMaker 可使我们跨多个可用区将模型一键式部署到自动扩展的 Amazon 机器学习实例上,以实现高冗余性。我们只需指定实例类型及所需的最大数和最小值,剩下的部分都将由 Amazon SageMaker 解决。
Amazon SageMaker 将启动实例、部署模型并设置安全的 HTTPS 终端节点。应用程序需要包含到此终端节点的 API 调用,以实现低延迟和高吞吐量推理。此架构可使我们在几分钟内将新模型集成到应用程序中,因为模型更改不再需要应用程序代码同步更改。Amazon SageMaker 是完全托管的服务,可代为管理生产计算基础设施,包括执行运行状况检查、应用安全补丁及执行其他的常规维护,这一切都可以使用内置的 Amazon CloudWatch 监控和日志记录来进行。
Amazon SageMaker 多模型终端节点可使我们在一个终端节点中部署多个经过训练的模型,并使用一个服务容器向外提供服务。多模型终端节点完全托管,具有高可用性,可实时提供推理服务。我们可以在推理请求中通过参数设置目标模型名称来轻松调用指定模型。如果拥有大量可通过共享服务容器提供服务,且不需要同时访问所有模型的相似模型,该项功能是不二之选。例如,法律应用程序可能需要全面覆盖一组广泛的监管辖区,如果有大量不经常访问的模型,那么一个多模型终端节点就可以高效的提供服务,并且显著的降低成本。
要在 Amazon SageMaker 中创建多模型终端节点,请选择多模型选项,提供推理服务容器镜像的路径,然后提供用于存储训练好的模型构件的 Amazon S3 前缀。只要模型全部使用相同前缀,即可按任何方式在 S3 中组织它们。调用多模型终端节点时,使用 InvokeEndpoint 的新 TargetModel 参数提供特定模型的相对路径。要在多模型终端节点中添加模型,只需将新训练的模型构件存储在与该终端节点关联的 S3 前缀下,然后该模型将立即可用于调用。要更新已在使用的模型,用新名称命名模型,并添加到 S3 中,然后用新模型名称调用终端节点。要停止使用在多模型终端节点上部署的模型,请停止调用该模型,并将它从 S3 中删除。
Amazon SageMaker 多模型终端节点将在调用时从 S3 中动态加载模型,而不是在创建终端节点时将所有模型从 S3 下载到容器中。因此,初次调用模型的推理延迟可能高于后续推理,后续推理将以低延迟返回调用。如果模型在调用时已加载到容器中,则可以跳过下载步骤,模型推理将以低延迟返回调用。例如,假设有一个一天只使用几次的模型,它将根据需要自动加载;而频繁访问的模型将保留在内存中,并持续以低延迟返回调用。下图显示了从 S3 动态加载到多模型终端节点中的模型。
使用 Amazon SageMaker 多模型终端节点预测房价
下文基于房屋定价领域带领大家逐步了解多模型终端节点的使用场景示例。有关更多信息,请参阅 GitHub 上的完整工作笔记本。它使用生成的合成数据让我们可以使用任意数量的模型进行实验。每个城市都使用随机生成的特征在一定数量的房子上进行了模型训练。
该实验包含以下步骤:
- 使训练好的模型可用于多模型终端节点
- 准备容器
- 创建和部署多模型终端节点
- 调用多模型终端节点
- 动态加载新模型
使训练好的模型可用于多模型终端节点
我们可以在不对模型或模型训练过程进行任何更改的情况下利用多模型部署,并继续生成将要保存在 S3 中的模型构件(如model.tar.gz文件)。
在示例笔记本中,将并行训练一组模型,且每个训练作业的模型构件都将复制到S3中指定的位置。训练并复制一组模型后,文件夹将拥有以下内容:
2019-11-15 14:40:04 11.2 KiB Chicago_IL.tar.gz
2019-11-15 14:40:04 11.9 KiB Houston_TX.tar.gz
2019-11-15 14:40:04 11.4 KiB LosAngeles_CA.tar.gz
对象总数:3
总大小:34.5 KiB
每个文件都根据原有的model.tar.gz名称进行重命名,以使每个模型都具有唯一的名称。发送请求做预测时,可通过名称指定目标模型。
准备容器
要使用 Amazon SageMaker 多模型终端节点,可以使用通用型多模型服务器功能在 GitHub 上构建 Docker 容器。该容器是一个灵活易用的框架,可托管基于任何框架的机器学习模型并对外提供服务。XGBoost 示例笔记本演示了如何将开源 Amazon SageMaker XGBoost 容器用作基础来构建容器。
创建多模型终端节点
下一步是创建多模型终端节点,该终端节点知道如何在S3中查找目标模型。本文使用 boto3(适用于 Python 的 AWS 开发工具包)创建模型元数据。将其模式设置为 MultiModel 并告知 Amazon SageMaker 包含所有模型构件的 S3 文件夹的位置,而不是指定某个模型。
此外,指定模型用于推理的框架镜像。本文使用在上一步构建的 XGBoost 容器。我们可以在为该框架配置的多模型终端节点中托管使用相同框架构建的模型。请参阅以下代码来创建模型实体:
container = {
'Image': XGB_CONTAINER,
'ModelDataUrl': ‘s3://my-bucket/path/to/artifacts/’,
'Mode': 'MultiModel'
}
response = sm_client.create_model(
ModelName = ‘my-multi-model-name’,
ExecutionRoleArn = role,
Containers = [container])
有了适当的模型定义后,还需要一个终端节点配置,该配置引用上面创建的模型实体名称。请参阅以下代码:
response = sm_client.create_endpoint_config(
EndpointConfigName = ‘my-epc’,
ProductionVariants=[{
'InstanceType': ‘ml.m4.xlarge’,
'InitialInstanceCount': 2,
'InitialVariantWeight': 1,
'ModelName': ‘my-multi-model-name’,
'VariantName': 'AllTraffic'}])
最后,使用以下代码创建终端节点:
response = sm_client.create_endpoint(
EndpointName = ‘my-endpoint’,
EndpointConfigName = ‘my-epc’)
调用多模型终端节点
要调用多模型终端节点,只需要传递一个新参数,该参数表示要调用的目标模型。以下示例代码为使用boto3的预测请求:
response = runtime_sm_client.invoke_endpoint(
EndpointName = ’my-endpoint’,
ContentType = 'text/csv',
TargetModel = ’Houston_TX.tar.gz’,
Body = body)
针对单一终端节点后托管的多个目标模型,示例笔记本通过一组随机调用进行迭代。它显示了终端节点如何按需动态加载目标模型。请参阅以下输出:
Using model Houston_TX.tar.gz to predict price of this house:
[1994, 3188, 5, 1.5, 1.62, 3]
486551.41 USD,took 1375 ms
Using model Chicago_IL.tar.gz to predict price of this house:
[1990, 3047, 5, 1.0, 1.11, 2]
428404.88 USD,took 850 ms
Using model Chicago_IL.tar.gz to predict price of this house:
[1995, 3514, 6, 2.0, 0.79, 2]
512149.66 USD,took 17 ms
Using model Houston_TX.tar.gz to predict price of this house:
[1978, 2973, 2, 1.5, 0.99, 1]
328904.12 USD,took 17 ms
由于要从 S3 下载特定模型并将其加载到内存中,针对该模型完成第一次请求的时间有更多延迟(称为冷启动)。后续,因为该模型已加载完成,调用不会产生额外的开销。
动态加载新模型到现有终端节点中
将新模型部署到现有的多模型终端节点中很简单。在终端节点已在运行的情况下,将一组新的模型构件复制到早前设置的相同的 S3 位置,然后客户端应用程序可以自由地请求来自于该目标模型的预测,剩余工作则交由 Amazon SageMaker 处理。下面的示例代码为纽约创建了一个可以立即投入使用的新模型:
!aws s3 cp NewYork_NY.tar.gz s3://my-bucket/path/to/artifacts/
response = runtime_sm_client.invoke_endpoint(
EndpointName=endpoint_name,
ContentType='text/csv',
TargetModel=’NewYork_NY.tar.gz’,
Body=body)
使用多模型终端节点,我们无需进行完整的终端节点更新,只需部署新模型(即一个 S3 副本),并且可以避免为每个新模型单独设置终端节点的成本开销。
为大量模型扩展多模型终端节点
随着捆绑模型的规模增大,Amazon SageMaker 多模型终端节点的好处也随之增加。使用一个终端节点托管两个模型时,可以节省成本,对于具有数百个甚至数千个模型的使用案例,节省幅度会更高。
例如,假设有1000个小型XGBoost模型,每个模型本身都可以由ml.c5.large终端节点(4GiB内存)提供服务,在 us-east-1 每实例小时的成本为0.119USD。如果为全部1000个模型各自提供终端节点,每月将花费171,360 USD。如果使用 Amazon SageMaker 多模型终端节点,使用ml.r5.2xlarge 实例的单个终端节点(64GiB内存)即可以托管全部1000个模型。这可以将生产推理成本降低99%,使每个月的成本仅为1,017 USD。下表总结了本示例中单个终端节点与多模型终端节点之间的区别。请注意,对每个目标模型进行冷启动调用后,多模型案例实现了7毫秒的第90个百分位延迟。假定终端节点配置为您的目标模型提供了足够的内存,所有模型都加载后的稳态调用延迟将与单模型终端节点的延迟相似。
使用 Amazon CloudWatch 指标监控多模型终端节点
为了在价格与性能之间进行权衡,我们要使用自己应用程序的模型和代表性流量对多模型终端节点进行测试。Amazon SageMaker在CloudWatch中为多模型终端节点提供额外的指标,以便确定终端节点的使用情况和缓存命中率,并对终端节点进行优化。指标如下:
- ModelLoadingWaitTime – 调用请求等待目标模型被下载或加载以执行推理的时间间隔。
- ModelUnloadingTime – 通过容器的 UnloadModel API 调用卸载模型所需要的时间间隔。
- ModelDownloadingTime – 从 S3 中下载模型所需要的时间间隔。
- ModelLoadingTime – 通过容器的 LoadModel API 调用加载模型所需要的时间间隔。
- ModelCacheHit – 发送至已加载模型的终端节点的 InvokeEndpoint请求数量。取平均统计值将显示模型已加载的请求的比率。
- LoadedModelCount – 已加载到终端节点的容器中的模型数量。每个实例都会发出该指标。1分钟内的平均(Average)统计量将显示每个实例已加载的模型平均数量,总(Sum)统计量显示在终端节点的所有实例中加载的模型总数量。因为我们可以将一个模型加载到终端节点的多个容器中,此指标跟踪的模型不一定是唯一的。
我们可以使用 CloudWatch 图表帮助持续作出决策,选择出最佳的实例类型、实例计数和某个特定终端节点应托管的模型数量。例如,下面的图表显示加载的模型数量在不断增加,缓存命中率也在相应增加。
在本例中,缓存命中率的起始值为0,当时没有加载模型。随着加载的模型数量增加,缓存命中率最终达到100%。
将终端节点配置与使用案例匹配
为 Amazon SageMaker 终端节点选择适当的终端节点配置,尤其是实例类型和实例数量,这在很大程度上取决于特定使用案例要求。对于多模型终端节点也是如此。我们可以在内存中保存的模型数量取决于终端节点配置(如实例类型和计数)、模型配置文件(如模型大小和模型延迟)及推理流量模式。我们应该综合考虑上述因素来配置多模型终端节点并适当调整实例的大小,并且还应该为终端节点设置自动缩放。
Amazon SageMaker 多模型终端节点完全支持自动缩放。调用速率用于触发自动缩放事件,该速率基于终端节点服务之完整模型集的聚合预测集。
有些情形下,我们可以通过选择不能同时在内存中保存所有目标模型的实例类型来降低成本。Amazon SageMaker 将在内存用完时动态卸载模型,从而为新目标模型腾出空间。对于不经常请求的模型,动态加载可以节省成本,延迟尚可接受。对延迟敏感的情形,可能需要选择更大的实例类型或更多实例。对于特定使用案例,预先投入时间使用多模型终端节点进行测试和分析,将有助于优化成本,同时满足应用程序的性能需求。
结论
Amazon SageMaker 多模型终端节点可帮助我们以尽可能低的成本提供高性能机器学习解决方案。通过将一组类似的模型捆绑到单个终端节点后面,可以显著降低推理成本,我们可以使用单个共享服务容器提供服务。同样地,Amazon SageMaker 提供的托管 Spot 训练以帮助降低训练成本,并针对深度学习工作负载为 Amazon Elastic Inference 提供集成支持。最重要的是,它们将助力于 Amazon SageMaker 改进生产力,并有助于提高机器学习团队的影响力。