在本教程中,您将学习如何使用 Amazon SageMaker 构建、训练和调整 TensorFlow 深度学习模型。
Amazon SageMaker 是一项全托管服务,为机器学习 (ML) 开发人员和数据科学家提供快速构建、训练和部署 ML 模型的能力。Amazon SageMaker 为您提供大规模训练和调整模型所需的一切资源,而无需管理基础设施。使用首个用于机器学习的集成开发环境 (IDE),即 Amazon SageMaker Studio,可以将实验快速可视化并跟踪训练进度,而无需离开熟悉的 Jupyter 笔记本界面。在 Amazon SageMaker Studio 中,您可以使用 Amazon SageMaker Experiments 轻松跟踪、评估和组织实验。
在本教程中,您将学习如何:
- 设置 Amazon SageMaker Studio
- 使用 Amazon SageMaker Studio 笔记本下载公共数据集,并将其上传到 Amazon S3
- 创建用来跟踪和管理训练作业的 Amazon SageMaker 实验
- 使用 Amazon SageMaker 的点击式训练在全托管的 GPU 实例上运行 TensorFlow 训练作业
- 运行大规模 Amazon SageMaker Automatic Model Tuning 作业以查找最佳的模型超参数,从而提高准确性
- 将训练结果可视化
您将使用 CIFAR-10 数据集来训练 TensorFlow 中的模型,以将图像分为 10 类。此数据集由 60,000 个 32x32 彩色图像组成,这些图像分为 40,000 个用于训练的图像、10,000 个用于验证的图像和 10,000 个用于测试的图像。
关于本教程 | |
---|---|
时间 | 1 小时 |
成本 | 大约 100 美元 |
使用场景 | 机器学习 |
产品 | Amazon SageMaker |
受众 | 开发人员 |
级别 | 中级 |
上次更新时间 | 2021 年 7 月 1 日 |
步骤 2:设置 Amazon SageMaker Studio
通过完成以下步骤来登录 Amazon SageMaker Studio 并设置 Amazon SageMaker Studio 控制面板。
注意:有关详细信息,请参见 Amazon SageMaker 文档中的 Amazon SageMaker Studio 入门。
a. 登录 Amazon SageMaker 控制台。
注意:确保在右上角选择可提供 SageMaker Studio 的 AWS 区域。有关区域列表,请参见登录 Amazon SageMaker Studio。
b. 在 Amazon SageMaker 导航窗格中,选择 Amazon SageMaker Studio。
注意:首次使用 Amazon SageMaker Studio 时,您必须完成 Studio 登录过程。登录时,您可以选择使用 AWS 单点登录 (AWS SSO) 或 AWS 身份与访问管理 (IAM) 作为身份验证方法。如果使用 IAM 身份验证,您可以选择 Quick start(快速入门)或 Standard setup(标准设置)过程。如果您不确定要使用哪个选项,请参见登录 Amazon SageMaker Studio 并向 IT 管理员寻求帮助。为简单起见,本教程使用 Quick start(快速入门)过程。
c. 在 Get started(入门)对话框中,选择 Quick start(快速入门)并指定用户名。
d. 对于 Execution role(执行角色),选择 Create an IAM role(创建 IAM 角色)。在出现的对话框中,选择 Any S3 bucket(任意 S3 存储桶),然后点击 Create role(创建角色)。
Amazon SageMaker 会创建一个具有所需权限的角色并将该角色分配给您的实例。
e. 点击 Submit(提交)。
步骤 3:下载数据集
Amazon SageMaker Studio 笔记本是点击式 Jupyter 笔记本,其中包含构建和测试训练脚本所需的一切资源。SageMaker Studio 还包括实验跟踪和可视化功能,可让您在某个位置轻松管理整个机器学习工作流。
通过完成以下步骤来创建 SageMaker 笔记本、下载数据集、将数据集转换为 TensorFlow 支持的 TFRecord 格式并将数据集上传到 Amazon S3。
注意:有关详细信息,请参见 Amazon SageMaker 文档中的使用 Amazon SageMaker Studio 笔记本。
a. 在 Amazon SageMaker Studio Control Panel(Amazon SageMaker Studio 控制面板)中,选择 Open Studio(打开 Studio)。
b. 在 JupyterLab 中的 File(文件)菜单中,选择 New Launcher(创建启动器)。在 Notebooks and compute resources(笔记本和计算资源)部分中,为 Select a SageMaker image(选择 SageMaker 图像)选择 TensorFlow 1.15 Python 3.6 (optimized for CPU)(TensorFlow 1.15 Python 3.6 (针对 CPU 优化))。然后,对于 Notebook(笔记本),选择 Python 3。
注意:在此步骤中,您将选择用来运行 SageMaker 笔记本的 CPU 实例,SageMaker 笔记本会下载数据集、构建训练脚本、提交 Amazon SageMaker 训练作业并将结果可视化。训练作业本身就是在一个单独的实例类型上运行,您可以指定实例类型(例如在步骤 5 中看到的 GPU 实例)。
c. 复制以下代码块并将其粘贴到代码单元格中,然后选择 Run(运行)。
此代码下载 generate_cifar10_tfrecords.py 脚本,下载 CIFAR-10 数据集,然后将该数据集转换为 TFRecord 格式。
注意:此代码运行时,方括号之间会出现一个特殊符号 (*)。此代码将在几秒后执行完毕,该符号 (*) 会替换成某个数字。
https://github.com/aws/amazon-sagemaker-examples/blob/master/advanced_functionality/tensorflow_bring_your_own/utils/generate_cifar10_tfrecords.py
复制以下代码并将其粘贴到代码单元格中,然后选择 Run(运行)。
!pip install ipywidgets
!python generate_cifar10_tfrecords.py --data-dir cifar10
d. 将该数据集上传到默认的 Amazon SageMaker Amazon S3 存储桶。复制以下代码并将其粘贴到代码单元格中,然后选择 Run(运行)。
您应当会看到输出结果是该数据集的 Amazon S3 位置。
import time, os, sys
import sagemaker, boto3
import numpy as np
import pandas as pd
sess = boto3.Session()
sm = sess.client('sagemaker')
role = sagemaker.get_execution_role()
sagemaker_session = sagemaker.Session(boto_session=sess)
datasets = sagemaker_session.upload_data(path='cifar10', key_prefix='datasets/cifar10-dataset')
datasets
步骤 4:创建一个 Amazon SageMaker 实验
现在您已下载数据集并将其暂存在 Amazon S3 中,可以创建 Amazon SageMaker 实验了。实验是与同一机器学习项目相关的处理和训练作业的集合。Amazon SageMaker Experiments 自动为您管理和跟踪所运行的训练。
通过完成以下步骤来创建新实验。
注意:有关详细信息,请参见 Amazon SageMaker 文档中的实验。
a. 在 Jupyter 笔记本中,复制以下代码块并将其粘贴到代码单元格中,然后选择 Run(运行)。
此代码使用 smexperiments python 软件包创建名为 sagemaker-training-experiments 的实验。此软件包会预先安装在 Amazon SageMaker Studio 笔记本上。您可以自定义实验名称和说明。
from smexperiments.experiment import Experiment
from smexperiments.trial import Trial
from smexperiments.trial_component import TrialComponent
training_experiment = Experiment.create(
experiment_name = "sagemaker-training-experiments",
description = "Experiment to track cifar10 training trials",
sagemaker_boto_client=sm)
b. 在左侧工具栏中,选择 Components and registries(组件和注册表)(三角形图标),然后选择 Experiments and trials(实验和试验)。新实验 sagemaker-training-experiments 将出现在列表中。
步骤 5:创建试验和训练脚本
若要训练 CIFAR-10 数据集上的分类器,您需要一个训练脚本。在此步骤中,您将为 TensorFlow 训练作业创建试验和训练脚本。每个试验都是端到端训练作业的一次迭代。除了训练作业之外,试验还可以跟踪预处理作业、后处理作业、数据集和其他元数据。单个实验中可以包括多个试验,这使您可以在 Amazon SageMaker Studio Experiments 窗格中轻松跟踪一段时间内的多次迭代。
通过完成以下步骤来为 TensorFlow 训练作业新建试验和训练脚本。
注意:有关详细信息,请参见 Amazon SageMaker 文档中的将 TensorFlow 与 Amazon SageMaker 结合使用。
a. 在 Jupyter 笔记本中,复制以下代码块并将其粘贴到代码单元格中,然后选择 Run(运行)。
此代码会创建一个新试验并将其与步骤 4 中创建的实验相关联。
single_gpu_trial = Trial.create(
trial_name = 'sagemaker-single-gpu-training',
experiment_name = training_experiment.experiment_name,
sagemaker_boto_client = sm,
)
trial_comp_name = 'single-gpu-training-job'
experiment_config = {"ExperimentName": training_experiment.experiment_name,
"TrialName": single_gpu_trial.trial_name,
"TrialComponentDisplayName": trial_comp_name}
每个试验都是端到端训练作业的一次迭代。除了训练作业之外,试验还可以跟踪预处理作业、后处理作业、数据集和其他元数据。单个实验中可以包括多个试验,这使您可以在 Amazon SageMaker Studio Experiments 窗格中轻松跟踪一段时间内的多次迭代。
b. 在左侧工具栏中,选择 Components and registries(组件和注册表)(三角形图标)。双击 sagemaker-training-experiments 以显示相关试验。新试验 sagemaker-single-gpu-training 将出现在列表中。
c. 在 File(文件)菜单中,选择 New(新建),然后选择 Text File(文本文件)。在代码编辑器中,复制以下 TensorFlow 代码并将其粘贴到新创建的文件中。
该脚本执行 TensorFlow 代码,用于读取 CIFAR-10 数据集并训练 resnet50 模型。
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.callbacks import ModelCheckpoint
from tensorflow.keras.layers import Input, Dense, Flatten
from tensorflow.keras.models import Model, load_model
from tensorflow.keras.optimizers import Adam, SGD
import argparse
import os
import re
import time
HEIGHT = 32
WIDTH = 32
DEPTH = 3
NUM_CLASSES = 10
def single_example_parser(serialized_example):
"""Parses a single tf.Example into image and label tensors."""
# Dimensions of the images in the CIFAR-10 dataset.
# See http://www.cs.toronto.edu/~kriz/cifar.html for a description of the
# input format.
features = tf.io.parse_single_example(
serialized_example,
features={
'image': tf.io.FixedLenFeature([], tf.string),
'label': tf.io.FixedLenFeature([], tf.int64),
})
image = tf.decode_raw(features['image'], tf.uint8)
image.set_shape([DEPTH * HEIGHT * WIDTH])
# Reshape from [depth * height * width] to [depth, height, width].
image = tf.cast(
tf.transpose(tf.reshape(image, [DEPTH, HEIGHT, WIDTH]), [1, 2, 0]),
tf.float32)
label = tf.cast(features['label'], tf.int32)
image = train_preprocess_fn(image)
label = tf.one_hot(label, NUM_CLASSES)
return image, label
def train_preprocess_fn(image):
# Resize the image to add four extra pixels on each side.
image = tf.image.resize_with_crop_or_pad(image, HEIGHT + 8, WIDTH + 8)
# Randomly crop a [HEIGHT, WIDTH] section of the image.
image = tf.image.random_crop(image, [HEIGHT, WIDTH, DEPTH])
# Randomly flip the image horizontally.
image = tf.image.random_flip_left_right(image)
return image
def get_dataset(filenames, batch_size):
"""Read the images and labels from 'filenames'."""
# Repeat infinitely.
dataset = tf.data.TFRecordDataset(filenames).repeat().shuffle(10000)
# Parse records.
dataset = dataset.map(single_example_parser, num_parallel_calls=tf.data.experimental.AUTOTUNE)
# Batch it up.
dataset = dataset.batch(batch_size, drop_remainder=True)
return dataset
def get_model(input_shape, learning_rate, weight_decay, optimizer, momentum):
input_tensor = Input(shape=input_shape)
base_model = keras.applications.resnet50.ResNet50(include_top=False,
weights='imagenet',
input_tensor=input_tensor,
input_shape=input_shape,
classes=None)
x = Flatten()(base_model.output)
predictions = Dense(NUM_CLASSES, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
return model
def main(args):
# Hyper-parameters
epochs = args.epochs
lr = args.learning_rate
batch_size = args.batch_size
momentum = args.momentum
weight_decay = args.weight_decay
optimizer = args.optimizer
# SageMaker options
training_dir = args.training
validation_dir = args.validation
eval_dir = args.eval
train_dataset = get_dataset(training_dir+'/train.tfrecords', batch_size)
val_dataset = get_dataset(validation_dir+'/validation.tfrecords', batch_size)
eval_dataset = get_dataset(eval_dir+'/eval.tfrecords', batch_size)
input_shape = (HEIGHT, WIDTH, DEPTH)
model = get_model(input_shape, lr, weight_decay, optimizer, momentum)
# Optimizer
if optimizer.lower() == 'sgd':
opt = SGD(lr=lr, decay=weight_decay, momentum=momentum)
else:
opt = Adam(lr=lr, decay=weight_decay)
# Compile model
model.compile(optimizer=opt,
loss='categorical_crossentropy',
metrics=['accuracy'])
# Train model
history = model.fit(train_dataset, steps_per_epoch=40000 // batch_size,
validation_data=val_dataset,
validation_steps=10000 // batch_size,
epochs=epochs)
# Evaluate model performance
score = model.evaluate(eval_dataset, steps=10000 // batch_size, verbose=1)
print('Test loss :', score[0])
print('Test accuracy:', score[1])
# Save model to model directory
model.save(f'{os.environ["SM_MODEL_DIR"]}/{time.strftime("%m%d%H%M%S", time.gmtime())}', save_format='tf')
#%%
if __name__ == "__main__":
parser = argparse.ArgumentParser()
# Hyper-parameters
parser.add_argument('--epochs', type=int, default=10)
parser.add_argument('--learning-rate', type=float, default=0.01)
parser.add_argument('--batch-size', type=int, default=128)
parser.add_argument('--weight-decay', type=float, default=2e-4)
parser.add_argument('--momentum', type=float, default='0.9')
parser.add_argument('--optimizer', type=str, default='sgd')
# SageMaker parameters
parser.add_argument('--model_dir', type=str)
parser.add_argument('--training', type=str, default=os.environ['SM_CHANNEL_TRAINING'])
parser.add_argument('--validation', type=str, default=os.environ['SM_CHANNEL_VALIDATION'])
parser.add_argument('--eval', type=str, default=os.environ['SM_CHANNEL_EVAL'])
args = parser.parse_args()
main(args)
d. 在 File(文件)菜单中,选择 Rename File(重命名文件)。在 New Name(新名称)文本框中,复制并粘贴 cifar10-training-sagemaker.py,然后选择 Rename(重命名)。(请确保新扩展名是 .py,而不是 .txt)。然后依次选择 File(文件)和 Save Python File(保存 Python 文件)。
步骤 6:运行 TensorFlow 训练作业并将结果可视化
在此步骤中,您将使用 Amazon SageMaker 运行 TensorFlow 训练作业。使用 Amazon SageMaker 可以轻松训练模型。在您指定数据集在 Amazon S3 中的位置以及训练实例的类型之后,Amazon SageMaker 会为您管理训练基础设施。
通过完成以下步骤来运行 TensorFlow 训练作业并将结果可视化。
注意:有关详细信息,请参见 Amazon SageMaker 文档中的将 TensorFlow 与 Amazon SageMaker 结合使用。
a. 在 Jupyter 笔记本中,复制以下代码块并将其粘贴到代码单元格中,然后选择 Run(运行)。接下来仔细查看代码。
注意:如果出现 ResourceLimitExceeded,请将实例类型更改为 ml.c5.xlarge。
注意:您可以放心忽略任何弃用警告(如 sagemaker.deprecations:train_instance_type has been renamed 已重命名...)。此类警告因版本变更而触发,不会导致任何训练失败。
from sagemaker.tensorflow import TensorFlow
hyperparams={'epochs' : 30,
'learning-rate': 0.01,
'batch-size' : 256,
'weight-decay' : 2e-4,
'momentum' : 0.9,
'optimizer' : 'adam'}
bucket_name = sagemaker_session.default_bucket()
output_path = f's3://{bucket_name}/jobs'
metric_definitions = [{'Name': 'val_acc', 'Regex': 'val_acc: ([0-9\\.]+)'}]
tf_estimator = TensorFlow(entry_point = 'cifar10-training-sagemaker.py',
output_path = f'{output_path}/',
code_location = output_path,
role = role,
train_instance_count = 1,
train_instance_type = 'ml.g4dn.xlarge',
framework_version = '1.15.2',
py_version = 'py3',
script_mode = True,
metric_definitions = metric_definitions,
sagemaker_session = sagemaker_session,
hyperparameters = hyperparams)
job_name=f'tensorflow-single-gpu-{time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())}'
tf_estimator.fit({'training' : datasets,
'validation': datasets,
'eval' : datasets},
job_name = job_name,
experiment_config=experiment_config)
此代码包括三个部分:
- 指定训练作业超参数
- 调用 Amazon SageMaker Estimator 函数并提供训练作业详细信息(如训练脚本的名称、要在其上进行训练的实例类型、框架版本等)
- 调用 fit 函数以启动训练作业
Amazon SageMaker 会自动配置所请求的实例、下载数据集、拉取 TensorFlow 容器、下载训练脚本并开始训练。
在此示例中,您将提交一个 Amazon SageMaker 训练作业,该作业将在 ml.g4dn.xlarge(GPU 实例)上运行。深度学习训练是计算密集型训练,建议使用 GPU 实例以便更快获取结果。
训练完成后,您应当会看到最终的准确性结果、训练时间和可计费时间。
b. 查看训练摘要。在左侧工具栏中,选择 Components and registries(组件和注册表)(三角形图标)。双击 sagemaker-training-experiments 以及 sagemaker-single-gpu-training,然后双击为您的训练作业新创建的 single-gpu-training-job 试验组件。选择 Metrics(指标)。
c. 将结果可视化。依次选择 Charts(图表)和 Add chart(添加图表)。在 Chart Properties(图表属性)窗格中,选择以下选项:
- Chart type(图表类型):Line(线形图)
- X-axis dimension(X 轴维度):Epoch
- Y-axis(Y 轴):val_acc_EVAL_avg
您应当会看到一张显示评估准确性随训练进行而发生变化的趋势图,并以步骤 6a 中的最终准确性结束。
步骤 7:使用 Amazon SageMaker 提供的模型自动调整功能来调整模型
在此步骤中,您将运行 Amazon SageMaker 模型自动调整作业,以找到最佳超参数并提高步骤 6 中获得的训练准确性。若要运行模型调整作业,需要为 Amazon SageMaker 提供超参数范围(而不是固定值),这样 Amazon SageMaker 就可以探查超参数空间并自动为您找到最佳值。
通过完成以下步骤来运行模型自动调整作业。
注意:有关详细信息,请参见 Amazon SageMaker 文档中的执行模型自动调整。
a. 在 Jupyter 笔记本中,复制以下代码块并将其粘贴到代码单元格中,然后选择 Run(运行)。接下来仔细查看代码。
注意:如果出现 ResourceLimitExceeded,请将实例类型更改为 ml.c5.xlarge。
注意:您可以放心忽略任何弃用警告(如 sagemaker.deprecations:train_instance_type 已重命名...)。此类警告因版本变更而触发,不会导致任何训练失败。
from sagemaker.tuner import IntegerParameter, CategoricalParameter, ContinuousParameter, HyperparameterTuner
hyperparameter_ranges = {
'epochs' : IntegerParameter(5, 30),
'learning-rate' : ContinuousParameter(0.001, 0.1, scaling_type='Logarithmic'),
'batch-size' : CategoricalParameter(['128', '256', '512']),
'momentum' : ContinuousParameter(0.9, 0.99),
'optimizer' : CategoricalParameter(['sgd', 'adam'])
}
objective_metric_name = 'val_acc'
objective_type = 'Maximize'
metric_definitions = [{'Name': 'val_acc', 'Regex': 'val_acc: ([0-9\\.]+)'}]
tf_estimator = TensorFlow(entry_point = 'cifar10-training-sagemaker.py',
output_path = f'{output_path}/',
code_location = output_path,
role = role,
train_instance_count = 1,
train_instance_type = 'ml.g4dn.xlarge',
framework_version = '1.15',
py_version = 'py3',
script_mode = True,
metric_definitions = metric_definitions,
sagemaker_session = sagemaker_session)
tuner = HyperparameterTuner(estimator = tf_estimator,
objective_metric_name = objective_metric_name,
hyperparameter_ranges = hyperparameter_ranges,
metric_definitions = metric_definitions,
max_jobs = 16,
max_parallel_jobs = 8,
objective_type = objective_type)
job_name=f'tf-hpo-{time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())}'
tuner.fit({'training' : datasets,
'validation': datasets,
'eval' : datasets},
job_name = job_name)
此代码包括四个部分:
- 指定超参数值的范围。该范围可以是整数范围(如迭代次数)、连续范围(如学习率)或分类值(如优化器类型 sgd 或 adam)。
- 调用与步骤 6 中相似的 Estimator 函数
- 创建一个 HyperparameterTuner 对象,该对象具有超参数范围、最大作业数以及要运行的并行作业数
- 调用 fit 函数以启动超参数调整作业
注意:您可以将 max_jobs 变量从 16 改为更小的值以节省作业调整成本。但是,调整作业数越少,找到更好模型的概率越小。您还可以将 max_parallel_jobs 变量减小到不大于 max_jobs 的值。当 max_parallel_jobs 等于 max_jobs 时,您可以更快地获取结果。请确保 max_parallel_jobs 小于 AWS 账户的实例限值,以免遇到资源错误。
b. 查看最佳超参数。打开 Amazon SageMaker 控制台,然后在左侧导航窗格中的 Training(训练)下面,选择 Hyperparameter tuning jobs(超参数调整作业)。在显示的页面中,选择所需调整作业,然后选择 Best training job(最佳训练作业)。您将看到训练准确性 (80%) 比步骤 6 中的结果 (60%) 有所提高。
注意:您的结果可能有所不同。可以通过增加 max_jobs、放宽超参数范围并探查其他模型架构来进一步改进结果。
步骤 8:清除
在此步骤中,您将终止本实验中使用的资源。
重要说明:终止当前未使用的资源可降低成本,这是一种最佳做法。如果不终止资源,则系统会继续从您的账户中扣费。
停止训练作业:
- 打开 Amazon SageMaker 控制台。
- 在左侧导航窗格的 Training(训练)下面,选择 Training Jobs(训练作业)。
- 确认没有状态为 In Progress(进行中)的训练作业。对于任何正在进行中的训练作业,您可以等待其完成训练,也可以选择训练作业名称并点击 Stop(停止)。
(可选)清除所有训练构件:若要清除所有训练构件(如模型、预处理的数据集等),请在 Jupyter 笔记本中,复制并粘贴以下代码,然后选择 Run(运行)。
注意:请确保将 ACCOUNT_NUMBER 替换为您的账号。
!aws s3 rm --recursive s3://sagemaker-us-west-2-ACCOUNT_NUMBER/datasets/cifar10-dataset
!aws s3 rm --recursive s3://sagemaker-us-west-2-ACCOUNT_NUMBER/jobs
结论
恭喜您!您已经使用 Amazon SageMaker 创建、训练和调整了 TensorFlow 深度学习模型。
可以通过下面的后续步骤部分继续您的 SageMaker 机器学习之旅。