发布于: Nov 30, 2022

【概要】下面我们将一步步给大家演示,如何在 Amazon Web Services 上构建云原生机器学习训练平台

下面我们将一步步给大家演示,如何在 Amazon Web Services 上构建云原生机器学习训练平台,在此实验中您将使用以下几个 Amazon Web Services 服务:

  • Amazon S3 :Amazon Web Services 对象存储服务,用于存放训练数据集以及机器学习模型
  • Amazon SageMaker:Amazon Web Services 机器学习托管服务,在实验中主要的操作我们将在 Notebook Instance 中完成
  • Amazon Glue:无服务器化的 ETL 服务,Glue 的数据处理脚本已经为您准备好,对 Glue 的操作都会在 Notebook 中通过 Amazon SDK 的方式调用
  • Amazon Step Functions:无服务器服务编排工具,对 Amazon Step Functions 的操作都会在 Notebook 中通过 Amazon Step Functions Data Science SDK 的方式调用

下面我们正式开始实验步骤

 

Notebook Instance 是使用 Amazon SageMaker 的入口,在 Notebook Instance 部署完成后您可以进入到熟悉的 Jupyter Notebook 或者 Jupyter Lab 的 UI 中,完成算法开发、交互式验证,SageMaker 服务调用等工作;在 Amazon Web Services 配置好的 Jupyter Notebook 环境中,已经安装好了常用的 Tensorflow、MXNet、Pytorch、Spark 和 Python 等 Kernel,并且 Amazon SDK 和 CLI 也已经配置好,用户可以快速的开始机器学习的算法研发和验证。

创建 Notebook Instance 需要进入 SageMaker 的 Console,然后点击 “Create notebook instance”

然后选择这个 Notebook Instance 的配置,根据自己的需求进行选择

此外还需要配置 Notebook Instance 的 Role,在 Jupyter 中调用 Amazon CLI 和 Amazon SDK 的都将使用这个 Role 的权限,这里选择 “Create a new role” 然后按照默认的权限配置就好

然后其他配置保持默认,点击 “Create notebook instance”,然后等待新的 Notebook Instance 的状态变为 “InService”,然后点击 “Open jupyterLab” 进入 Jupyter Lab

进入 Jupyter Lab 之后,打开一个 Terminal,然后运行以下命令,将 Github repo 下载到 Jupyter Lab 本地:

cd SageMaker/ && git clone https://Github.com/xzy0223/SageMaker-example.git

然后导航到对应的目录,找到 SageMaker Pipeline 的 notebook 并打开,之后的大部分操作将在这里完成。

 

 

在 Notebook 中运行此 cell,这将在环境中安装 Step Functions Data Scientist SDK,用于后面调用

然后进行一些全局参数的初始化

  • session,接下来调用 SageMaker 组件的 session
  • bucket,用于存放训练数据的 S3 存储桶,需要提前创建好
  • source_prefix,用于存放原始训练数据的 S3 prefix
  • output_prefix,用于存放通过 Glue 转换过的最终训练数据的 prefix
 

在这个实验中,涉及到 Amazon Web Services 之间服务的调用,所以需要给这些服务配置正确的权限才能顺利完成。这些操作可以根据 notebook 中的描述在 Amazon Console 中完成。

  • 为 Notebook Instance 的 Role 分配 “Amazon Step Functions Full Access”,以便在 Jupyter notebook 中 Step Functions Data Scientist SDK 可以有权限操作。
  • 为 Notebook Instance 的 Role 分配可以创建 Glue Job 的权限,因为后边在 Jupyter notebook 中会通过 Amazon SDK 创建 Glue Job。
  • 为 Step Functions 创建一个 Role,并赋予这个 Role 操作 SageMaker 和 Glue 的权限,因为 Step Functions 要和这个 Role 绑定去启动 Glue job 和 SageMaker 的 training job 等组件
  • 为 Glue Job 创建一个 Role,Glue ETL job 需要使用这个 Role 的权限从 S3 读取和写入训练数据
 

从 Internet 下载 MNIST 数据集

将数据分割成 Train、Validation 和 Test 数据集并存储到 S3 上

创建 Glue ETL Job

我们需要创建一个 Glue ETL Job 用于后边 Step Functions 的调用,实验目录中包含了一个名为 “train_val_norm.py” 的 ETL 脚本,您可以打开进行查看,这个脚本的主要作用是从 S3 中读取原始训练数据,对特征进行归一化,最后再存储回 S3。

import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from pyspark.sql.functions import *
from awsglue.context import GlueContext
from awsglue.job import Job

# 获取Glue Job传进来的参数
args = getResolvedOptions(sys.argv, ['JOB_NAME','SOURCE_PATH', 'OUTPUT_PATH', 'TRAIN_PREFIX', 'VAL_PREFIX'])

# 获取Spark Context运行环境并生成Glue运行环境
glueContext = GlueContext(SparkContext.getOrCreate())
spark = glueContext.spark_session

# 开始Job
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

'''
对featurn数据进行normalization的函数
参数:
    data_source_url:原始数据的S3路径
    data_output_url:存储处理过的数据的S3路径
'''
def norm_transform(data_source_url, data_output_url):
    
    # 读取原始数据为dataframe
    source_data_frame = spark.read.load(data_source_url, format='csv',
                                        inferSchema=True, header=False)
    
    # MNIST数据集包含785列,第一列为label,剩下的为feature,选择dataframe的第一列数据生成新的label dataframe
    source_label_data_frame = source_data_frame.select(source_data_frame.columns[0])
    
    # 丢掉第一列,剩下的feature生成feature dataframe
    source_feature_data_frame = source_data_frame.drop(source_data_frame.columns[0])
    
    # 获得feature所有列的列表
    columns = source_feature_data_frame.columns
    # 遍历所有的列,对数据进行normalization
    for column in columns:
        source_feature_data_frame = source_feature_data_frame.withColumn(column, (source_feature_data_frame[column] / 255.))

    # 对feature和label数据分别生成自增id,两个dataframe的id是完全一样的
    source_label_data_frame = source_label_data_frame.withColumn("id", monotonically_increasing_id())
    source_feature_data_frame = source_feature_data_frame.withColumn("id", monotonically_increasing_id())
    
    # 通过outer join的方式将两组dataframe在列的方向进行合并,并删除不在需要的id
    target_train_data_frame = source_label_data_frame.join(source_feature_data_frame, "id", "outer").drop("id")

    # 存储数据到S3
    target_train_data_frame.write.save(
        data_output_url, 
        format='csv', 
        mode='overwrite')

# 组织好训练数据和验证数据
train_data_source_url = args['SOURCE_PATH'] + args['TRAIN_PREFIX'] + '*'
train_data_output_url = args['OUTPUT_PATH'] + args['TRAIN_PREFIX']

val_data_source_url = args['SOURCE_PATH'] + args['VAL_PREFIX'] + '*'
val_data_output_url = args['OUTPUT_PATH'] + args['VAL_PREFIX']

# 进行数据转换
norm_transform(train_data_source_url, train_data_output_url)
norm_transform(val_data_source_url, val_data_output_url)

# 提交Job
job.commit()

在 notebook 中通过 Amazon SDK 创建 Glue ETL Job

 

 

SageMaker 可以支持 Tensorflow、Pytorch 和 MXNet 等常见的框架,并且在 SageMaker SDK 中也为大家封装了对应的类,可以通过这个类创建出一个对应框架的 estimator,通过这个 estimator 对象可以完成从训练、部署到推理的整个机器学习流程。在本实验中,我们的算法基于 Tensorflow 开发,并且使用了脚本模式进行训练,脚本模式允许算法工程是编写自己的训练脚本,而无需构建一个训练容器镜像,简化了开发和验证算法的难度。

我们需要创建一个 Tensorflow Estimator,在后边 Step Funtions 会使用这个 Estimator 完成训练、部署模型的步骤,在创建时需要传入一些必要的参数:

  • entry_point:训练脚本的路径
  • output_path:模型文件存放的 S3 路径
  • train_instance_type:训练模型的实例类型,机型配置
  • train_instance_count:训练实例的数量
  • hyperparameters:训练脚本需要使用的超参数
  • framework_version:训练脚本使用的 Tensorflow 的版本
  • py_version:训练脚本使用的 python 版本
  • metric_definitions:训练任务要监控的模型性能指标
  • script_mode:打开脚本模式

 

 

Step Functions 是 Amazon Web Services 的任务编排服务,在其中最核心的概念就是 Step,也就是工作流中每一步要执行的任务;另外 Step Functions 中每个 step 都会有 input 和 output;并且可以在 Step Functions 中编排复杂的任务逻辑,比如并行、判断、分支等等,在这个实验中我们使用最简单的串行逻辑,按照数据处理、模型训练、模型创建到模型部署的流程顺序执行。

首先 import 相关类库

Step Functions 的工作流是通过事件触发的机制被启动的,并且由于每个 step 都要有 input,所以我们要定义一个触发工作流的 input schema,这个 input 会在各个 step 中传递,在其中我们定义了一些参数变量,对应的 step 会使用这些参数,完成对应的任务

定义 Glue Job Step,定义一些 Glue ETL Job 需要使用的参数

定义 Training Step,这里使用了我们刚才创建的 Tensorflow Estimator,还有需要传入训练数据的 S3 路径,并等待训练任务完成再进入下一个 Step

当训练结束后,需要创建一个 SageMaker 的 Model

下一个 Step 就是要生成一个部署模型的配置信息,比如托管模型的实例的配置和数量等

最后一个 Step 就是基于上一个 Step 创建的配置,部署托管模型的 Endpoint,这个 Endpoint 就可以被 client 进行调用,完成在线推理的工作

各个 Step 已经创建完成,那么就需要创建一个工作流将它们串联起来创建这个工作流

此时,来到 Step Functions 的 console 中,应该可以看到对应的工作流已经创建,并可以看到整个 pipeline 的图形化展现。您可以看到左侧是这个工作流的定义,在没有 Step Functions Data Scientist SDK 的情况下,您需要自己编写这个 JSON 文档完成配置,如果使用了 Step Functions Data Scientist SDK 极大的简化了创建机器学习工作流的难度和过程。

最后回到 notebook,完成对工作流的触发,传入我们定义好的 input 参数

当工作流开始运行后,您可以在 Step Functions 的 console 中看到每个 Step 的执行情况和 input/output

 

 

在本文中,我主要讲述了如何通过 Step Functions 编排整个机器学习工作流,使用 Glue 可以帮助我们完成训练数据的 ETL 和特征工程等数据相关的操作,SageMaker 可以完成从模型训练、超参调优、模型生成和模型部署等机器学习流程,最后通过服务器化的任务编排服务 Step Functions 将整个流程串联,并且 Amazon Web Services 提供了完善的 UI 和 SDK 工具,帮助算法工程师快速的构建、管理和监控机器学习工作流,大大提高了模型开发和模型验证的效率,更好的满足越来越多的业务需求。

 

相关文章