AWS SageMaker - 如何加载经过训练的 sklearn 模型以用于推理?
AWS SageMaker - How to load trained sklearn model to serve for inference?
我正在尝试将使用 sklearn 训练的模型部署到端点并将其用作 API 进行预测。我只想使用 sagemaker 来部署和使用 joblib
序列化的服务器模型,仅此而已。我读过的每一篇博客和 sagemaker python 文档都表明 sklearn 模型必须在 sagemaker 上进行训练才能部署在 sagemaker 中。
当我浏览 SageMaker 文档时,我了解到 sagemaker 确实允许用户 load a serialised model 存储在 S3 中,如下所示:
def model_fn(model_dir):
clf = joblib.load(os.path.join(model_dir, "model.joblib"))
return clf
这就是文档对参数 model_dir
:
的描述
SageMaker will inject the directory where your model files and
sub-directories, saved by save, have been mounted. Your model function
should return a model object that can be used for model serving.
这又意味着必须在 sagemaker 上进行训练。
那么,有没有一种方法可以指定我的序列化模型的 S3 位置并让 sagemaker 从 S3 反序列化(或加载)模型并将其用于推理?
编辑 1:
我在我的应用程序的答案中使用了代码,但在尝试从 SageMaker studio 的笔记本进行部署时出现以下错误。我相信 SageMaker 尖叫说训练没有在 SageMaker 上完成。
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-6662bbae6010> in <module>
1 predictor = model.deploy(
2 initial_instance_count=1,
----> 3 instance_type='ml.m4.xlarge'
4 )
/opt/conda/lib/python3.7/site-packages/sagemaker/estimator.py in deploy(self, initial_instance_count, instance_type, serializer, deserializer, accelerator_type, endpoint_name, use_compiled_model, wait, model_name, kms_key, data_capture_config, tags, **kwargs)
770 """
771 removed_kwargs("update_endpoint", kwargs)
--> 772 self._ensure_latest_training_job()
773 self._ensure_base_job_name()
774 default_name = name_from_base(self.base_job_name)
/opt/conda/lib/python3.7/site-packages/sagemaker/estimator.py in _ensure_latest_training_job(self, error_message)
1128 """
1129 if self.latest_training_job is None:
-> 1130 raise ValueError(error_message)
1131
1132 delete_endpoint = removed_function("delete_endpoint")
ValueError: Estimator is not associated with a training job
我的代码:
import sagemaker
from sagemaker import get_execution_role
# from sagemaker.pytorch import PyTorchModel
from sagemaker.sklearn import SKLearn
from sagemaker.predictor import RealTimePredictor, json_serializer, json_deserializer
sm_role = sagemaker.get_execution_role() # IAM role to run SageMaker, access S3 and ECR
model_file = "s3://sagemaker-manual-bucket/sm_model_artifacts/model.tar.gz" # Must be ".tar.gz" suffix
class AnalysisClass(RealTimePredictor):
def __init__(self, endpoint_name, sagemaker_session):
super().__init__(
endpoint_name,
sagemaker_session=sagemaker_session,
serializer=json_serializer,
deserializer=json_deserializer, # To be able to use JSON serialization
content_type='application/json' # To be able to send JSON as HTTP body
)
model = SKLearn(model_data=model_file,
entry_point='inference.py',
name='rf_try_1',
role=sm_role,
source_dir='code',
framework_version='0.20.0',
instance_count=1,
instance_type='ml.m4.xlarge',
predictor_cls=AnalysisClass)
predictor = model.deploy(initial_instance_count=1,
instance_type='ml.m4.xlarge')
是的,你可以。 AWS 文档侧重于在 SageMaker 中从训练到部署的端到端,这给人的印象是训练必须在 sagemaker 上完成。 AWS 文档和示例应明确区分 Estimator 培训、保存和加载模型以及 SageMaker 端点的部署模型。
SageMaker 模型
您需要创建 AWS::SageMaker::Model 资源,该资源引用您已训练 和更多 的“模型”。 AWS::SageMaker::Model 在 CloudFormation 文档中,但它只是为了解释您需要什么 AWS 资源。
CreateModel API creates a SageMaker model resource. The parameters specifie the docker image to use, model location in S3, IAM role to use, etc. See How SageMaker Loads Your Model Artifacts.
Docker 图片
显然您需要框架,例如ScikitLearn、TensorFlow、PyTorch 等,您用来训练模型以获得推论。您需要一个具有框架的 docker 图像,以及响应预测调用的 HTTP 前端。参见 SageMaker Inference Toolkit and Using the SageMaker Training and Inference Toolkits。
形象的建立并不容易。因此 AWS 提供了名为 AWS Deep Learning Containers and available images are in Github.
的预构建图像
如果你的框架和版本在那里列出,你可以使用它作为图像。否则需要自己搭建。参见 Building a docker container for training/deploying our classifier。
SageMaker Python 框架 SDK
使用 API 自己创建 SageMaker 模型很难。因此,AWS SageMaker Python SDK 提供了实用程序来为多个框架创建 SageMaker 模型。参见 Frameworks for available frameworks. If it is not there, you may still be able to use sagemaker.model.FrameworkModel and Model to load your trained model. For your case, see Using Scikit-learn with the SageMaker Python SDK。
model.tar.gz
例如,如果您使用 PyTorch 并将模型保存为 model.pth。要加载模型和推理代码以从模型中获取预测,您需要创建一个 model.tar.gz 文件。 model.tar.gz 中的结构在 Model Directory Structure. If you use Windows, beware of the CRLF to LF. AWS SageMaker runs in *NIX environment. See Create the directory structure for your model files 中有解释。
|- model.pth # model file is inside / directory.
|- code/ # Code artefacts must be inside /code
|- inference.py # Your inference code for the framework
|- requirements.txt # only for versions 1.3.1 and higher. Name must be "requirements.txt"
在 S3 中保存 tar.gz 文件。确保 IAM 角色可以访问 S3 存储桶和对象。
正在加载模型并进行推理
参见 Create a PyTorchModel object。在实例化 PyTorchModel class 时,SageMaker 会自动为 PyTorch 选择 AWS 深度学习容器镜像以用于 framework_version 中指定的版本。如果该版本的图像不存在,则失败。这在 AWS 中没有记录,但需要注意。然后,SageMaker 使用 S3 模型文件位置和 AWS 深度学习容器图像 URL.
在内部调用 CreateModel API
import sagemaker
from sagemaker import get_execution_role
from sagemaker.pytorch import PyTorchModel
from sagemaker.predictor import RealTimePredictor, json_serializer, json_deserializer
role = sagemaker.get_execution_role() # IAM role to run SageMaker, access S3 and ECR
model_file = "s3://YOUR_BUCKET/YOUR_FOLDER/model.tar.gz" # Must be ".tar.gz" suffix
class AnalysisClass(RealTimePredictor):
def __init__(self, endpoint_name, sagemaker_session):
super().__init__(
endpoint_name,
sagemaker_session=sagemaker_session,
serializer=json_serializer,
deserializer=json_deserializer, # To be able to use JSON serialization
content_type='application/json' # To be able to send JSON as HTTP body
)
model = PyTorchModel(
model_data=model_file,
name='YOUR_MODEL_NAME_WHATEVER',
role=role,
entry_point='inference.py',
source_dir='code', # Location of the inference code
framework_version='1.5.0', # Availble AWS Deep Learning PyTorch container version must be specified
predictor_cls=AnalysisClass # To specify the HTTP request body format (application/json)
)
predictor = model.deploy(
initial_instance_count=1,
instance_type='ml.m5.xlarge'
)
test_data = {"body": "YOUR PREDICTION REQUEST"}
prediction = predictor.predict(test_data)
默认情况下,SageMaker 使用 NumPy 作为序列化格式。为了能够使用JSON,需要指定序列化器和content_type。您可以将它们指定为预测器,而不是使用 RealTimePredictor class。
predictor.serializer=json_serializer
predictor.predict(test_data)
或
predictor.serializer=None # As the serializer is None, predictor won't serialize the data
serialized_test_data=json.dumps(test_data)
predictor.predict(serialized_test_data)
推理代码示例
参见 Process Model Input, Get Predictions from a PyTorch Model and Process Model Output。在此示例中,预测请求在 HTTP 请求正文中作为 JSON 发送。
import os
import sys
import datetime
import json
import torch
import numpy as np
CONTENT_TYPE_JSON = 'application/json'
def model_fn(model_dir):
# SageMaker automatically load the model.tar.gz from the S3 and
# mount the folders inside the docker container. The 'model_dir'
# points to the root of the extracted tar.gz file.
model_path = f'{model_dir}/'
# Load the model
# You can load whatever from the Internet, S3, wherever <--- Answer to your Question
# NO Need to use the model in tar.gz. You can place a dummy model file.
...
return model
def predict_fn(input_data, model):
# Do your inference
...
def input_fn(serialized_input_data, content_type=CONTENT_TYPE_JSON):
input_data = json.loads(serialized_input_data)
return input_data
def output_fn(prediction_output, accept=CONTENT_TYPE_JSON):
if accept == CONTENT_TYPE_JSON:
return json.dumps(prediction_output), accept
raise Exception('Unsupported content type')
相关
备注
SageMaker 团队不断更改实现,文档经常过时。当您确定您确实遵循了文档并且它不起作用时,很可能是过时的文档。在这种情况下,需要与 AWS 支持澄清,或在 Github.
中打开问题
我正在尝试将使用 sklearn 训练的模型部署到端点并将其用作 API 进行预测。我只想使用 sagemaker 来部署和使用 joblib
序列化的服务器模型,仅此而已。我读过的每一篇博客和 sagemaker python 文档都表明 sklearn 模型必须在 sagemaker 上进行训练才能部署在 sagemaker 中。
当我浏览 SageMaker 文档时,我了解到 sagemaker 确实允许用户 load a serialised model 存储在 S3 中,如下所示:
def model_fn(model_dir):
clf = joblib.load(os.path.join(model_dir, "model.joblib"))
return clf
这就是文档对参数 model_dir
:
SageMaker will inject the directory where your model files and sub-directories, saved by save, have been mounted. Your model function should return a model object that can be used for model serving.
这又意味着必须在 sagemaker 上进行训练。
那么,有没有一种方法可以指定我的序列化模型的 S3 位置并让 sagemaker 从 S3 反序列化(或加载)模型并将其用于推理?
编辑 1:
我在我的应用程序的答案中使用了代码,但在尝试从 SageMaker studio 的笔记本进行部署时出现以下错误。我相信 SageMaker 尖叫说训练没有在 SageMaker 上完成。
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-6662bbae6010> in <module>
1 predictor = model.deploy(
2 initial_instance_count=1,
----> 3 instance_type='ml.m4.xlarge'
4 )
/opt/conda/lib/python3.7/site-packages/sagemaker/estimator.py in deploy(self, initial_instance_count, instance_type, serializer, deserializer, accelerator_type, endpoint_name, use_compiled_model, wait, model_name, kms_key, data_capture_config, tags, **kwargs)
770 """
771 removed_kwargs("update_endpoint", kwargs)
--> 772 self._ensure_latest_training_job()
773 self._ensure_base_job_name()
774 default_name = name_from_base(self.base_job_name)
/opt/conda/lib/python3.7/site-packages/sagemaker/estimator.py in _ensure_latest_training_job(self, error_message)
1128 """
1129 if self.latest_training_job is None:
-> 1130 raise ValueError(error_message)
1131
1132 delete_endpoint = removed_function("delete_endpoint")
ValueError: Estimator is not associated with a training job
我的代码:
import sagemaker
from sagemaker import get_execution_role
# from sagemaker.pytorch import PyTorchModel
from sagemaker.sklearn import SKLearn
from sagemaker.predictor import RealTimePredictor, json_serializer, json_deserializer
sm_role = sagemaker.get_execution_role() # IAM role to run SageMaker, access S3 and ECR
model_file = "s3://sagemaker-manual-bucket/sm_model_artifacts/model.tar.gz" # Must be ".tar.gz" suffix
class AnalysisClass(RealTimePredictor):
def __init__(self, endpoint_name, sagemaker_session):
super().__init__(
endpoint_name,
sagemaker_session=sagemaker_session,
serializer=json_serializer,
deserializer=json_deserializer, # To be able to use JSON serialization
content_type='application/json' # To be able to send JSON as HTTP body
)
model = SKLearn(model_data=model_file,
entry_point='inference.py',
name='rf_try_1',
role=sm_role,
source_dir='code',
framework_version='0.20.0',
instance_count=1,
instance_type='ml.m4.xlarge',
predictor_cls=AnalysisClass)
predictor = model.deploy(initial_instance_count=1,
instance_type='ml.m4.xlarge')
是的,你可以。 AWS 文档侧重于在 SageMaker 中从训练到部署的端到端,这给人的印象是训练必须在 sagemaker 上完成。 AWS 文档和示例应明确区分 Estimator 培训、保存和加载模型以及 SageMaker 端点的部署模型。
SageMaker 模型
您需要创建 AWS::SageMaker::Model 资源,该资源引用您已训练 和更多 的“模型”。 AWS::SageMaker::Model 在 CloudFormation 文档中,但它只是为了解释您需要什么 AWS 资源。
CreateModel API creates a SageMaker model resource. The parameters specifie the docker image to use, model location in S3, IAM role to use, etc. See How SageMaker Loads Your Model Artifacts.
Docker 图片
显然您需要框架,例如ScikitLearn、TensorFlow、PyTorch 等,您用来训练模型以获得推论。您需要一个具有框架的 docker 图像,以及响应预测调用的 HTTP 前端。参见 SageMaker Inference Toolkit and Using the SageMaker Training and Inference Toolkits。
形象的建立并不容易。因此 AWS 提供了名为 AWS Deep Learning Containers and available images are in Github.
的预构建图像如果你的框架和版本在那里列出,你可以使用它作为图像。否则需要自己搭建。参见 Building a docker container for training/deploying our classifier。
SageMaker Python 框架 SDK
使用 API 自己创建 SageMaker 模型很难。因此,AWS SageMaker Python SDK 提供了实用程序来为多个框架创建 SageMaker 模型。参见 Frameworks for available frameworks. If it is not there, you may still be able to use sagemaker.model.FrameworkModel and Model to load your trained model. For your case, see Using Scikit-learn with the SageMaker Python SDK。
model.tar.gz
例如,如果您使用 PyTorch 并将模型保存为 model.pth。要加载模型和推理代码以从模型中获取预测,您需要创建一个 model.tar.gz 文件。 model.tar.gz 中的结构在 Model Directory Structure. If you use Windows, beware of the CRLF to LF. AWS SageMaker runs in *NIX environment. See Create the directory structure for your model files 中有解释。
|- model.pth # model file is inside / directory.
|- code/ # Code artefacts must be inside /code
|- inference.py # Your inference code for the framework
|- requirements.txt # only for versions 1.3.1 and higher. Name must be "requirements.txt"
在 S3 中保存 tar.gz 文件。确保 IAM 角色可以访问 S3 存储桶和对象。
正在加载模型并进行推理
参见 Create a PyTorchModel object。在实例化 PyTorchModel class 时,SageMaker 会自动为 PyTorch 选择 AWS 深度学习容器镜像以用于 framework_version 中指定的版本。如果该版本的图像不存在,则失败。这在 AWS 中没有记录,但需要注意。然后,SageMaker 使用 S3 模型文件位置和 AWS 深度学习容器图像 URL.
在内部调用 CreateModel APIimport sagemaker
from sagemaker import get_execution_role
from sagemaker.pytorch import PyTorchModel
from sagemaker.predictor import RealTimePredictor, json_serializer, json_deserializer
role = sagemaker.get_execution_role() # IAM role to run SageMaker, access S3 and ECR
model_file = "s3://YOUR_BUCKET/YOUR_FOLDER/model.tar.gz" # Must be ".tar.gz" suffix
class AnalysisClass(RealTimePredictor):
def __init__(self, endpoint_name, sagemaker_session):
super().__init__(
endpoint_name,
sagemaker_session=sagemaker_session,
serializer=json_serializer,
deserializer=json_deserializer, # To be able to use JSON serialization
content_type='application/json' # To be able to send JSON as HTTP body
)
model = PyTorchModel(
model_data=model_file,
name='YOUR_MODEL_NAME_WHATEVER',
role=role,
entry_point='inference.py',
source_dir='code', # Location of the inference code
framework_version='1.5.0', # Availble AWS Deep Learning PyTorch container version must be specified
predictor_cls=AnalysisClass # To specify the HTTP request body format (application/json)
)
predictor = model.deploy(
initial_instance_count=1,
instance_type='ml.m5.xlarge'
)
test_data = {"body": "YOUR PREDICTION REQUEST"}
prediction = predictor.predict(test_data)
默认情况下,SageMaker 使用 NumPy 作为序列化格式。为了能够使用JSON,需要指定序列化器和content_type。您可以将它们指定为预测器,而不是使用 RealTimePredictor class。
predictor.serializer=json_serializer
predictor.predict(test_data)
或
predictor.serializer=None # As the serializer is None, predictor won't serialize the data
serialized_test_data=json.dumps(test_data)
predictor.predict(serialized_test_data)
推理代码示例
参见 Process Model Input, Get Predictions from a PyTorch Model and Process Model Output。在此示例中,预测请求在 HTTP 请求正文中作为 JSON 发送。
import os
import sys
import datetime
import json
import torch
import numpy as np
CONTENT_TYPE_JSON = 'application/json'
def model_fn(model_dir):
# SageMaker automatically load the model.tar.gz from the S3 and
# mount the folders inside the docker container. The 'model_dir'
# points to the root of the extracted tar.gz file.
model_path = f'{model_dir}/'
# Load the model
# You can load whatever from the Internet, S3, wherever <--- Answer to your Question
# NO Need to use the model in tar.gz. You can place a dummy model file.
...
return model
def predict_fn(input_data, model):
# Do your inference
...
def input_fn(serialized_input_data, content_type=CONTENT_TYPE_JSON):
input_data = json.loads(serialized_input_data)
return input_data
def output_fn(prediction_output, accept=CONTENT_TYPE_JSON):
if accept == CONTENT_TYPE_JSON:
return json.dumps(prediction_output), accept
raise Exception('Unsupported content type')
相关
备注
SageMaker 团队不断更改实现,文档经常过时。当您确定您确实遵循了文档并且它不起作用时,很可能是过时的文档。在这种情况下,需要与 AWS 支持澄清,或在 Github.
中打开问题