模型工件检查、导出与实时端点部署
1. 模型工件检查与导出
1.1 MXNet 模型示例
首先,我们定义一个存储在 MXNet NDArray 中的测试样本:
import mxnet as mx
test_sample = mx.nd.array(
[0.00632,18.00,2.310,0,0.5380,6.5750,65.20,4.0900,1,296.0,15.30,4.98])
然后将其传入模型并读取输出:
response = net(test_sample)
print(response)
预测结果显示该房屋价格为 30,173 美元:
array([[30.173424]], dtype=float32)
1.2 计算机视觉(CV)内置模型
CV 的三个内置算法基于 Apache MXNet,以下是操作步骤:
1. 解压图像分类模型的工件:
$ tar xvfz model.tar.gz
x image-classification-0010.params
x model-shapes.json
x image-classification-symbol.json
- 加载模型及其参数:
import mxnet, json
from mxnet import gluon
sym_json = json.load(open('image-classification-symbol.json'))
sym_json_string = json.dumps(sym_json)
net = gluon.nn.SymbolBlock(
outputs=mx.sym.load_json(sym_json_string),
inputs=mx.sym.var('data'))
net.load_parameters('image-classification-0010.params', allow_missing=True)
net.collect_params().initialize()
- 创建一个 300x300 的三通道随机彩色图像作为测试样本,传入模型并读取结果:
test_sample = mx.ndarray.random.normal(shape=(1,3,300,300))
response = net(test_sample)
print(response)
结果显示该随机图像被分类为猫:
array([[0.99126923, 0.00873081]], dtype=float32)
1.3 XGBoost 模型
XGBoost 工件包含单个文件,其模型格式取决于使用方式:
-
内置算法
:模型是一个存储 Booster 对象的 pickle 文件。解压工件后,使用以下代码加载模型:
$ tar xvfz model.tar.gz
x xgboost-model
import pickle
model = pickle.load(open('xgboost-model', 'rb'))
print(type(model))
输出结果为:
<class 'xgboost.core.Booster'>
- 内置框架 :模型是一个保存的文件。解压工件后,直接加载模型:
$ tar xvfz model.tar.gz
x xgb.model
import xgboost as xgb
bst = xgb.Booster({'nthread': 4})
model = bst.load_model('xgb.model')
print(type(bst))
输出结果为:
<class 'xgboost.core.Booster'>
1.4 scikit-learn 模型
scikit-learn 模型使用 joblib 进行保存和加载:
$ tar xvfz model.tar.gz
x model.joblib
import joblib
model = joblib.load('model.joblib')
print(type(model))
输出结果为:
<class 'sklearn.linear_model._base.LinearRegression'>
1.5 TensorFlow 模型
TensorFlow 和 Keras 模型以 TensorFlow Serving 格式保存:
$ mkdir /tmp/models
$ tar xvfz model.tar.gz -C /tmp/models
x 1/
x 1/saved_model.pb
x 1/assets/
x 1/variables/
x 1/variables/variables.index
x 1/variables/variables.data-00000-of-00002
x 1/variables/variables.data-00001-of-00002
使用 Docker 镜像运行 TensorFlow Serving 来服务该模型:
$ docker run -t --rm -p 8501:8501 \
-v "/tmp/models:/models/fmnist" \
-e MODEL_NAME=fmnist \
tensorflow/serving
1.6 Hugging Face 模型
以 PyTorch 训练的情感分析模型为例:
1. 从 S3 复制并解压模型工件:
$ tar xvfz model.tar.gz
training_args.bin
config.json
pytorch_model.bin
- 在 Jupyter 笔记本中,使用 Hugging Face API 加载模型配置并构建模型:
from transformers import AutoConfig, DistilBertForSequenceClassification
config = AutoConfig.from_pretrained('./model/config.json')
model = DistilBertForSequenceClassification.from_pretrained('./model/pytorch_model.bin', config=config)
- 获取与模型关联的分词器:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained('distilbert-base-uncased')
- 编写一个函数对模型输出层的激活值应用 softmax:
import torch
def probs(logits):
softmax = torch.nn.Softmax(dim=1)
pred = softmax(logits).detach().numpy()
return pred
- 定义一个样本并使用模型进行预测:
inputs = tokenizer("The Phantom Menace was a really bad movie. What a waste of my life.", return_tensors='pt')
outputs = model(**inputs)
print(probs(outputs.logits))
输出结果显示情感强烈为负面:
[[0.22012234 0.7798777 ]]
2. 模型实时端点部署
2.1 SageMaker SDK 管理端点
SageMaker SDK 可通过以下几种方式处理端点:
- 配置估计器,使用 fit() 训练,使用 deploy() 部署端点,使用 predict() 调用。
- 导入并部署模型。
- 调用现有端点。
- 更新现有端点。
2.1.1 导入并部署 XGBoost 模型
步骤如下:
1. 创建模型工件:
$ tar cvfz model-xgb.tar.gz xgboost-model
- 在 Jupyter 笔记本中上传模型工件到默认存储桶:
import sagemaker
sess = sagemaker.Session()
prefix = 'export-xgboost'
model_path = sess.upload_data(
path='model-xgb.tar.gz',
key_prefix=prefix)
- 创建 XGBoostModel 对象:
from sagemaker.xgboost.model import XGBoostModel
xgb_model = XGBoostModel(
model_data=model_path,
entry_point='xgb-script.py',
framework_version='1.3-1',
role=sagemaker.get_execution_role())
- 编写推理脚本:
import os
import xgboost as xgb
def model_fn(model_dir):
model = xgb.Booster()
model.load_model(
os.path.join(model_dir,'xgboost-model'))
return model
- 部署并预测:
xgb_predictor = xgb_model.deploy(...)
xgb_predictor.predict(...)
2.1.2 导入并部署 TensorFlow 模型
步骤如下:
1. 打包 TensorFlow 模型:
$ tar tvfz model.tar.gz
1/
1/saved_model.pb
1/assets/
1/variables/
1/variables/variables.index
1/variables/variables.data-00000-of-00002
1/variables/variables.data-00001-of-00002
- 上传工件到 S3:
import sagemaker
sess = sagemaker.Session()
prefix = 'byo-tf'
model_path = sess.upload_data(
path='model.tar.gz',
key_prefix=prefix)
- 创建 SageMaker 模型:
from sagemaker.tensorflow.model import TensorFlowModel
tf_model = TensorFlowModel(
model_data=model_path,
framework_version='2.3.1',
role=sagemaker.get_execution_role())
- 部署并预测。
2.1.3 导入并部署 Hugging Face 模型(PyTorch)
首先编写推理脚本:
from transformers import AutoTokenizer, AutoConfig, DistilBertForSequenceClassification
import json
import torch
tokenizer = AutoTokenizer.from_pretrained('distilbert-base-uncased')
CLASS_NAMES = ['negative', 'positive']
def model_fn(model_dir):
config_path='{}/config.json'.format(model_dir)
model_path='{}/pytorch_model.bin'.format(model_dir)
config=AutoConfig.from_pretrained(config_path)
model= DistilBertForSequenceClassification.from_pretrained(model_path, config=config)
return model
def input_fn(serialized_input_data, content_type='application/json'):
if content_type == 'application/json':
input_data = json.loads(serialized_input_data)
return input_data
else:
raise Exception('Unsupported input type: ' + content_type)
def output_fn(prediction_output, accept='application/json'):
if accept == 'application/json':
return json.dumps(prediction_output), accept
else:
raise Exception('Unsupported output type: ' + accept)
def predict_fn(input_data, model):
inputs = tokenizer(input_data['text'], return_tensors='pt')
outputs = model(**inputs)
logits = outputs.logits
_, prediction = torch.max(logits, dim=1)
return CLASS_NAMES[prediction]
然后在笔记本中导入并部署模型:
from sagemaker.pytorch import PyTorchModel
model = PyTorchModel(
model_data=model_data_uri,
role=sagemaker.get_execution_role(),
entry_point='torchserve-predictor.py',
source_dir='src',
framework_version='1.6.0',
py_version='py36')
model.deploy()
positive_data = {'text': "This is a very nice camera, I'm super happy with it."}
negative_data = {'text': "Terrible purchase, I want my money back!"}
predictor = model.deploy()
prediction = predictor.predict(positive_data)
print(prediction)
prediction = predictor.predict(negative_data)
print(prediction)
2.1.4 调用现有端点
步骤如下:
1. 构建 TensorFlowPredictor 预测器:
from sagemaker.tensorflow.model import TensorFlowPredictor
another_predictor = TensorFlowPredictor(
endpoint_name=tf_endpoint_name,
serializer=sagemaker.serializers.JSONSerializer()
)
- 进行预测:
another_predictor.predict(...)
2.1.5 更新现有端点
以 TensorFlow 端点为例,将实例数设置为 2 并更新端点:
another_predictor.update_endpoint(
initial_instance_count=2,
instance_type='ml.t2.medium')
2.2 boto3 SDK 管理端点
boto3 是 AWS 的 Python SDK,使用它部署端点的步骤如下:
1. 使用 create_model() API 创建一个或多个模型,也可使用 SageMaker SDK 训练或导入的现有模型。
2. 定义一个或多个生产变体,列出每个模型的基础设施要求。
3. 使用 create_endpoint_config() API 创建端点配置,传入之前定义的生产变体并为每个变体分配权重。
4. 使用 create_endpoint() API 创建端点。
以下是部署一个运行 XGBoost 模型两个变体的端点示例:
1. 定义两个变体:
production_variants = [
{ 'VariantName': 'variant-1',
'ModelName': model_name_1,
'InitialInstanceCount': 1,
'InitialVariantWeight': 9,
'InstanceType': 'ml.t2.medium'},
{ 'VariantName': 'variant-2',
'ModelName': model_name_2,
'InitialInstanceCount': 1,
'InitialVariantWeight': 1,
'InstanceType': 'ml.t2.medium'}]
- 创建端点配置:
import boto3
sm = boto3.client('sagemaker')
endpoint_config_name = 'xgboost-two-models-epc'
response = sm.create_endpoint_config(
EndpointConfigName=endpoint_config_name,
ProductionVariants=production_variants,
Tags=[{'Key': 'Name',
'Value': endpoint_config_name},
{'Key': 'Algorithm', 'Value': 'xgboost'}])
- 创建端点:
endpoint_name = 'xgboost-two-models-ep'
response = sm.create_endpoint(
EndpointName=endpoint_name,
EndpointConfigName=endpoint_config_name,
Tags=[{'Key': 'Name','Value': endpoint_name},
{'Key': 'Algorithm','Value': 'xgboost'},
{'Key': 'Environment',
'Value': 'development'}])
- 创建 boto3 等待器等待端点就绪:
waiter = sm.get_waiter('endpoint_in_service')
waiter.wait(EndpointName=endpoint_name)
- 调用端点:
smrt = boto3.Session().client(service_name='runtime.sagemaker')
response = smrt.invoke_endpoint(
EndpointName=endpoint_name,
ContentType='text/csv',
Body=test_sample)
- 选择接收预测请求的变体进行 A/B 测试:
variants = ['variant-1', 'variant-2']
for v in variants:
response = smrt.invoke_endpoint(
EndpointName=endpoint_name,
ContentType='text/csv',
Body=test_sample,
TargetVariant=v)
print(response['Body'].read())
- 更新变体权重:
response = sm.update_endpoint_weights_and_capacities(
EndpointName=endpoint_name,
DesiredWeightsAndCapacities=[
{ 'VariantName': 'variant-1',
'DesiredWeight': 5},
{ 'VariantName': 'variant-2',
'DesiredWeight': 5}])
- 移除一个变体:
production_variants_2 = [
{'VariantName': 'variant-2',
'ModelName': model_name_2,
'InitialInstanceCount': 1,
'InitialVariantWeight': 1,
'InstanceType': 'ml.t2.medium'}]
endpoint_config_name_2 = 'xgboost-one-model-epc'
response = sm.create_endpoint_config(
EndpointConfigName=endpoint_config_name_2,
ProductionVariants=production_variants_2,
Tags=[{'Key': 'Name',
'Value': endpoint_config_name_2},
{'Key': 'Algorithm', 'Value': 'xgboost'}])
模型部署流程 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(选择模型类型):::process
B --> C{MXNet?}:::decision
C -- 是 --> D(MXNet 模型操作):::process
C -- 否 --> E{CV 模型?}:::decision
E -- 是 --> F(CV 模型操作):::process
E -- 否 --> G{XGBoost 模型?}:::decision
G -- 是 --> H(XGBoost 模型操作):::process
G -- 否 --> I{scikit - learn 模型?}:::decision
I -- 是 --> J(scikit - learn 模型操作):::process
I -- 否 --> K{TensorFlow 模型?}:::decision
K -- 是 --> L(TensorFlow 模型操作):::process
K -- 否 --> M{Hugging Face 模型?}:::decision
M -- 是 --> N(Hugging Face 模型操作):::process
D --> O(选择部署方式):::process
F --> O
H --> O
J --> O
L --> O
N --> O
O --> P{SageMaker SDK?}:::decision
P -- 是 --> Q(SageMaker SDK 部署操作):::process
P -- 否 --> R{boto3 SDK?}:::decision
R -- 是 --> S(boto3 SDK 部署操作):::process
Q --> T([结束]):::startend
S --> T
模型类型与操作步骤表格
| 模型类型 | 操作步骤 |
|---|---|
| MXNet 模型 | 定义测试样本,传入模型并读取输出 |
| CV 模型 | 解压工件,加载模型及参数,创建测试样本,传入模型并读取结果 |
| XGBoost 模型(内置算法) | 解压工件,使用 pickle 加载模型 |
| XGBoost 模型(内置框架) | 解压工件,直接加载模型 |
| scikit - learn 模型 | 解压工件,使用 joblib 加载模型 |
| TensorFlow 模型 | 解压工件,使用 Docker 镜像运行 TensorFlow Serving 服务模型 |
| Hugging Face 模型 | 解压工件,加载模型配置,获取分词器,编写处理函数,定义样本并预测 |
2.2.1 各模型操作与部署总结
为了更清晰地展示不同模型的操作和部署步骤,我们将其总结在以下表格中:
| 模型类型 | 工件处理 | 模型加载 | 部署方式 | 关键代码 |
| ---- | ---- | ---- | ---- | ---- |
| MXNet | 无 |
net(test_sample)
| 无 |
python test_sample = mx.nd.array([...]) response = net(test_sample)
|
| CV(基于 MXNet) |
tar xvfz model.tar.gz
|
python sym_json = json.load(open('image - classification - symbol.json')) sym_json_string = json.dumps(sym_json) net = gluon.nn.SymbolBlock(outputs = mx.sym.load_json(sym_json_string), inputs = mx.sym.var('data')) net.load_parameters('image - classification - 0010.params', allow_missing = True) net.collect_params().initialize()
| 无 |
python test_sample = mx.ndarray.random.normal(shape=(1,3,300,300)) response = net(test_sample)
|
| XGBoost(内置算法) |
tar xvfz model.tar.gz
|
python import pickle model = pickle.load(open('xgboost - model', 'rb'))
| SageMaker SDK 或 boto3 SDK | 见前文对应部分代码 |
| XGBoost(内置框架) |
tar xvfz model.tar.gz
|
python import xgboost as xgb bst = xgb.Booster({'nthread': 4}) model = bst.load_model('xgb.model')
| SageMaker SDK 或 boto3 SDK | 见前文对应部分代码 |
| scikit - learn |
tar xvfz model.tar.gz
|
python import joblib model = joblib.load('model.joblib')
| 无 | |
| TensorFlow |
mkdir /tmp/models; tar xvfz model.tar.gz -C /tmp/models
| 无 | Docker 运行 TensorFlow Serving 或 SageMaker SDK |
bash docker run -t --rm -p 8501:8501 -v "/tmp/models:/models/fmnist" -e MODEL_NAME=fmnist tensorflow/serving
|
| Hugging Face(PyTorch) |
tar xvfz model.tar.gz
|
python from transformers import AutoConfig, DistilBertForSequenceClassification config = AutoConfig.from_pretrained('./model/config.json') model = DistilBertForSequenceClassification.from_pretrained('./model/pytorch_model.bin', config = config)
| SageMaker SDK | 见前文对应部分代码 |
2.2.2 不同 SDK 部署对比
SageMaker SDK 和 boto3 SDK 在模型部署方面各有特点,以下是它们的对比:
| SDK 类型 | 优点 | 缺点 | 适用场景 |
| ---- | ---- | ---- | ---- |
| SageMaker SDK | 操作简单,对常见模型有高级封装,适合快速部署和测试 | 灵活性相对较低,对于复杂场景可能需要额外开发 | 快速验证模型、简单模型部署 |
| boto3 SDK | 提供底层 API,可完全控制服务操作,适合复杂场景定制 | 代码复杂度高,需要对 AWS 服务有深入了解 | 复杂模型部署、多模型变体管理、A/B 测试等 |
2.2.3 部署过程中的注意事项
-
模型版本匹配
:在使用 SDK 部署模型时,要确保框架版本与训练时使用的版本一致,否则可能导致模型加载失败或预测结果不准确。例如,在使用 XGBoostModel 时,
framework_version要与训练时的版本匹配。 - 推理脚本编写 :推理脚本中的输入输出处理函数要考虑各种可能的输入输出类型,确保在不同场景下都能正常工作。例如,在处理 JSON 输入时,要对输入格式进行严格检查。
- 资源配置 :在使用 boto3 SDK 部署多模型变体时,要合理配置实例数量和权重,避免资源浪费或性能不足。例如,在进行 A/B 测试时,根据测试需求调整变体权重。
2.2.4 未来展望
随着机器学习技术的不断发展,模型部署的需求也越来越多样化。未来,可能会出现更高效、更智能的部署工具和方法。例如,自动化的模型部署流程,能够根据模型类型和数据特点自动选择最佳的部署方式和资源配置。同时,随着边缘计算的兴起,模型在边缘设备上的部署也将成为一个重要的研究方向。
模型部署 SDK 选择 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(确定部署需求):::process
B --> C{是否需要快速部署?}:::decision
C -- 是 --> D{模型是否常见?}:::decision
D -- 是 --> E(选择 SageMaker SDK):::process
D -- 否 --> F{是否需要复杂定制?}:::decision
F -- 是 --> G(选择 boto3 SDK):::process
F -- 否 --> E
C -- 否 --> F
E --> H(进行部署操作):::process
G --> H
H --> I([结束]):::startend
通过以上对不同模型工件的检查、导出以及使用不同 SDK 进行实时端点部署的介绍,我们可以根据具体需求选择合适的模型和部署方式,实现高效、准确的模型预测服务。在实际应用中,要根据模型的特点和业务需求,灵活运用这些方法和工具,不断优化部署流程,提高模型的性能和可用性。
超级会员免费看
54

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



