优化机器学习模型部署:多模型端点、弹性推理与模型编译
1. 多模型端点部署
在处理大量模型时,将每个模型部署到单独的端点可能并不合理。例如,一家SaaS公司为其10,000个客户分别构建回归模型,管理和支付10,000个端点的成本是巨大的。此时,多模型端点就派上了用场。
1.1 多模型端点理解
多模型端点可以基于CPU为存储在S3中的任意数量的模型提供预测服务(撰写本文时暂不支持GPU)。在每个预测请求中传递要使用的模型工件的路径。模型会根据使用情况和端点上的可用内存动态加载和卸载。通过在S3中复制或删除工件,还可以向端点添加或删除模型。
为了服务多个模型,推理容器必须实现一组特定的API,端点将调用这些API,包括:LOAD MODEL、LIST MODEL、GET MODEL、UNLOAD MODEL和INVOKE MODEL。详情可查看:https://docs.aws.amazon.com/sagemaker/latest/dg/mms-container-apis.html。
目前,最新的scikit - learn、TensorFlow、Apache MXNet和PyTorch内置容器原生支持这些API。XGBoost、kNN、线性学习器和随机切割森林等内置算法也支持。对于其他算法和框架,最佳选择是构建包含SageMaker推理工具包的自定义容器,因为它已经实现了所需的API(https://github.com/aws/sagemaker - inference - toolkit)。该工具包基于多模型服务器(https://github.com/awslabs/multi - model - server),也可以直接从CLI使用它来为多个模型提供预测服务。更多信息可查看:https://docs.aws.amazon.com/sagemaker/latest/dg/build - multi - model - build - container.html。
1.2 使用scikit - learn构建多模型端点
以下是使用scikit - learn构建多模型端点的步骤,该端点托管在波士顿住房数据集上训练的模型,此功能仅支持scikit - learn 0.23 - 1及以上版本:
1.
上传数据集到S3
:
import sagemaker, boto3
sess = sagemaker.Session()
bucket = sess.default_bucket()
prefix = 'sklearn - boston - housing - mme'
training = sess.upload_data(path='housing.csv',
key_prefix=prefix +
'/training')
output = 's3://{}/{}/output/'.format(bucket,prefix)
- 使用不同的测试大小训练三个模型,并将它们的名称存储在字典中 :
from sagemaker.sklearn import SKLearn
jobs = {}
for test_size in [0.2, 0.1, 0.05]:
sk = SKLearn(entry_point=
'sklearn - boston - housing.py',
role=sagemaker.get_execution_role(),
framework_version='0.23 - 1',
instance_count=1,
instance_type='ml.m5.large',
output_path=output,
hyperparameters={ 'normalize': True,
'test - size': test_size }
)
sk.fit({'training':training}, wait=False)
jobs[sk.latest_training_job.name] = {}
jobs[sk.latest_training_job.name]['test - size'] = test_size
- 查找模型工件的S3 URI及其前缀 :
import boto3
sm = boto3.client('sagemaker')
for j in jobs.keys():
job = sm.describe_training_job(TrainingJobName=j)
jobs[j]['artifact'] = job['ModelArtifacts']['S3ModelArtifacts']
jobs[j]['key'] = '/'.join(
job['ModelArtifacts']['S3ModelArtifacts']
.split('/')[3:])
- 删除S3中之前存储的任何模型 :
%%sh -s "$bucket" "$prefix"
aws s3 rm --recursive s3://$1/$2/models
- 将三个模型工件复制到指定位置 :
s3 = boto3.client('s3')
for j in jobs.keys():
copy_source = { 'Bucket': bucket,
'Key': jobs[j]['key'] }
s3.copy_object(CopySource=copy_source,
Bucket=bucket,
Key=prefix+'/models/'+j+'.tar.gz')
response = s3.list_objects(Bucket=bucket,
Prefix=prefix+'/models/')
for o in response['Contents']:
print(o['Key'])
列出的模型工件如下:
sklearn - boston - housing - mme/models/sagemaker - scikit - learn - 2021 - 09 - 01 - 07 - 52 - 22 - 679
sklearn - boston - housing - mme/models/sagemaker - scikit - learn - 2021 - 09 - 01 - 07 - 52 - 26 - 399
sklearn - boston - housing - mme/models/sagemaker - scikit - learn - 2021 - 09 - 01 - 08 - 05 - 33 - 229
- 定义脚本名称和将上传代码存档的S3位置 :
script = 'sklearn - boston - housing.py'
script_archive = 's3://{}/{}/source/source.tar.gz'.format(bucket, prefix)
- 创建代码存档并将其上传到S3 :
%%sh -s "$script" "$script_archive"
tar cvfz source.tar.gz $1
aws s3 cp source.tar.gz $2
- 使用create_model() API创建多模型端点并相应设置Mode参数 :
import time
model_name = prefix+'-'+time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
response = sm.create_model(
ModelName = model_name,
ExecutionRoleArn = role,
Containers = [{
'Image': sk.image_uri,
'ModelDataUrl':'s3://{}/{}/models/'.format(bucket,
prefix),
'Mode': 'MultiModel',
'Environment': {
'SAGEMAKER_PROGRAM' : script,
'SAGEMAKER_SUBMIT_DIRECTORY' : script_archive
}
}]
)
- 像往常一样创建端点配置 :
epc_name = prefix+'-epc'+time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
response = sm.create_endpoint_config(
EndpointConfigName = epc_name,
ProductionVariants=[{
'InstanceType': 'ml.m5.large',
'InitialInstanceCount': 1,
'InitialVariantWeight': 1,
'ModelName': model_name,
'VariantName': 'variant - 1'}]
)
- 像往常一样创建端点 :
ep_name = prefix+'-ep'+time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
response = sm.create_endpoint(
EndpointName=ep_name,
EndpointConfigName=epc_name)
- 端点投入使用后,从数据集中加载样本并将其转换为numpy数组 :
import pandas as pd
import numpy as np
from io import BytesIO
data = pd.read_csv('housing.csv')
payload = data[:10].drop(['medv'], axis=1)
buffer = BytesIO()
np.save(buffer, payload.values)
- 使用所有三个模型对这些样本进行预测,在每个预测请求中传递要使用的模型名称 :
smrt = boto3.client('runtime.sagemaker')
for j in jobs.keys():
model_name=j+'.tar.gz'
response = smrt.invoke_endpoint(
EndpointName=ep_name,
TargetModel=model_name,
Body=buffer.getvalue(),
ContentType='application/x - npy')
print(response['Body'].read())
- 可以训练更多模型,将其工件复制到相同的S3位置,无需重新创建端点即可直接使用。也可以删除不需要的模型 。
- 完成后,删除端点 :
sm.delete_endpoint(EndpointName=ep_name)
sm.delete_endpoint_config(EndpointConfigName=epc_name)
2. 使用Amazon Elastic Inference部署模型
在部署模型时,需要决定是在CPU实例还是GPU实例上运行。有些算法无法从GPU加速中受益,应部署到CPU实例;而计算机视觉或自然语言处理等复杂的深度学习模型在GPU上运行效果最佳。但在很多情况下,情况并非如此明确。首先要了解应用程序的最大预测延迟。例如,实时广告技术应用中预测点击率时,每毫秒都很重要;而在后台办公应用中预测客户流失率时,对延迟的要求则没那么高。此外,即使可以从GPU加速中受益的模型,也可能不够大或复杂,无法充分利用现代GPU上的数千个核心。在这种情况下,部署在CPU上可能速度不够,而部署在GPU上又不划算。
2.1 Amazon Elastic Inference简介
Amazon Elastic Inference旨在解决这个问题(https://aws.amazon.com/machine - learning/elastic - inference/)。它允许将部分GPU加速功能附加到任何EC2实例,包括笔记本实例和端点实例。加速器有三种不同的尺寸(中、大、特大),可以为应用程序找到最佳的性价比。
Elastic Inference适用于TensorFlow、PyTorch和Apache MXNet。借助深度学习AMI中可用的AWS扩展,可以在运行于EC2实例上的代码中使用它,也可以与深度学习容器一起使用。更多信息可查看:https://docs.aws.amazon.com/elastic - inference/latest/developerguide/working - with - ei.html。
当然,Elastic Inference也可在SageMaker上使用。可以在创建笔记本实例时附加加速器,并使用内置的conda环境。也可以将加速器附加到端点,下面通过示例展示如何操作。
2.2 使用Amazon Elastic Inference部署模型示例
我们复用之前在猫狗图像上训练的图像分类模型,该模型基于18层ResNet模型,在卷积神经网络中算是比较小的:
1.
模型训练完成后,将其像往常一样部署到两个端点
:一个由ml.c5.large实例支持,另一个由ml.g4dn.xlarge实例支持(SageMaker上最具成本效益的GPU实例):
import time
endpoint_name = 'c5 - '+time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
c5_predictor = ic.deploy(initial_instance_count=1,
instance_type='ml.c5.large',
endpoint_name=endpoint_name,
wait=False)
endpoint_name = 'g4 - '+time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
g4_predictor = ic.deploy(
initial_instance_count=1,
instance_type='ml.g4dn.xlarge',
endpoint_name=endpoint_name,
wait=False)
- 下载测试图像,对其进行1000次预测,并测量总时间 :
with open(file_name, 'rb') as f:
payload = f.read()
payload = bytearray(payload)
def predict_images(predictor, iterations=1000):
total = 0
for i in range(0, iterations):
tick = time.time()
response = runtime.invoke_endpoint(
EndpointName=predictor.endpoint_name,
ContentType='application/x - image',
Body=payload)
tock = time.time()
total += tock - tick
return total/iterations
predict_images(c5_predictor)
predict_images(g4_predictor)
-
结果如下表所示(us - east - 1价格)
:
| 实例类型 | 速度 | 成本 |
| ---- | ---- | ---- |
| ml.c5.large | 相对较慢 | 低 |
| ml.g4dn.xlarge | 约为CPU实例的两倍快 | 高 |
可以看出,GPU实例速度约为CPU实例的两倍,但CPU实例更具成本效益,其成本不到GPU实例的四分之一。也就是说,可以用四个CPU实例代替一个GPU实例运行端点,在相同成本下获得更高的吞吐量。这表明了解应用程序的延迟要求非常重要,“快”和“慢”是相对的概念。
- 将相同的模型部署到另外三个由ml.c5.large实例支持的端点,并分别使用中、大、特大的Elastic Inference加速器进行加速 。只需在deploy() API中添加一个额外的参数。以下是中型端点的代码:
endpoint_name = 'c5 - medium - '+time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
c5_medium_predictor = ic.deploy(
initial_instance_count=1,
instance_type='ml.c5.large',
accelerator_type='ml.eia2.medium',
endpoint_name=endpoint_name,
wait=False)
predict_images(c5_medium_predictor)
与裸CPU端点相比,速度最多可提高20%,且成本低于使用GPU实例。
- 考虑数据类型对模型的影响 :之前的表格中包含了32位和16位浮点值的teraFLOP值。实际上,可以使用这两种数据类型之一来存储模型参数。查看图像分类算法的文档,发现可以使用precision_dtype参数选择数据类型,默认值为float32。那么,在float16模式下训练模型,结果会有不同吗?我们来测试一下:
ic.set_hyperparameters(
num_layers=18,
use_pretrained_model=0,
num_classes=2,
num_training_samples=22500,
mini_batch_size=128,
precision_dtype='float16',
epochs=10)
-
再次训练模型,发现与float32模式下的模型准确率相同。再次进行部署和基准测试,得到以下结果
:
在裸实例上没有明显差异。在大型和特大型加速器上使用FP - 16模型进行预测,与FP - 32模型相比,速度可提高约10%。与裸CPU实例相比,性能有了很大提升,且与GPU实例相比更具成本效益。实际上,将单个端点实例从ml.g4dn.xlarge切换到ml.c5.large + ml.eia2.large,每月可节省($0.736 - $0.438) x 24 x 30 = $214美元。
综上所述,Amazon Elastic Inference非常易于使用,为模型部署提供了更多选择。一旦确定了应用程序的预测延迟要求,就可以快速进行实验,找到最佳的性价比。
下面我们将介绍另一个SageMaker功能:Amazon Neo,它可以为特定的硬件架构编译模型。
3. 使用Amazon SageMaker Neo编译模型
嵌入式软件开发人员早已学会如何编写高度优化的代码,既能快速运行又能节省硬件资源。理论上,同样的技术也可应用于优化机器学习预测。但实际上,由于机器学习库和模型的复杂性,这是一项艰巨的任务。Amazon SageMaker Neo旨在解决这个问题。
3.1 理解Amazon SageMaker Neo
Amazon Neo有两个组件:一个模型编译器,用于为底层硬件优化模型;一个名为深度学习运行时(DLR)的小型运行时,用于加载优化后的模型并进行预测(https://aws.amazon.com/sagemaker/neo)。
Amazon SageMaker Neo可以编译使用以下算法和框架训练的模型:
-
内置算法
:XGBoost和图像分类。
-
内置框架
:TensorFlow、PyTorch和Apache MXNet,以及ONNX格式的模型。支持许多运算符,完整列表可查看:https://aws.amazon.com/releasenotes/sagemaker - neo - supported - frameworks - and - operators。
训练过程与往常一样,使用选择的估计器。然后,使用compile_model() API,可以轻松为以下硬件目标之一编译模型:
-
Amazon EC2实例家族
:c4、c5、m4、m5、p2、p3和inf1(本章后面会讨论),以及Lambda。
-
AI相机
:AWS DeepLens和Acer aiSage。
-
NVIDIA Jetson平台
:TX1、TX2、Nano和Xavier。
-
Raspberry Pi
。
-
来自Rockchip、Qualcomm、Ambarella等的片上系统平台
。
模型编译会进行架构优化(如融合层)和代码优化(用硬件优化版本替换机器学习运算符)。生成的工件存储在S3中,包含原始模型及其优化形式。
DLR用于加载模型并进行预测。当然,它也可以独立使用,例如在Raspberry Pi上。安装说明可查看:https://neo - ai - dlr.readthedocs.io。由于DLR是开源的(https://github.com/neo - ai/neo - ai - dlr),还可以从源代码构建它,并根据自己的硬件平台进行定制!
在SageMaker中使用DLR时,事情要简单得多。SageMaker提供了支持Neo的内置容器,应该使用这些容器来部署使用Neo编译的模型(如前所述,训练容器保持不变)。支持Neo的容器列表可查看:https://docs.aws.amazon.com/sagemaker/latest/dg/neo - deployment - hosting - services - cli.html。
最后,DLR的一个优点是其体积小。例如,p2和p3实例的Python包只有5.4 MB,比典型的深度学习库及其依赖项小几个数量级。这对于嵌入式环境显然至关重要,在SageMaker上也很受欢迎,因为容器也会更小。
3.2 在SageMaker上编译和部署图像分类模型
为了让Neo有更多的工作可做,这次我们训练一个50层的ResNet模型。然后编译它,将其部署到端点,并与原始模型进行比较:
1.
将num_layers设置为50,训练模型30个周期。然后像往常一样将其部署到ml.c5.4xlarge实例
:
ic_predictor = ic.deploy(initial_instance_count=1,
instance_type='ml.c5.4xlarge',
endpoint_name=ic_endpoint_name)
- 使用Neo编译模型,目标是EC2 c5实例家族。还定义模型的输入形状:一张图像,三个通道(红、绿、蓝),224 x 224像素(图像分类算法的默认值)。由于内置算法是用Apache MXNet实现的,相应地设置框架 :
output_path = 's3://{}/{}/output - neo/'.format(bucket, prefix)
ic_neo_model = ic.compile_model(
target_instance_family='ml_c5',
input_shape={'data':[1, 3, 224, 224]},
role=role,
framework='mxnet',
framework_version='1.5.1',
output_path=output_path)
- 像往常一样部署编译后的模型,明确将预测容器设置为支持Neo的图像分类版本 :
ic_neo_model.image = get_image_uri(
session.boto_region_name,
'image - classification - neo',
repo_version='latest')
ic_neo_predictor = ic_neo_model.deploy(
endpoint_name=ic_neo_endpoint_name,
initial_instance_count=1,
instance_type='ml.c5.4xlarge')
- 下载测试图像,并使用之前用于Amazon Elastic Inference的相同基准测试函数,测量预测1000张图像所需的时间 :
predict_images(ic_predictor)
predict_images(ic_neo_predictor)
原始模型预测需要87秒,而经过Neo优化的模型预测只需要28.5秒,速度提高了三倍!而且编译Neo模型是免费的,所以没有理由不尝试一下。
综上所述,多模型端点、Amazon Elastic Inference和Amazon SageMaker Neo为机器学习模型的部署提供了强大的工具和优化方案,可以根据不同的需求和场景选择合适的方法,以达到最佳的性能和成本效益。
优化机器学习模型部署:多模型端点、弹性推理与模型编译
4. 总结与对比
为了更清晰地展示多模型端点、Amazon Elastic Inference和Amazon SageMaker Neo这三种技术的特点和适用场景,我们将它们的关键信息总结在以下表格中:
| 技术 | 适用场景 | 优势 | 操作步骤 |
| ---- | ---- | ---- | ---- |
| 多模型端点 | 处理大量模型,无需为每个模型部署单独端点 | 节省管理成本和资源,可动态加载和卸载模型 | 上传数据集到S3;训练多个模型;查找模型工件S3 URI;删除旧模型;复制模型工件;定义脚本和存档位置;创建代码存档并上传;创建多模型端点;创建端点配置;创建端点;进行预测;完成后删除端点 |
| Amazon Elastic Inference | 模型需要一定GPU加速,但又不足以充分利用完整GPU资源 | 提供部分GPU加速,有多种尺寸可选,可找到最佳性价比 | 部署模型到不同实例;下载测试图像进行预测并测量时间;尝试不同加速器尺寸;考虑不同数据类型训练模型并对比结果 |
| Amazon SageMaker Neo | 为特定硬件架构优化模型,提高预测速度 | 进行架构和代码优化,生成优化后的模型工件,DLR体积小 | 训练模型;使用Neo编译模型;部署编译后的模型;进行基准测试对比 |
下面是这三种技术的使用流程的mermaid流程图:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([开始]):::startend --> B{选择技术}:::decision
B -->|多模型端点| C(上传数据集到S3):::process
B -->|Amazon Elastic Inference| D(部署模型到不同实例):::process
B -->|Amazon SageMaker Neo| E(训练模型):::process
C --> F(训练多个模型):::process
F --> G(查找模型工件S3 URI):::process
G --> H(删除旧模型):::process
H --> I(复制模型工件):::process
I --> J(定义脚本和存档位置):::process
J --> K(创建代码存档并上传):::process
K --> L(创建多模型端点):::process
L --> M(创建端点配置):::process
M --> N(创建端点):::process
N --> O(进行预测):::process
O --> P([结束]):::startend
D --> Q(下载测试图像进行预测并测量时间):::process
Q --> R(尝试不同加速器尺寸):::process
R --> S(考虑不同数据类型训练模型并对比结果):::process
S --> P
E --> T(使用Neo编译模型):::process
T --> U(部署编译后的模型):::process
U --> V(进行基准测试对比):::process
V --> P
5. 实际应用建议
在实际应用中,我们可以根据具体的业务需求和模型特点来选择合适的技术:
-
多模型端点
:当你有大量模型需要管理,且这些模型的使用频率相对较低或者不需要实时响应时,多模型端点是一个很好的选择。例如,一家电商公司为不同地区的用户群体训练了多个推荐模型,这些模型可以通过多模型端点进行统一管理和调用。
-
Amazon Elastic Inference
:如果你的模型需要一定的GPU加速,但又不想承担使用完整GPU实例的高昂成本,那么Amazon Elastic Inference是一个理想的解决方案。比如,一个小型的图像识别应用,其模型规模不足以充分利用GPU资源,但又需要比CPU更快的预测速度,就可以使用Elastic Inference。
-
Amazon SageMaker Neo
:当你需要将模型部署到特定的硬件设备上,并且希望提高模型的预测性能时,Amazon SageMaker Neo可以帮助你实现这一目标。例如,将模型部署到边缘设备(如AI相机、嵌入式系统等)上,通过Neo进行优化可以显著提高预测速度。
6. 未来展望
随着机器学习技术的不断发展,模型的规模和复杂度越来越高,对部署效率和成本的要求也越来越严格。多模型端点、Amazon Elastic Inference和Amazon SageMaker Neo等技术为我们提供了有效的解决方案,但未来可能还会有更多创新的技术和方法出现。
例如,可能会出现更加智能的资源分配算法,能够根据模型的实时使用情况自动调整资源配置,进一步提高资源利用率和成本效益。同时,随着硬件技术的不断进步,可能会有更适合机器学习模型部署的新型硬件设备出现,这也将促使相关技术不断优化和升级。
总之,我们需要密切关注这些技术的发展动态,不断探索和尝试新的方法,以满足日益增长的机器学习应用需求。
超级会员免费看
405

被折叠的 条评论
为什么被折叠?



