在本教程中,您将:
    1.    创建笔记本实例
    2.    准备数据
    3.    训练模型以从数据中学习
    4.    部署模型
    5.    评估您的机器学习模型的性能

管理亚马逊云科技资源

登录控制台


导航到 Amazon SageMaker 控制台。

1. 单击此处之后,亚马逊云科技管理控制台将在新窗口中打开,因此您可以使本分步指南保持打开状态。开始在搜索栏中键入 SageMaker,并选择 Amazon SageMaker 以打开服务控制台。

 

XGBoost_1

(单击以缩放)

XGBoost_1


在此步骤中,您将创建一个 Amazon SageMaker 笔记本实例。  

1. 从 Amazon SageMaker 控制面板中选择笔记本实例。

XGBoost_2

(单击以缩放)

XGBoost_2

2. 在创建笔记本实例页面上,在笔记本实例名称字段中输入名称。本教程使用 RecommendationSystemTest作为实例名称,如有需要,您可以选择其他名称。
在本教程中,您可以保留默认的笔记本实例类型:ml.t2.medium。
要使笔记本实例能够访问并安全地将数据上传到 Amazon S3,必须指定 IAM 角色。在 IAM 角色字段中,选择创建新角色,让 Amazon SageMaker 创建具有所需权限的角色,并将其分配给您的实例。或者,您也可以在您的账户中选择现有 IAM 角色来达到此目的。

XGBoost_3

(单击以缩放)

XGBoost_3

3. 在创建 IAM 角色框中,选择任意 S3 存储桶。 这让您的 Amazon SageMaker 实例可以访问您账户中的所有 S3 存储桶。在本教程的稍后部分,您将创建一个新的 S3 存储桶。但是,如果您有一个想要使用的存储桶,请选择特定 S3 存储桶并指定相应存储桶的名称。
选择创建角色。

XGBoost_4

(单击以缩放)

XGBoost_4

4.  请注意,Amazon SageMaker 为您创建了一个名为 AmazonSageMaker-ExecutionRole-20200415T100974 的角色。

在本教程中,我们将为其他字段使用默认值。选择创建笔记本实例。

(单击以缩放)


5. 在笔记本实例页面上,您应该会看到新的 xgboost-notebook 笔记本实例处于待处理状态。
您的笔记本实例应在两分钟内从待处理转变为服务中状态。

(单击以缩放)



在此步骤中,您将使用 Amazon SageMaker 笔记本预处理训练机器学习模型所需的数据。


1. 在笔记本实例页面上,等待 xgboost-notebook 从待处理转变为服务中状态。
当状态转变为服务中后,选择xgboost-notebook 并使用操作下拉菜单将其打开,或选择服务中状态旁边的打开 Jupyter。

(单击以缩放)

(单击以缩放)


2. 打开 Jupyter 后,从文件选项卡中选择新建,然后选择 conda_python3。

(单击以缩放)


3. 要准备数据,训练机器学习模型并进行部署,您需要导入一些库并在 Jupyter 笔记本环境中定义一些环境变量。将以下代码复制到实例中的代码单元格中,然后选择运行。

运行代码时,方括号之间会出现 *,几秒钟后,代码执行完成,* 将替换为数字 1,而且您将看到一条成功消息。

(单击以缩放)


4. 完成新建后就可以在notebook里开展我们后续的⼀系列⼯作了,⾸先我们安装基本的库:

!pip install sagemaker pandas

5. 之后,我们import⼀些基本的module,并把S3的数据加载到当前⽬录,做⼀个简单的数据探索:

import time
import boto3
import sagemaker
import urllib
import pandas as pd
from sklearn.model_selection import train_test_split

# 获取当前AWS region和notebook所绑定的role
role = sagemaker.get_execution_role()
region = boto3.Session().region_name

# 设置数据存放的桶和工作目录
bucket = 'sagemaker-bucket-xgb'
prefix = 'ori-data'

# 可以使用 SageMaker session 来上传下载数据,这里把S3的训练数据下载到当前目录
sm_session = sagemaker.Session()
sm_session.download_data("./", bucket, prefix + 'train.csv')
sm_session.download_data("./", bucket, prefix + 'test.csv')

# 通过describe来对查看一下训练数据feature的构成和分布
X_full=pd.read_csv("./train.csv", index_col='Id')
X_full.describe()

describe的结果如图所示,我们可以看到训练数据有很多字段构成,同时可以看到每个字段的取值分布情况,⽐如LotArea这个字段我们可以看到取值范围从1300到215245,平均值10516.828082,以及25%,50%,75%的分位数(Quantile)取值,也可以借助一些matplotlib,seaborn等图形化的库来更好做这种数据探索,好的数据探索对我们后续做数据预处理、改善模型的准确度都是很有帮助的。


(单击以缩放)


从上⾯的describe结果来看,⾥⾯⼀些feature的取值有⼀些不寻常的特点,对于当前的数据我们做⼀个简单的预处理:丢弃没有SalePrice的sample:

除了丢弃没有SalePrice的sample以外,我们还做了另外⼀个处理”提取训练数据中的label列,在原始数据中丢弃label列“,这是因为SageMaker的内置XGBoost算法对于输⼊数据有两个要求:

1. 训练数据要是把label作为⾸列,我们这⾥先把label从原始数据提取了出来,后⾯还会再把它作为第⼀列拼接回训练数据中;

2. 训练数据⾥不能有表头信息(就是诸如MSSubClass,LotFrontage这些列名)

另外,为了后⾯模型训练过程中验证模型的合理性我们还要对原始训练数据做⼀个拆分。把原始的训练数据拆分成training set和validation set。sklearn提供了很多⽤来做数据拆分的⼯具,我们这⾥直接调⽤它的⼀个函数来实现这个拆分:

# 丢弃没有SalePrice的sample
X = pd.read_csv("./train.csv", index_col='Id') 
X.dropna(axis=0, subset=['SalePrice'], inplace=True)

# 提取训练数据中的label列,在原始数据中丢弃label列
y = X.SalePrice
X.drop(['SalePrice'], axis=1, inplace=True)

# 拆分原始训练数据为四份,X_train_full, X_valid_full, y_train, y_valid
X_train_full, X_valid_full, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2, random_state=0)

7. 特征⼯程的引⼊是为了让我们的算法更好的理解特征⽽引⼊的。这里我们采⽤one-hot encoding来对可枚举的属性编码时,如果属性的取值个数过多,会导致产⽣过多的数据,在这⾥我们选择只对取值个数少于10的属性来做one-hot encoding,具体如下:

# Cardinality 代表的就是某个枚举类型的属性取值范围个数
# 这里是要筛选出 Cardinality 小于10的属性
low_cardinality_cols = [cname for cname in X_train_full.columns if X_train_full[cname].nunique() < 10 and X_train_full[cname].dtype == "object"]

# 筛选出数字类型的列
numeric_cols = [cname for cname in X_train_full.columns if X_train_full[cname].dtype in ['int64', 'float64']]

# 把Cardinality小于10和数字类型的列拼在一起作为全部的列
my_cols = low_cardinality_cols + numeric_cols

# 在training set 和 validation set 中只保留通过上面方法筛选出来的列
X_train = X_train_full[my_cols].copy()
X_valid = X_valid_full[my_cols].copy()

# 做 one-hot encoding
X_train = pd.get_dummies(X_train)
X_valid = pd.get_dummies(X_valid)

X_train, X_valid = X_train.align(X_valid, join='left', axis=1)

在此步骤中,您将使用训练数据集训练您的机器学习模型。

1. 要使用 Amazon SageMaker 预构建的 XGBoost 模型,您需要重新格式化训练数据的标题和第一列,并将结果存储在S3上。将以下代码复制到新的代码单元格中,然后选择运行 

# 对于training set 把label数据挪到第一列,去掉表头保存到当前目录
X_train_xgb= pd.concat([y_train,X_train], axis=1)
X_train_xgb.to_csv('./X_train.csv',header=False,index=False)

# 对于validation set 同样的把label数据挪到第一列,去掉表头保存到当前目录
X_valid_xgb= pd.concat([y_valid,X_valid], axis=1)
X_valid_xgb.to_csv('./X_valid.csv',header=False,index=False)

# 把准备的数据输入放到S3的工作目录里
train_data_location = 's3://{}/{}/{}'.format(bucket, prefix, 'train')
validation_data_location = 's3://{}/{}/{}'.format(bucket, prefix, 'validation')
sm_session.upload_data('./X_train.csv',bucket,prefix)
sm_session.upload_data('./X_valid.csv',bucket,prefix)

2. 接下来,您需要设置 Amazon SageMaker 会话,创建 XGBoost 模型(估算器)的实例,并定义模型的超参数。将以下代码复制到新的代码单元格中,然后选择运行,几分钟后,您应开始看到正在生成的训练日志。

# 我们使⽤SageMaker内置的XGBoost来训练,⾸先要获取这个算法的container
from sagemaker.amazon.amazon_estimator import get_image_uri
container = get_image_uri(region, 'xgboost', repo_version='0.90-2')
# 设置算法超参
hyperparameters = {
"max_depth":"5",
"eta":"0.5",
"early_stopping_rounds":"5",
"eval_metric":"mae",
"num_round":"20"}
# 训练使⽤哪种EC2实例来完成
instance_type = 'ml.m5.2xlarge'
# 模型输出⽬录
output_path = 's3://{}/{}/output'.format(bucket, prefix)
# 训练输⼊数据的类型
content_type = "csv"
# 设置训练任务的名字
job_name = 'xgb-housing-' + time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
print("Training job", job_name)
# 借助 Managed Spot Training 功能,⼤幅降低训练成本
train_use_spot_instances = True
train_max_run = 3600
train_max_wait = 7200 if train_use_spot_instances else None
checkpoint_s3_uri = ('s3://{}/{}/checkpoints/{}'.format(bucket, prefix,
job_name)
if train_use_spot_instances else None)
# 在SageMaker⾥的使⽤任何算法来训练都要先⽣成⼀个 estimator 对象
estimator = sagemaker.estimator.Estimator(container,
role,
hyperparameters=hyperparameters,
train_instance_count=1,
train_instance_type=instance_type,
train_volume_size=5, # 5 GB
output_path=output_path,
sagemaker_session=sagemaker.Session(),
train_use_spot_instances=train_use_spot_instances,
train_max_run=train_max_run,
train_max_wait=train_max_wait,
checkpoint_s3_uri=checkpoint_s3_uri
);
# 设置训练数据的 data channel
train_data_location = 's3://{}/{}/{}'.format(bucket, prefix, 'X_train.csv')
validation_data_location = 's3://{}/{}/{}'.format(bucket, prefix,
'X_valid.csv')
train_channel = sagemaker.session.s3_input(train_data_location,
content_type='text/csv')
valid_channel = sagemaker.session.s3_input(validation_data_location,
content_type='text/csv')
data_channels = {'train': train_channel, 'validation': valid_channel}
# 调⽤ fit 来训练
estimator.fit(inputs=data_channels, job_name=job_name, logs=True)

1. 评估模型的第⼀步是要先确⽴评估的标准——evaluation metric,在这⾥我们使⽤XGBoost解决回归问题,选择mae来作为评估标准。在训练过程中,我们就可以⼀直看到这个评估指标的输出情况:

# 部署模型

fm_predictor = fm.deploy(initial_instance_count=1,
                         instance_type='ml.t2.medium')

(单击以缩放)


2. 创建自动化调参任务

在console中找到“Hyperparameter tuning jobs”然后点击“Create hyperparameter tuning jobs”开始创建⾃动化调参任务。


(单击以缩放)


3. 新建⼀个名字叫xgb-housing-tuning的调参job

XGBoost_13

(单击以缩放)

XGBoost_13

4. tuning job内部需要先有⼀个training job,然后通过不断优化超参,来使得training job的评估指标最优。这⼀步就是创建这个training job,设置名字叫 xgb-housing-training-job 的训练job,然后在后续的界⾯中按照图示设置如何⾃动调参。

objective metric就是评估指标,我们这⾥还是选择mae。在Hyperparameter configuration这⾥,SageMaker会⾃动的把XGBoost相关的超参列出来供我们进⾏调整。IAM role就选择之前创建notebook时创建的role即可。

(单击以缩放)

XGBoost_15

(单击以缩放)

XGBoost_15

(单击以缩放)


6.在设置training job最后⼀个界⾯可以勾选使⽤spot training,这样可以利⽤spot instance⼤⼤节省调参的成本。

(单击以缩放)


7. 设置最⼤同时训练任务数(3次)和总共训练多少次(9次)

 

完成以上hyperparameter tuning job的创建后,就可以看到调参的运⾏情况,这⾥我们可以看到已经有3个训练任务在同时运⾏了。完成后我们可以看到所有9个训练任务的结果,其中mae最⼩值是16320.2998046875,查看这个训练

任务的详情我们就可以得到最佳的超参配⽐了。

可以看到每个超参的取值是多少:

(单击以缩放)

XGBoost_20

(单击以缩放)

XGBoost_20
XGBoost_21

(单击以缩放)

XGBoost_21

1. 点击“CreateModel”就可以把训练结果制作成⼀个可部署的模型了。建好后,就可以向下图⼀样在左边的菜单⾥的inference->Models下⾯看到创建好的模型了。

(单击以缩放)


2.点击上⾯任何⼀个模型后选择“Create endpoint”就可以进⼊模型的部署界⾯了。

(单击以缩放)

(单击以缩放)



现在我们要使⽤上图中的部署好的endpoint来做推理。跟上⾯在训练的时候提到的 Estimator 类似,SageMaker Python SDK也对推理调⽤有统⼀的抽象,这个名字是Predictors,任何的推理调⽤都要⾸先创建⼀个RealTimePredictor,然后调⽤它的predict⽅法,如下:

from sagemaker.predictor import csv_serializer
# 创建 predictor
xgb_predictor=sagemaker.predictor.RealTimePredictor(
"xgb-housing", // 这个名字就是上图中蓝⾊⽅框中endpoint的name
sagemaker_session=sm_session,
serializer=csv_serializer,
content_type='text/csv')
# 调⽤predictor的predict⽅法做推理
xgb_predictor.predict(X_valid.values[0]).decode('utf-8')