使用SageMaker Python SDK配置和使用Amazon SageMaker资源的默认值

Amazon SageMaker Python SDK是一款开源的库,可用于在Amazon SageMaker上训练和部署机器学习(ML)模型。在医疗保健和金融等高度受控行业中,企业客户设置安全防护措施,以确保其数据加密并且流量不经过互联网。为确保SageMaker的ML模型培训和部署遵循这些安全防护措施,通常会通过服务控制策略和AWS身份和访问管理(IAM)策略在帐户或AWS组织级别上设置限制,以强制执行特定的IAM角色、Amazon虚拟私有云(Amazon VPC)配置和AWS密钥管理服务(AWS KMS)密钥的使用。在这种情况下,数据科学家必须手动提供这些参数给他们的ML模型培训和部署代码,通过记录子网、安全组和KMS密钥。这使得数据科学家需要记住指定这些配置,以成功运行他们的作业,并避免出现访问被拒绝的错误。

从SageMaker Python SDK版本2.148.0开始,您现在可以配置参数的默认值,例如IAM角色、VPC和KMS密钥。管理员和终端用户可以在YAML格式的配置文件中初始化AWS基础设施原语中指定的默认值。一旦配置完成,Python SDK会自动继承这些值,并将它们传播到底层的SageMaker API调用,如CreateProcessingJob()CreateTrainingJob()CreateEndpointConfig(),无需其他操作。该SDK还支持多个配置文件,允许管理员为所有用户设置一个配置文件,用户可以通过存储在Amazon简单存储服务(Amazon S3)、Amazon弹性文件系统(Amazon EFS)中的用户级配置或用户的本地文件系统来覆盖它。

在本文中,我们将向您展示如何在Studio中创建和存储默认配置文件,并使用SDK默认功能创建您的SageMaker资源。

解决方案概述

我们使用一个端到端的AWS CloudFormation模板演示了这个新功能,该模板将创建所需的基础架构,并在部署的VPC中创建一个Studio域。此外,我们还为加密训练和处理作业中使用的卷创建了KMS密钥。步骤如下:

  1. 在您的账户中启动CloudFormation堆栈。或者,如果您想在现有的SageMaker域或笔记本上探索此功能,则可以跳过此步骤。
  2. 填充config.yaml文件并将该文件保存在默认位置。
  3. 运行一个包含数据处理、模型训练和推断的端到端ML用例的示例笔记本。
  4. 覆盖默认配置值。

先决条件

在开始之前,请确保您拥有AWS帐户和拥有管理员权限的IAM用户或角色。如果您是当前将基础架构参数传递给笔记本中的资源的数据科学家,则可以跳过下一步设置您的环境并开始创建配置文件。

要使用此功能,请确保通过运行pip install --upgrade sagemaker来升级您的SageMaker SDK版本。

设置环境

要部署包括网络和Studio域在内的完整基础架构,请完成以下步骤:

  1. 克隆GitHub存储库。
  2. 登录到您的AWS帐户并打开AWS CloudFormation控制台。
  3. 选择创建堆栈来部署网络资源。
  4. 上传setup/vpc_mode/01_networking.yaml下的模板。
  5. 为堆栈提供名称(例如networking-stack),并完成其余步骤以创建堆栈。
  6. 选择创建堆栈以部署Studio域。
  7. 上传setup/vpc_mode/02_sagemaker_studio.yaml下的模板。
  8. 为堆栈提供名称(例如sagemaker-stack),并在提示输入CoreNetworkingStackName参数时提供网络堆栈的名称。
  9. 按照其余步骤进行操作,选择IAM资源的确认并创建堆栈。

当两个堆栈的状态更新为CREATE_COMPLETE时,继续进行下一步。

创建配置文件

要使用 SageMaker Python SDK 的默认配置,您需要创建一个格式符合 SDK 要求的 config.yaml 文件。有关 config.yaml 文件的格式,请参阅 Configuration file structure。根据您的工作环境,例如 Studio 笔记本、SageMaker 笔记本实例或本地 IDE,您可以将配置文件保存到默认位置,或通过传递配置文件位置来覆盖默认设置。有关其他环境的默认位置,请参阅 Configuration file locations。以下步骤展示了 Studio 笔记本环境的设置。

要轻松创建 config.yaml 文件,请在 Studio 系统终端中运行以下单元格,将占位符替换为上一步中的 CloudFormation 堆栈名称:

git clone https://github.com/aws-samples/amazon-sagemaker-build-train-deploy.git
cd amazon-sagemaker-build-train-deploy
pip install boto3
python generate-defaults.py --networking-stack <network-stack-name> \
--sagemaker-stack <sagemaker-stack-name>

# 将文件保存到默认位置
mkdir .config/sagemaker
cp user-configs.yaml ~/.config/sagemaker/config.yaml

该脚本会自动填充 YAML 文件,并用基础架构默认值替换占位符,然后将文件保存到主文件夹中。然后将文件复制到 Studio 笔记本环境的默认位置。生成的配置文件应该类似于以下格式:

SageMaker:
  Model:
    EnableNetworkIsolation: false
    VpcConfig:
      SecurityGroupIds:
      - sg-xxxx
      Subnets:
      - subnet-xxxx
      - subnet-xxxx
  ProcessingJob:
    NetworkConfig:
      EnableNetworkIsolation: false
      VpcConfig:
        SecurityGroupIds:
        - sg-xxxx
        Subnets:
        - subnet-xxxx
        - subnet-xxxx
    ProcessingOutputConfig:
      KmsKeyId: arn:aws:kms:us-east-2:0123456789:alias/kms-defaults
    RoleArn: arn:aws:iam::0123456789:role/service-role/AmazonSageMakerExecutionRole-xxx
  TrainingJob:
    EnableNetworkIsolation: false
    VpcConfig:
      SecurityGroupIds:
      - sg-xxxx
      Subnets:
      - subnet-xxxx
      - subnet-xxxx
SchemaVersion: '1.0'
something: '1.0'

如果您已经设置了现有域和网络配置,请按照所需格式创建 config.yaml 文件,并将其保存到 Studio 笔记本的默认位置。

请注意,这些默认值只是自动填充适当的 SageMaker SDK 调用的配置值,并不强制用户使用特定的 VPC、子网或角色。作为管理员,如果您希望用户使用特定的配置或角色,请使用 IAM 条件键强制默认值。

此外,每个 API 调用都可以有自己的配置。例如,在前面的配置文件示例中,您可以为训练作业指定 vpc-asubnet-a,并为处理作业指定 vpc-bsubnet-csubnet-d

运行示例笔记本

现在您已经设置了配置文件,可以像往常一样开始运行模型构建和训练笔记本,大多数 SDK 函数无需显式设置网络和加密参数。有关受支持的 API 调用和参数的完整列表,请参阅 Supported APIs and parameters。

在 Studio 中,选择导航窗格中的文件资源管理器图标,然后打开 03_feature_engineering/03_feature_engineering.ipynb,如下图所示。

逐个运行笔记本单元格,并注意您不需要指定任何其他配置。当您创建处理器对象时,您将看到类似于以下示例的单元格输出。

如您在输出中所见,处理作业自动应用默认配置,无需用户提供任何额外的输入。

当您运行下一个单元格以运行处理器时,您还可以通过在导航窗格中选择“处理”下的“处理作业”,如以下截图所示,查看是否已设置默认值。

选择以前缀end-to-end-ml-sm-proc开头的处理作业,您应该可以查看网络和加密配置。

您可以继续运行剩余的笔记本以训练和部署模型,您会注意到基础设施默认值会自动应用于训练作业和模型。

覆盖默认配置文件

有时,用户需要覆盖默认配置,例如,尝试使用公共互联网访问进行实验,或者如果子网的IP地址用尽,则更新网络配置。在这种情况下,Python SDK还允许您为配置文件提供自定义位置,可以在本地存储上,也可以指向Amazon S3上的位置。在本节中,我们将探讨一个示例。

打开您的主目录中的user-configs.yaml文件,并在TrainingJob部分下将EnableNetworkIsolation值更新为True

现在,打开同样的笔记本,并将以下单元格添加到笔记本的开头:

import os
os.environ["SAGEMAKER_USER_CONFIG_OVERRIDE"] = "~/config.yaml"

使用此单元格,您可以将配置文件的位置指向SDK。现在,当您创建处理器对象时,您会注意到默认配置已被覆盖以启用网络隔离,处理作业将以网络隔离模式失败。

如果您正在使用本地环境(例如VSCode),您可以使用相同的覆盖环境变量设置配置文件的位置。

调试和检索默认值

如果在从笔记本运行API调用时遇到任何错误,单元格输出将显示应用的默认配置,如前一节所示,以供快速故障排除。要查看创建以默认配置文件传递的属性值的确切Boto3调用,请通过打开Boto3日志记录进行调试。要启用日志记录,请在笔记本顶部运行以下单元格:

import boto3
import logging
boto3.set_stream_logger(name='botocore.endpoint', level=logging.DEBUG)

任何后续的Boto3调用都将在日志中记录完整的请求,可以在日志的正文部分中查看。

您还可以使用session.sagemaker_config值查看默认配置的集合,如以下示例所示。

最后,如果您正在使用Boto3创建SageMaker资源,则可以使用sagemaker_config变量检索默认配置值。例如,在相同的笔记本中输入以下单元格的内容并运行该单元格以使用Boto3运行03_feature_engineering.ipynb中的处理作业:

import boto3
import sagemaker
session = sagemaker.Session()
client = boto3.client('sagemaker')

# get the default values
subnet_ids = session.sagemaker_config["SageMaker"]["ProcessingJob"]['NetworkConfig']["VpcConfig"]["Subnets"]
security_groups = session.sagemaker_config["SageMaker"]["ProcessingJob"]['NetworkConfig']["VpcConfig"]["SecurityGroupIds"]
kms_key = session.sagemaker_config["SageMaker"]["ProcessingJob"]["ProcessingOutputConfig"]["KmsKeyId"]
role_arn = session.sagemaker_config["SageMaker"]["ProcessingJob"]["RoleArn"]

# upload processing code
code_location = sagemaker_session.upload_data('./source_dir/preprocessor.py', 
                              bucket=s3_bucket_name, 
                              key_prefix=f'{s3_key_prefix}/code')
code_location = ('/').join(code_location.split('/')[:-1])

# create a processing job
response = client.create_processing_job(
    ProcessingJobName='end-to-end-ml-sm-proc-boto3',
    ProcessingInputs=[
        {
            'InputName': 'raw_data',
            "S3Input": {
                "S3Uri": raw_data_path,
                "LocalPath": "/opt/ml/processing/input",
                "S3DataType": "S3Prefix",
                "S3InputMode": "File",
            }
        },
        {
            "InputName": "code",
            "S3Input": {
                "S3Uri": code_location,
                "LocalPath": "/opt/ml/processing/input/code",
                "S3DataType": "S3Prefix",
                "S3InputMode": "File",
            }
        }
    ],
    ProcessingOutputConfig={
        'Outputs': [
            {
                'OutputName': 'train_data',
                'S3Output': {
                    'S3Uri': train_data_path,
                    'LocalPath': "/opt/ml/processing/train",
                    'S3UploadMode': 'EndOfJob'
                },
            },
            {
                'OutputName': 'val_data',
                'S3Output': {
                    'S3Uri': val_data_path,
                    'LocalPath': "/opt/ml/processing/val",
                    'S3UploadMode': 'EndOfJob'
                },
            },
            {
                'OutputName': 'test_data',
                'S3Output': {
                    'S3Uri': test_data_path,
                    'LocalPath': "/opt/ml/processing/test",
                    'S3UploadMode': 'EndOfJob'
                },
            },
            {
                'OutputName': 'model',
                'S3Output': {
                    'S3Uri': model_path,
                    'LocalPath': "/opt/ml/processing/model",
                    'S3UploadMode': 'EndOfJob'
                },
            },
        ],
        'KmsKeyId': kms_key
    },
    ProcessingResources={
        'ClusterConfig': {
            'InstanceCount': 1,
            'InstanceType': 'ml.m5.large',
            'VolumeSizeInGB': 30,
        }
    },
    AppSpecification={
        "ImageUri": "257758044811.dkr.ecr.us-east-2.amazonaws.com/sagemaker-scikit-learn:0.20.0-cpu-py3",
        "ContainerArguments": [
            "--train-test-split-ratio",
            "0.2"
        ],
        "ContainerEntrypoint": [
            "python3",
            "/opt/ml/processing/input/code/preprocessor.py"
        ]
    },
    NetworkConfig={
        'EnableNetworkIsolation': False,
        'VpcConfig': {
            'SecurityGroupIds': security_groups,
            'Subnets': subnet_ids
        }
    },
    RoleArn=role_arn,
)

自动创建配置文件

对于管理员来说,需要为每个SageMaker笔记本实例或工作室用户配置文件创建配置文件并保存文件可能是一项艰巨的任务。虽然您可以建议用户使用存储在默认S3位置中的公共文件,但这会给数据科学家额外的负担。

为了自动化这一过程,管理员可以使用SageMaker生命周期配置(LCC)。对于工作室用户配置文件或笔记本实例,您可以将以下示例LCC脚本附加为用户默认Jupyter Server应用程序的默认LCC:

# sample LCC script to set default config files on the user's folder
#!/bin/bash

set -eux

# add --endpoint-url [S3 Interface Endpoint] if using an S3 interface endpoint
aws s3 cp <s3-location-of-config-file> ~/.config/sagemaker/config.yaml
echo "config file saved in the default location"

有关创建和设置默认生命周期脚本的说明,请参见使用Amazon SageMaker Studio的生命周期配置或自定义笔记本实例。

清理

完成此功能实验后,请清理您的资源以避免支付额外成本。如果按照本文所述规定预配了新资源,请按照以下步骤清理您的资源:

  1. 关闭用户配置文件的工作室应用程序。请参见关闭和更新SageMaker Studio和Studio应用程序以获取说明。在删除堆栈之前,请确保删除所有应用程序。
  2. 删除为工作室域创建的EFS卷。可以使用DescribeDomain API调用查看附加到域的EFS卷。
  3. 删除工作室域堆栈。
  4. 删除为工作室域创建的安全组。您可以在Amazon Elastic Compute Cloud(Amazon EC2)控制台上找到它们,名称为security-group-for-inbound-nfs-d-xxx和security-group-for-outbound-nfs-d-xxx
  5. 删除网络堆栈。

结论

在本文中,我们讨论了使用SageMaker Python SDK配置和使用关键基础设施参数的默认值。这使得管理员可以为数据科学家设置默认配置,从而为用户和管理员节省时间,消除重复指定参数的负担,并产生更精简和易于管理的代码。有关支持的参数和API的完整列表,请参见使用SageMaker Python SDK配置和使用默认值。有关任何问题和讨论,请加入机器学习和人工智能社区。