1. 概览
在本实验中,您将学习如何使用自动打包功能在 Vertex AI Training 上运行自定义训练作业。Vertex AI 上的自定义训练作业使用容器。如果您不想构建自己的映像,可以使用自动打包功能,该功能会根据您的代码构建自定义 Docker 映像,将该映像推送到 Container Registry,并根据该映像启动 CustomJob。
学习内容
您将学习如何:
在 Google Cloud 上运行此实验的总费用约为 2 美元 。
2. 用例概览
您将使用 Hugging Face 中的库在 IMDB 数据集 上微调 Bert 模型。该模型将预测电影评论是正面还是负面。数据集将从 Hugging Face 数据集库 下载,Bert 模型将从 Hugging Face Transformers 库 下载。
3. Vertex AI 简介
本实验使用的是 Google Cloud 上提供的最新 AI 产品。Vertex AI 将整个 Google Cloud 的机器学习产品集成到无缝的开发体验中。以前,使用 AutoML 训练的模型和自定义模型是通过不同的服务访问的。现在,该新产品与其他新产品一起将这两种模型合并到一个 API 中。您还可以将现有项目迁移到 Vertex AI。如果您有任何反馈,请参阅支持页面。
Vertex AI 包含许多不同的产品,可支持端到端机器学习工作流。本实验将重点介绍 Training 和 Workbench。

4. 设置您的环境
您需要一个启用了结算功能的 Google Cloud Platform 项目才能运行此 Codelab。如需创建项目,请按照此处的说明操作。
第 1 步:启用 Compute Engine API
前往 Compute Engine,然后选择 启用 (如果尚未启用)。
第 2 步:启用 Vertex AI API
前往 Cloud Console 的 Vertex AI 部分,然后点击 启用 Vertex AI API。

第 3 步:启用 Container Registry API
前往 Container Registry,然后选择 启用 (如果尚未启用)。您将使用此产品为您的自定义训练作业创建容器。
第 4 步:创建 Vertex AI Workbench 实例
在 Cloud Console 的 Vertex AI 部分中,点击“Workbench”:

然后点击代管式笔记本:

然后选择新建笔记本。

为您的笔记本命名,然后点击高级设置。

在“高级设置”下,启用空闲关闭,并将分钟数设置为 60。这意味着,您的笔记本处于未使用状态时会自动关闭,以免产生不必要的费用。

您可以保留所有其他高级设置。
接下来,点击创建 。
创建实例后,选择打开 JupyterLab 。

首次使用新实例时,系统会要求您进行身份验证。

5. 编写训练代码
首先,通过“启动器”菜单在笔记本实例中打开终端窗口:

创建一个名为 autopkg-codelab 的新目录并通过 cd 命令进入该目录。
mkdir autopkg-codelab
cd autopkg-codelab
在终端中,运行以下命令来为训练代码创建一个目录,并创建一个 Python 文件,您将在其中添加代码:
mkdir trainer
touch trainer/task.py
您的 autopkg-codelab/ 目录中现在应包含以下内容:
+ trainer/
+ task.py
接下来,打开刚刚创建的 task.py 文件,然后复制以下代码。
import argparse
import tensorflow as tf
from datasets import load_dataset
from transformers import AutoTokenizer
from transformers import TFAutoModelForSequenceClassification
CHECKPOINT = "bert-base-cased"
def get_args():
'''Parses args.'''
parser = argparse.ArgumentParser()
parser.add_argument(
'--epochs',
required=False,
default=3,
type=int,
help='number of epochs')
parser.add_argument(
'--job_dir',
required=True,
type=str,
help='bucket to store saved model, include gs://')
args = parser.parse_args()
return args
def create_datasets():
'''Creates a tf.data.Dataset for train and evaluation.'''
raw_datasets = load_dataset('imdb')
tokenizer = AutoTokenizer.from_pretrained(CHECKPOINT)
tokenized_datasets = raw_datasets.map((lambda examples: tokenize_function(examples, tokenizer)), batched=True)
# To speed up training, we use only a portion of the data.
# Use full_train_dataset and full_eval_dataset if you want to train on all the data.
small_train_dataset = tokenized_datasets['train'].shuffle(seed=42).select(range(1000))
small_eval_dataset = tokenized_datasets['test'].shuffle(seed=42).select(range(1000))
full_train_dataset = tokenized_datasets['train']
full_eval_dataset = tokenized_datasets['test']
tf_train_dataset = small_train_dataset.remove_columns(['text']).with_format("tensorflow")
tf_eval_dataset = small_eval_dataset.remove_columns(['text']).with_format("tensorflow")
train_features = {x: tf_train_dataset[x] for x in tokenizer.model_input_names}
train_tf_dataset = tf.data.Dataset.from_tensor_slices((train_features, tf_train_dataset["label"]))
train_tf_dataset = train_tf_dataset.shuffle(len(tf_train_dataset)).batch(8)
eval_features = {x: tf_eval_dataset[x] for x in tokenizer.model_input_names}
eval_tf_dataset = tf.data.Dataset.from_tensor_slices((eval_features, tf_eval_dataset["label"]))
eval_tf_dataset = eval_tf_dataset.batch(8)
return train_tf_dataset, eval_tf_dataset
def tokenize_function(examples, tokenizer):
'''Tokenizes text examples.'''
return tokenizer(examples['text'], padding='max_length', truncation=True)
def main():
args = get_args()
train_tf_dataset, eval_tf_dataset = create_datasets()
model = TFAutoModelForSequenceClassification.from_pretrained(CHECKPOINT, num_labels=2)
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=tf.metrics.SparseCategoricalAccuracy(),
)
model.fit(train_tf_dataset, validation_data=eval_tf_dataset, epochs=args.epochs)
model.save(f'{args.job_dir}/model_output')
if __name__ == "__main__":
main()
关于此代码,有几点需要注意:
CHECKPOINT是我们要微调的模型。在本例中,我们使用 Bert。TFAutoModelForSequenceClassification方法将在 TensorFlow 中加载指定的语言模型架构 + 权重,并在顶部添加一个具有随机初始化的权重的分类头。在本例中,我们有一个二元分类问题(正面或负面),因此我们为此分类器指定了num_labels=2。
6. 在本地容器化和运行训练代码
您可以使用 gcloud ai custom-jobs local-run 命令根据训练代码构建 Docker 容器映像,并在本地机器上以容器的形式运行该映像。在本地运行容器采用与在 Vertex AI Training 上运行容器类似的方式执行训练代码,有助于在对 Vertex AI 执行自定义训练之前调试代码存在的问题。
在训练作业中,我们将经过训练的模型导出到 Cloud Storage 存储分区。在终端中,运行以下命令为项目定义一个环境变量,务必注意将 your-cloud-project 替换为您的项目 ID:
PROJECT_ID='your-cloud-project'
然后,创建一个存储分区。如果您有现有的存储分区,可以随意使用该存储分区。
BUCKET_NAME="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET_NAME
在 Vertex AI Training 上运行自定义训练作业时,我们将使用 GPU。但由于我们没有为 Workbench 实例指定 GPU,因此我们将使用基于 CPU 的映像进行本地测试。在本示例中,我们使用 Vertex AI Training 预构建容器。
运行以下命令来设置要用作容器基础的 Docker 映像的 URI。
BASE_CPU_IMAGE=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-7:latest
然后,为本地运行命令构建的生成的 Docker 映像设置名称。
OUTPUT_IMAGE=$PROJECT_ID-local-package-cpu:latest
我们的训练代码使用 Hugging Face 数据集和 Transformers 库。这些库不包含在我们选择作为基础映像的映像中,因此我们需要将它们作为要求提供。为此,我们将在 autopkg-codelab 目录中创建一个 requirements.txt 文件。
确保您位于 autopkg-codelab 目录中,然后在终端中输入以下内容。
touch requirements.txt
您的 autopkg-codelab 目录中现在应包含以下内容:
+ requirements.txt
+ trainer/
+ task.py
打开要求文件,然后粘贴以下内容
datasets==1.18.2
transformers==4.16.2
最后,执行 gcloud ai custom-jobs local-run 命令,以在 Workbench 代管式实例上启动训练。
gcloud ai custom-jobs local-run \
--executor-image-uri=$BASE_CPU_IMAGE \
--python-module=trainer.task \
--output-image-uri=$OUTPUT_IMAGE \
-- \
--job_dir=$BUCKET_NAME
您应该会看到 Docker 映像正在构建。我们添加到 requirements.txt 文件中的依赖项将通过 pip 安装。首次执行此命令时,这可能需要几分钟才能完成。构建映像后,task.py 文件将开始运行,您将看到模型训练。您应会看到类似下图的界面:

由于我们未在本地使用 GPU,因此模型训练将需要很长时间。您可以按 Ctrl+c 并取消本地训练,而不是等待作业完成。
请注意,如果您想进行进一步测试,还可以直接运行上面构建的映像,而无需重新打包。
gcloud beta ai custom-jobs local-run \
--executor-image-uri=$OUTPUT_IMAGE \
-- \
--job_dir=$BUCKET_NAME \
--epochs=1
7. 创建自定义作业
现在我们已经测试了本地模式,接下来我们将使用自动打包功能在 Vertex AI Training 上启动自定义训练作业。只需一个命令,此功能即可:
- 根据您的代码构建自定义 Docker 映像。
- 将映像推送到 Container Registry。
- 根据映像启动
CustomJob。
返回到终端,然后 cd 到 autopkg-codelab 目录上一级。
+ autopkg-codelab
+ requirements.txt
+ trainer/
+ task.py
将 Vertex AI Training 预构建 TensorFlow GPU 映像指定为自定义训练作业的基础映像。
BASE_GPU_IMAGE=us-docker.pkg.dev/vertex-ai/training/tf-gpu.2-7:latest
接下来,执行 gcloud ai custom-jobs create 命令。首先,此命令将根据训练代码构建自定义 Docker 映像。基础映像是我们设置为 BASE_GPU_IMAGE 的 Vertex AI Training 预构建容器。然后,自动打包功能将通过 pip 安装数据集和 Transformers 库,如我们的 requirements.txt 文件中所指定。
gcloud ai custom-jobs create \
--region=us-central1 \
--display-name=fine_tune_bert \
--args=--job_dir=$BUCKET_NAME \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,accelerator-type=NVIDIA_TESLA_V100,executor-image-uri=$BASE_GPU_IMAGE,local-package-path=autopkg-codelab,python-module=trainer.task
我们来看看 worker-pool-spec 实参。此实参定义了自定义作业使用的工作器池配置。您可以指定多个工作器池规范,以便创建具有多个工作器池的自定义作业以进行分布式训练。在本示例中,我们仅指定一个工作器池,因为我们的训练代码未配置为进行分布式训练。
以下是此规范的一些关键字段:
machine-type(必需):机器的类型。点击此处查看受支持的类型。replica-count:此工作器池要使用的工作器副本数,默认值为 1。accelerator-type:GPU 的类型。点击此处查看受支持的类型。在本示例中,我们指定了一个 NVIDIA Tesla V100 GPU。accelerator-count:工作器池中每个虚拟机要使用的 GPU 数量,默认值为 1。executor-image-uri:将运行所提供软件包的容器映像的 URI。此值设置为我们的基础映像。local-package-path:包含训练代码的文件夹的本地路径。python-module:要在所提供软件包中运行的 Python 模块名称。
与运行本地命令时类似,您将看到 Docker 映像正在构建,然后训练作业启动。不同的是,您不会看到训练作业的输出,而是会看到以下消息,确认您的训练作业已启动。请注意,首次运行 custom-jobs create 命令时,映像可能需要几分钟才能构建和推送。

返回到 Cloud 控制台的 Vertex AI Training 部分,在自定义作业 下,您应该会看到作业正在运行。

该作业大约需要 20 分钟才能完成。
完成后,您应该会在存储分区的 model_output 目录中看到以下已保存的模型工件。

🎉 恭喜!🎉
您学习了如何使用 Vertex AI 执行以下操作:
- 在本地容器化和运行训练代码
- 使用自动打包功能将训练作业提交到 Vertex AI Training
如需详细了解 Vertex AI 的不同部分,请参阅相关文档。
8. 清理
因为我们将笔记本配置为在空闲 60 分钟后超时,所以不必担心关停实例。如果您要手动关停实例,请点击控制台的 Vertex AI Workbench 部分中的“停止”按钮。如果您想完全删除该笔记本,请点击“删除”按钮。

如需删除存储桶,请使用 Cloud Console 中的导航菜单,浏览到“存储空间”,选择您的存储桶,然后点击“删除”:
