在人工智能(AI)和机器学习(ML)迅速发展的环境中,为组织构建一个机器学习运营(MLOps)平台对于无缝桥接数据科学实验和部署、同时满足模型性能、安全性和合规性要求至关重要。
为了满足监管和合规要求,在设计这样一个平台时主要需求包括:
- 解决数据漂移问题
- 监视模型性能
- 实现自动模型再训练
- 提供模型审批流程
- 将模型放在安全环境中
在本文中,我们展示了如何使用亚马逊Web服务(AWS)和第三方工具集创建一个MLOps框架来满足这些需求。该解决方案包括多环境设置,自动模型再训练,批量推断以及通过使用AWS的Amazon SageMaker,Amazon EventBridge,Amazon Simple Notification Service(Amazon SNS),HashiCorp Terraform,GitHub和Jenkins CI/CD实现机器学习代码和管道在各个环境之间的推广。我们构建了一个使用公开可用的UCI Mammography Mass数据集训练的XGBoost算法的乳腺肿块严重程度(良性或恶性)预测模型,并使用MLOps框架进行部署。完整的说明和代码可在GitHub存储库中找到。
解决方案概述
以下架构图显示了MLOps框架的概述,其中包含以下主要组件:
- 多账户策略 – 根据AWS良好架构最佳实践,在两个不同的AWS账户中设置了两个不同的环境(dev和prod),并在中央模型注册表中设置了第三个账户:
- Dev 环境 – 在该环境中设置了Amazon SageMaker Studio域,允许模型开发、模型训练和ML管道(训练和推断)的测试,在将模型提升至更高环境之前。
- Prod 环境 – 在此环境中,从dev环境中推广ML管道作为第一步,并在其上安排和监控一段时间。
- 中央模型注册表 – 分别在单独的AWS账户中设置了Amazon SageMaker Model Registry,用于跟踪在dev和prod环境中生成的模型版本。
- CI/CD和源代码控制 – 通过Jenkins设置的CI/CD来处理跨环境的ML管道部署,而版本控制则通过GitHub进行管理。合并到相应环境git分支的代码更改会触发CI/CD工作流程,以对给定目标环境进行适当的更改。
- 批量预测与模型监控 – 使用Amazon SageMaker Pipelines构建的推断管道定期运行,生成预测结果,并使用SageMaker Model Monitor监测数据漂移。
- 自动化重新训练机制 – 使用SageMaker Pipelines构建的训练管道在检测到推断管道中的数据漂移时被触发。训练完成后,模型将被注册到中央模型注册表中,由模型审批人批准。批准后,更新的模型版本将用于通过推断管道生成预测。
- 基础架构即代码 – 使用HashiCorp Terraform创建的基础架构即代码(IaC)支持使用EventBridge调度推断管道、基于EventBridge规则触发训练管道,并使用Amazon Simple Notification Service(Amazon SNS)主题发送通知。
MLOps工作流程包括以下步骤:
- 在开发账户中访问SageMaker Studio域,克隆GitHub存储库,使用提供的示例模型进行模型开发流程,并生成训练和推断管道。
- 在开发账户中运行训练管道,生成训练模型版本的模型工件,并将模型注册到中央模型注册账户的SageMaker模型注册表中。
- 在中央模型注册账户的SageMaker模型注册表中批准模型。
- 将代码(训练和推断管道以及Terraform IaC代码用于创建EventBridge调度、EventBridge规则和SNS主题)推送到GitHub存储库的特性分支中。创建拉取请求将代码合并到GitHub存储库的主分支中。
- 触发与GitHub存储库设置的Jenkins CI/CD管道。CI/CD管道将代码部署到生产账户中,创建训练和推断管道以及用于提供EventBridge调度、EventBridge规则和SNS主题的Terraform代码。
- 推断管道按日程安排运行,而训练管道设置为在从推断管道中检测到数据漂移时运行。
- 无论训练管道还是推断管道出现故障,都会通过SNS主题发送通知。
先决条件
这个解决方案需要满足以下先决条件:
- 三个AWS账户(开发、生产和中央模型注册账户)
- 在每个AWS账户中设置SageMaker Studio域(参见Onboard to Amazon SageMaker Studio或观看视频Onboard Quickly to Amazon SageMaker Studio获取设置说明)
- 在AWS上安装具有管理员权限的Jenkins(我们使用Jenkins 2.401.1)
- 在Jenkins服务器上安装Terraform版本1.5.5或更高版本
本文中,我们在us-east-1
区域部署解决方案。
在开发和生产账户中设置KMS密钥
我们的第一步是在开发和生产账户中创建AWS Key Management Service(AWS KMS)密钥。
在开发账户中创建KMS密钥并授予生产账户访问权限
按照以下步骤在开发账户中创建KMS密钥:
- 登录AWS KMS控制台,选择导航面板中的Customer managed keys。
- 选择Create key。
- 对于Key type,选择Symmetric。
- 对于Key usage,选择Encrypt and decrypt。
- 选择Next。
- 输入生产账号编号,以使生产账户能够访问在开发账户中配置的KMS密钥。这是一个必要的步骤,因为在开发账户中首次训练模型时,在将模型工件写入中央模型注册账户的S3存储桶之前,模型工件将使用KMS密钥进行加密。生产账户需要访问KMS密钥以解密模型工件并运行推断管道。
- 选择Next并完成密钥的创建。
密钥配置完成后,应在AWS KMS控制台上可见。
在prod账户中创建KMS密钥
按照前一部分的步骤,在prod账户中创建一个客户托管的KMS密钥。您可以跳过将KMS密钥共享到其他账户的步骤。
在中央模型注册表账户中设置模型工件的S3存储桶
在中央模型注册表账户中,使用您喜欢的字符串sagemaker
作为存储桶名称的一部分来创建一个S3存储桶,并更新S3存储桶上的存储桶策略,以授予从开发账户和prod账户读取和写入模型工件到S3存储桶的权限。
以下代码是要更新在S3存储桶上的存储桶策略:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AddPerm", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<dev-account-id>:root" }, "Action": [ "s3:PutObject", "s3:PutObjectAcl", "s3:GetObject", "s3:GetObjectVersion" ], "Resource": "arn:aws:s3:::<s3-bucket-in-central-model-registry-account>/*" }, { "Sid": "AddPerm1", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<dev-account-id>:root" }, "Action": "s3:ListBucket", "Resource": [ "arn:aws:s3:::<s3-bucket-in-central-model-registry-account>", "arn:aws:s3:::<s3-bucket-in-central-model-registry-account>/*" ] }, { "Sid": "AddPerm2", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<prod-account-id>:root" }, "Action": [ "s3:PutObject", "s3:PutObjectAcl", "s3:GetObject", "s3:GetObjectVersion" ], "Resource": "arn:aws:s3:::<s3-bucket-in-central-model-registry-account>/*" }, { "Sid": "AddPerm3", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<prod-account-id>:root" }, "Action": "s3:ListBucket", "Resource": [ "arn:aws:s3:::<s3-bucket-in-central-model-registry-account>", "arn:aws:s3:::<s3-bucket-in-central-model-registry-account>/*" ] } ]}
在您的AWS账户中设置IAM角色
下一步是在您的AWS账户中设置AWS身份和访问管理(IAM)角色,以授予AWS Lambda、SageMaker和Jenkins的权限。
Lambda执行角色
在dev账户和prod账户中设置Lambda执行角色,Lambda函数将作为SageMaker Pipelines Lambda步骤的一部分运行。这一步将从推论流水线中运行,以获取最新批准的模型,生成推论。在dev账户和prod账户中创建IAM角色,命名约定为arn:aws:iam::<account-id>:role/lambda-sagemaker-role
并附加以下IAM策略:
-
策略 1 – 创建一个内联策略,名为
cross-account-model-registry-access
,该策略允许在中央账户的模型注册表中访问模型包:{ "版本": "2012-10-17", "声明": [ { "标识符": "VisualEditor0", "效果": "允许", "动作": "sagemaker:ListModelPackages", "资源": "arn:aws:sagemaker:us-east-1:<中央模型注册账户ID>:model-package/mammo-severity-model-package/*" }, { "标识符": "VisualEditor1", "效果": "允许", "动作": "sagemaker:DescribeModelPackageGroup", "资源": "arn:aws:sagemaker:us-east-1:<中央模型注册账户ID>:model-package-group/mammo-severity-model-package" } ]}
-
策略 2 – 附加AmazonSageMakerFullAccess,这是一个AWS管理策略,授予SageMaker的完全访问权限。它还提供对相关服务的选择性访问权限,如AWS应用自动扩展、Amazon S3、Amazon Elastic Container Registry (Amazon ECR) 和Amazon CloudWatch Logs。
-
策略 3 – 附加AWSLambda_FullAccess,这是一个AWS管理策略,授予Lambda、Lambda控制台功能和其他相关AWS服务的完全访问权限。
-
策略 4 – 使用以下IAM信任策略作为IAM角色使用:
{ "版本": "2012-10-17", "声明": [ { "效果": "允许", "主体": { "服务": [ "lambda.amazonaws.com", "sagemaker.amazonaws.com" ] }, "动作": "sts:AssumeRole" } ]}
SageMaker执行角色
在开发和生产账户中设置的SageMaker Studio域应各自关联一个执行角色,可以在域详细信息页面的域设置选项卡中找到,如下图所示。该角色用于在SageMaker Studio域内运行训练作业、处理作业等。
将以下策略添加到两个账户中的SageMaker执行角色:
-
策略 1 – 创建一个内联策略,名为
cross-account-model-artifacts-s3-bucket-access
,该策略允许在中央模型注册账户的S3存储桶中访问模型工件:{ "版本": "2012-10-17", "声明": [ { "标识符": "VisualEditor0", "效果": "允许", "动作": [ "s3:PutObject", "s3:GetObject", "s3:GetObjectVersion" ], "资源": "arn:aws:s3:::<中央模型注册账户中的S3存储桶>/*" }, { "标识符": "VisualEditor1", "效果": "允许", "动作": [ "s3:ListBucket" ], "资源": [ "arn:aws:s3:::<中央模型注册账户中的S3存储桶>", "arn:aws:s3:::<中央模型注册账户中的S3存储桶>/*" ] } ]}
-
策略 2 – 创建一个内联策略,名为
cross-account-model-registry-access
,该策略允许在中央模型注册账户的模型注册表中访问模型包:{ "版本": "2012-10-17", "声明": [ { "标识符": "VisualEditor0", "效果": "允许", "动作": "sagemaker:CreateModelPackageGroup", "资源": "arn:aws:sagemaker:us-east-1:<中央模型注册账户ID>:model-package-group/mammo-severity-model-package" } ]}
-
策略 3 – 创建一个内联策略,名为
kms-key-access-policy
,该策略允许访问前一步骤中创建的KMS密钥。请提供正在创建策略的账户ID和在该账户中创建的KMS密钥ID。{ "版本": "2012-10-17", "声明": [ { "标识符": "AllowUseOfKeyInThisAccount", "效果": "允许", "动作": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "资源": "arn:aws:kms:us-east-1:<账户ID>:key/<KMS密钥ID>" } ]}
-
策略 4 – 附加AmazonSageMakerFullAccess,这是一个AWS管理策略,授予SageMaker的完全访问权限并选择性访问相关服务。
-
策略 5 – 附加AWSLambda_FullAccess,这是一个AWS管理策略,授予Lambda、Lambda控制台功能和其他相关AWS服务的完全访问权限。
-
策略 6 – 附加CloudWatchEventsFullAccess,这是一个AWS管理策略,授予CloudWatch Events的完全访问权限。
-
策略 7 – 添加以下IAM信任策略以进行SageMaker执行IAM角色:
{ "版本": "2012-10-17", "声明": [ { "效果": "允许", "主体": { "服务": [ "events.amazonaws.com", "sagemaker.amazonaws.com" ] }, "动作": "sts:AssumeRole" } ]}
-
策略 8 (仅适用于生产账户中的SageMaker执行角色)
跨账户 Jenkins 角色
在生产账户中设置一个名为
cross-account-jenkins-role
的 IAM 角色,Jenkins 将会扮演这个角色来部署机器学习管道和相应的基础设施到生产账户中。将以下托管的 IAM 策略添加到该角色中:
CloudWatchFullAccess
AmazonS3FullAccess
AmazonSNSFullAccess
AmazonSageMakerFullAccess
AmazonEventBridgeFullAccess
AWSLambda_FullAccess
更新角色的信任关系,以授予托管 Jenkins 服务器的 AWS 账户权限:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com", "AWS": "arn:aws:iam::<jenkins-account-id>:root" }, "Action": "sts:AssumeRole", "Condition": {} } ]}
更新与 Jenkins 服务器关联的 IAM 角色的权限
假设 Jenkins 已在 AWS 上设置好,更新与 Jenkins 关联的 IAM 角色,添加以下策略,从而使 Jenkins 可以访问并部署资源到生产账户中:
-
策略 1 – 创建名为
assume-production-role-policy
的内联策略:{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::<prod-account-id>:role/cross-account-jenkins-role" } ]}
-
策略 2 – 附加
CloudWatchFullAccess
托管的 IAM 策略。
在中央模型注册账户中设置模型包组
在中央模型注册账户的 SageMaker Studio 域中,使用以下代码段创建一个名为
mammo-severity-model-package
的模型包组(可以在 Jupyter 笔记本中运行):import boto3 model_package_group_name = "mammo-severity-model-package"sm_client = boto3.Session().client("sagemaker")create_model_package_group_response = sm_client.create_model_package_group( ModelPackageGroupName=model_package_group_name, ModelPackageGroupDescription="Cross account model package group for mammo severity model",)print('ModelPackageGroup Arn : {}'.format(create_model_package_group_response['ModelPackageGroupArn']))
为开发和生产账户中的 IAM 角色设置模型包访问权限
为在开发和生产账户中创建的 SageMaker 执行角色提供访问中央模型注册中的模型包
mammo-severity-model-package
的权限,从中央模型注册账户的 SageMaker Studio 域中,运行以下代码在 Jupyter 笔记本中:import json import boto3 model_package_group_name = "mammo-severity-model-package"# 将策略从 JSON 字典转换为字符串model_package_group_policy = dict({ "Version": "2012-10-17", "Statement": [ { "Sid": "AddPermModelPackageGroupCrossAccount", "Effect": "Allow", "Principal": { "AWS": ["arn:aws:iam::<dev-account-id>:root", "arn:aws:iam::<prod-account-id>:root"] }, "Action": [ "sagemaker:DescribeModelPackageGroup" ], "Resource": "arn:aws:sagemaker:us-east-1:<central-model-registry-account>:model-package-group/mammo-severity-model-package" }, { "Sid": "AddPermModelPackageVersionCrossAccount", "Effect": "Allow", "Principal": { "AWS": ["arn:aws:iam::<dev-account-id>:root", "arn:aws:iam::<prod-account-id>:root"] }, "Action": [ "sagemaker:DescribeModelPackage", "sagemaker:ListModelPackages", "sagemaker:UpdateModelPackage", "sagemaker:CreateModelPackage", "sagemaker:CreateModel" ], "Resource": "arn:aws:sagemaker:us-east-1:<central-model-registry-account>:model-package/mammo-severity-model-package/*" } ]})model_package_group_policy = json.dumps(model_package_group_policy)# 将策略添加到模型包组中sm_client = boto3.Session().client("sagemaker")response = sm_client.put_model_package_group_policy( ModelPackageGroupName = model_package_group_name, ResourcePolicy = model_package_group_policy)
设置Jenkins
在本节中,我们通过Jenkins CI/CD流程来配置Jenkins,以创建ML流水线和相应的Terraform基础架构在生产账户中。
- 在CloudWatch控制台中,创建一个名为
jenkins-log
的日志组,用于Jenkins将日志从CI/CD流程推送到生产账户中。日志组应该和Jenkins服务器设置的地区一致。 - 在Jenkins服务器上安装以下插件:
- 使用在生产账户中预置的跨账户IAM角色(
cross-account-jenkins-role
)在Jenkins中设置AWS凭证。 - 对于系统配置,选择AWS。
- 提供之前创建的凭证和CloudWatch日志组。
- 在Jenkins中设置GitHub凭证。
- 创建一个新的项目在Jenkins中。
- 输入一个项目名称并选择Pipeline。
- 在通用选项卡上,选择GitHub项目并输入复制的GitHub仓库的URL。
- 选择该项目为参数化。
- 在添加参数菜单中,选择字符串参数。
- 对于名称,输入
prodAccount
。 - 对于默认值,输入生产账户ID。
- 在高级项目选项下,对于定义,选择来自SCM的Pipeline脚本。
- 对于SCM,选择Git。
- 对于仓库URL,输入复制的GitHub仓库的URL。
- 对于凭证,输入在Jenkins中保存的GitHub凭证。
- 在要构建的分支部分中输入
main
,基于该分支触发CI/CD流程。 - 对于脚本路径,输入
Jenkinsfile
。 - 选择保存。
Jenkins流水线应该已经创建并显示在您的仪表板上。
准备S3存储桶,收集和准备数据
完成以下步骤来设置S3存储桶和数据:
-
在开发和生产账户中,使用字符串
sagemaker
将根据命名约定创建一个S3存储桶,以存储数据集和模型工件。 -
在生产账户中设置一个S3存储桶以维护Terraform状态。
-
从S3存储桶下载并保存公开可用的UCI乳腺X射线数据集到之前在开发账户中创建的S3存储桶。
-
在开发账户的SageMaker Studio域内分叉并克隆GitHub存储库。该存储库具有以下文件夹结构:
- /environments – 生产环境配置脚本
- /mlops-infra – 使用Terraform代码部署AWS服务的代码
- /pipelines – SageMaker流水线组件的代码
- Jenkinsfile – 通过Jenkins CI/CD流水线部署的脚本
- setup.py – 用于安装所需的Python模块和创建run-pipeline命令
- mammography-severity-modeling.ipynb – 允许您创建和运行ML工作流程
-
在克隆的GitHub存储库文件夹中创建一个名为data的文件夹,并保存公开可用的UCI乳腺X射线数据集的副本。
-
按照Jupyter笔记本
mammography-severity-modeling.ipynb
的指导进行操作。 -
在笔记本中运行以下代码,对数据集进行预处理并将其上传到开发账户中的S3存储桶:
import boto3import sagemakerimport numpy as npimport pandas as pdfrom sklearn.compose import ColumnTransformerfrom sklearn.impute import SimpleImputerfrom sklearn.pipeline import Pipelinefrom sklearn.preprocessing import StandardScaler, OneHotEncoder#根据已创建的资源替换值default_bucket = "<s3-bucket-in-dev-account>"model_artifacts_bucket = "<s3-bucket-in-central-model-registry-account>"region = "us-east-1"model_name = "mammography-severity-model"role = sagemaker.get_execution_role()lambda_role = "arn:aws:iam::<dev-account-id>:role/lambda-sagemaker-role"kms_key = "arn:aws:kms:us-east-1:<dev-account-id>:key/<kms-key-id-in-dev-account>"model_package_group_name="arn:aws:sagemaker:us-east-1:<central-model-registry-account-id>:model-package-group/mammo-severity-model-package"feature_columns_names = [ 'BIRADS', 'Age', 'Shape', 'Margin', 'Density',]feature_columns_dtype = { 'BIRADS': np.float64, 'Age': np.float64, 'Shape': np.float64, 'Margin': np.float64, 'Density': np.float64,}#读取原始数据集mammographic_data = pd.read_csv("data/mammographic_masses.data",header=None)#将数据分为批处理数据集和原始数据集batch_df =mammographic_data.sample(frac=0.05,random_state=200)raw_df =mammographic_data.drop(batch_df.index)#将原始数据集分为两部分,一部分用于最初的模型训练,另一部分在重新训练模型时使用train_dataset_part2 =raw_df.sample(frac=0.1,random_state=200)train_dataset_part1 =raw_df.drop(train_dataset_part2.index)#保存训练数据集train_dataset_part1.to_csv("data/mammo-train-dataset-part1.csv",index=False)train_dataset_part2.to_csv("data/mammo-train-dataset-part2.csv",index=False)#从批处理数据集中删除标签列,该列将用于生成推断batch_df.drop(5,axis=1,inplace=True)#创建批处理数据集的副本batch_modified_df = batch_dfdef preprocess_batch_data(feature_columns_names,feature_columns_dtype,batch_df): batch_df.replace("?", "NaN", inplace = True) batch_df.columns = feature_columns_names batch_df = batch_df.astype(feature_columns_dtype) numeric_transformer = Pipeline( steps=[("imputer", SimpleImputer(strategy="median"))] ) numeric_features = list(feature_columns_names) preprocess = ColumnTransformer( transformers=[ ("num", numeric_transformer, numeric_features) ] ) batch_df = preprocess.fit_transform(batch_df) return batch_df#保存批处理数据集文件batch_df = preprocess_batch_data(feature_columns_names,feature_columns_dtype,batch_df)pd.DataFrame(batch_df).to_csv("data/mammo-batch-dataset.csv", header=False, index=False)#修改批处理数据集以引入缺失值batch_modified_df.replace("?", "NaN", inplace = True)batch_modified_df.columns = feature_columns_namesbatch_modified_df = batch_modified_df.astype(feature_columns_dtype)#保存带有异常值的批处理数据集文件batch_modified_df.to_csv("data/mammo-batch-dataset-outliers.csv",index=False)
该代码将生成以下数据集:
-
- data/mammo-train-dataset-part1.csv – 将用于训练模型的第一个版本。
- data/mammo-train-dataset-part2.csv -将与mammo-train-dataset-part1.csv数据集一起用于训练模型的第二个版本。
- data/mammo-batch-dataset.csv – 将用于生成推理。
- data/mammo-batch-dataset-outliers.csv -将离群值引入数据集以使推理流程失败。 这将使我们能够测试触发模型自动重新训练的模式。
-
将数据集
mammo-train-dataset-part1.csv
上传到前缀为mammography-severity-model/train-dataset
的S3存储桶中,并将数据集mammo-batch-dataset.csv
和mammo-batch-dataset-outliers.csv
上传到前缀为mammography-severity-model/batch-dataset
的S3存储桶中:import boto3s3_client = boto3.resource('s3')s3_client.Bucket(default_bucket).upload_file("data/mammo-train-dataset-part1.csv","mammography-severity-model/data/train-dataset/mammo-train-dataset-part1.csv")s3_client.Bucket(default_bucket).upload_file("data/mammo-batch-dataset.csv","mammography-severity-model/data/batch-dataset/mammo-batch-dataset.csv")s3_client.Bucket(default_bucket).upload_file("data/mammo-batch-dataset-outliers.csv","mammography-severity-model/data/batch-dataset/mammo-batch-dataset-outliers.csv")
-
通过Amazon S3控制台将数据集
mammo-train-dataset-part1.csv
和mammo-train-dataset-part2.csv
上传到在生产账户中创建的S3存储桶中。 -
将数据集
mammo-batch-dataset.csv
和mammo-batch-dataset-outliers.csv
上传到生产账户中的S3存储桶的前缀为mammography-severity-model/batch-dataset
的位置。
运行训练流程
在
<项目名称>/pipelines/train
下,您可以看到以下Python脚本:- scripts/raw_preprocess.py – 与SageMaker处理集成以进行特征工程
- scripts/evaluate_model.py – 允许模型指标计算,本例中为
auc_score
- train_pipeline.py – 包含模型训练流程的代码
完成以下步骤:
-
将脚本上传到Amazon S3:
import boto3s3_client = boto3.resource('s3')s3_client.Bucket(default_bucket).upload_file("pipelines/train/scripts/raw_preprocess.py","mammography-severity-model/scripts/raw_preprocess.py")s3_client.Bucket(default_bucket).upload_file("pipelines/train/scripts/evaluate_model.py","mammography-severity-model/scripts/evaluate_model.py")
-
获取训练流程实例:
from pipelines.train.train_pipeline import get_pipelinetrain_pipeline = get_pipeline( region=region, role=role, default_bucket=default_bucket, model_artifacts_bucket=model_artifacts_bucket, model_name = model_name, kms_key = kms_key, model_package_group_name = model_package_group_name, pipeline_name = "mammo-severity-train-pipeline", base_job_prefix = "mammo-severity", )train_pipeline.definition()
-
提交训练流程并运行它:
train_pipeline.upsert(role_arn=role)train_execution = train_pipeline.start()
下图展示了训练流程的成功运行。流程中的最后一步是在中央模型注册表帐户中注册模型。
在中央模型注册表中批准模型
登录中央模型注册表帐户,访问SageMaker Studio领域内的SageMaker模型注册表。将模型版本状态更改为已批准。
批准后,模型版本的状态应更改。
运行推理流程(可选)
此步骤不是必需的,但您仍然可以运行推理流程以在dev账户中生成预测结果。
在
<project-name>/pipelines/inference
下,您可以看到以下Python脚本:- scripts/lambda_helper.py – 使用SageMaker Pipelines Lambda步骤从中央模型注册表帐户中获取最新批准的模型版本
- inference_pipeline.py – 包含模型推理流程的代码
完成以下步骤:
-
将脚本上传到S3存储桶:
import boto3s3_client = boto3.resource('s3')s3_client.Bucket(default_bucket).upload_file("pipelines/inference/scripts/lambda_helper.py","mammography-severity-model/scripts/lambda_helper.py")
-
获取使用正常批处理数据集的推理流程实例:
from pipelines.inference.inference_pipeline import get_pipelineinference_pipeline = get_pipeline( region=region, role=role, lambda_role = lambda_role, default_bucket=default_bucket, kms_key=kms_key, model_name = model_name, model_package_group_name= model_package_group_name, pipeline_name="mammo-severity-inference-pipeline", batch_dataset_filename = "mammo-batch-dataset" )
-
提交推理流程并运行:
inference_pipeline.upsert(role_arn=role)inference_execution = inference_pipeline.start()
下图展示了推理流程的成功运行。流程中的最后一步生成预测结果并将其存储在S3存储桶中。我们使用MonitorBatchTransformStep来监视批转换作业的输入。如果存在任何异常值,则推理流程将进入失败状态。
运行Jenkins流程
GitHub存储库中的
environment/
文件夹包含了用于prod账户的配置脚本。完成以下步骤来触发Jenkins流程:-
根据前面步骤中创建的资源更新配置脚本
prod.tfvars.json
:{ "env_group": "prod", "aws_region": "us-east-1", "event_bus_name": "default", "pipelines_alert_topic_name": "mammography-model-notification", "email":"admin@org.com", "lambda_role":"arn:aws:iam::<prod-account-id>:role/lambda-sagemaker-role", "default_bucket":"<s3-bucket-in-prod-account>", "model_artifacts_bucket": "<s3-bucket-in-central-model-registry-account>", "kms_key": "arn:aws:kms:us-east-1:<prod-account-id>:key/<kms-key-id-in-prod-account>", "model_name": "mammography-severity-model", "model_package_group_name":"arn:aws:sagemaker:us-east-1:<central-model-registry-account-id>:model-package-group/mammo-severity-model-package", "train_pipeline_name":"mammo-severity-train-pipeline", "inference_pipeline_name":"mammo-severity-inference-pipeline", "batch_dataset_filename":"mammo-batch-dataset", "terraform_state_bucket":"<s3-bucket-terraform-state-in-prod-account>", "train_pipeline": { "name": "mammo-severity-train-pipeline", "arn": "arn:aws:sagemaker:us-east-1:<prod-account-id>:pipeline/mammo-severity-train-pipeline", "role_arn": "arn:aws:iam::<prod-account-id>:role/service-role/<sagemaker-execution-role-in-prod-account>" }, "inference_pipeline": { "name": "mammo-severity-inference-pipeline", "arn": "arn:aws:sagemaker:us-east-1:<prod-account-id>:pipeline/mammo-severity-inference-pipeline", "cron_schedule": "cron(0 23 * * ? *)", "role_arn": "arn:aws:iam::<prod-account-id>:role/service-role/<sagemaker-execution-role-in-prod-account>" }}
-
完成更新后,将代码推送到fork的GitHub存储库中,并将代码合并到main分支。
-
进入Jenkins UI,选择Build with Parameters,触发之前创建的CI/CD流程。
当构建完成且成功时,您可以登录prod账号,在SageMaker Studio领域中查看训练和推断流水线。
此外,在prod账号的EventBridge控制台上,您还将看到三个EventBridge规则:
- 调度推断流水线
- 在训练流水线上发送故障通知
- 当推断流水线未能触发训练流水线时,发送通知
最后,您还将在Amazon SNS控制台上看到一个通过电子邮件发送通知的SNS通知主题。您将收到一封电子邮件要求您确认接受这些通知邮件。
使用无异常值批量数据集测试推断流水线
为了测试推断流水线在prod账号中是否按预期工作,我们可以登录prod账号并使用不含异常值的批量数据集触发推断流水线。
通过SageMaker Pipelines控制台在prod账号的SageMaker Studio领域中运行流水线,其中
transform_input
将是不含异常值数据集的S3 URI(s3://<s3-bucket-in-prod-account>/mammography-severity-model/data/mammo-batch-dataset.csv
)。推断流水线成功并将预测结果写回到S3存储桶。
使用带有异常值的批量数据集测试推断流水线
您可以运行带有异常值的批量数据集的推断流水线,以检查自动化重新训练机制是否按预期工作。
通过SageMaker Pipelines控制台在prod账号的SageMaker Studio领域中运行流水线,其中
transform_input
将是带有异常值数据集的S3 URI(s3://<s3-bucket-in-prod-account>/mammography-severity-model/data/mammo-batch-dataset-outliers.csv
)。推断流水线如预期失败,触发EventBridge规则,进而触发训练流水线。
几秒钟后,您应该在SageMaker Pipelines控制台上看到一条新的训练流水线运行,它将挑选出上传到S3存储桶的两个不同的训练数据集(
mammo-train-dataset-part1.csv
和mammo-train-dataset-part2.csv
)重新训练模型。您还将收到发送到订阅了SNS主题的电子邮件通知。
要使用更新后的模型版本,请登录中央模型注册表帐户并批准模型版本,这将在通过预定的EventBridge规则触发的推理流水线的下次运行中捡起。
虽然训练和推理流水线使用静态数据集URL,但您可以将数据集URL作为动态变量传递给训练和推理流水线,以便在实际场景中使用更新的数据集重新训练模型并生成预测。
清理
为避免未来产生费用,完成以下步骤:
- 删除所有AWS帐户中的SageMaker Studio域。
- 删除SageMaker之外创建的所有资源,包括S3存储桶、IAM角色、EventBridge规则和通过Terraform在生产环境中设置的SNS主题。
- 使用AWS命令行界面(AWS CLI)删除跨帐户创建的SageMaker流水线。
结论
组织通常需要与企业级工具集保持一致,以实现不同职能领域和团队之间的协作。这种协作确保您的MLOps平台能够适应不断变化的业务需求,并加速了各个团队之间的ML采用。本文介绍了如何在多环境设置中创建MLOps框架,以实现自动化模型重新训练、批量推理和监控,使用Amazon SageMaker Model Monitor进行模型版本管理,并通过CI/CD流水线在环境之间推广ML代码和流水线。我们展示了使用AWS服务和第三方工具集的组合解决方案。有关实施此解决方案的说明,请参阅GitHub存储库。您还可以通过引入自己的数据源和建模框架来扩展此解决方案。