在 Cloud TPU 上训练 EfficientNet

EfficientNet 模型是一系列图像分类模型,可实现领先的准确率,同时比其他模型更小巧、更快速。EfficientNet-EdgeTpu 模型经过定制,可在 Google EdgeTPU 设备上高效运行。

本教程中的模型基于《EfficientNet:重新思考卷积神经网络的模型扩缩》。 研究人员开发了一种新技术来提高模型性能:使用一个简单而高效的复合系数仔细平衡网络深度、宽度与分辨率。

efficientnet-b0efficientnet-b7 的模型系列可在 Google EdgeTPU 设备资源受限的情况下实现良好的图片分类准确率。

本教程中使用的 efficientnet-b0 模型对应最小的基本模型,而 efficientnet-b7 对应最强大、但需要大量计算的模型。本教程演示如何使用 TPUEstimator 训练模型。

目标

  • 创建 Cloud Storage 存储分区以保存数据集和模型输出。
  • 准备测试版 ImageNet 数据集,该数据集又称为 fake_imagenet 数据集。
  • 运行训练作业。
  • 验证输出结果。

费用

本教程使用 Google Cloud 的以下收费组件:

  • Compute Engine
  • Cloud TPU
  • Cloud Storage

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

准备工作

在开始学习本教程之前,请检查您的 Google Cloud 项目是否已正确设置。

  1. 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  5. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  6. 本演示使用 Google Cloud 的收费组件。请查看 Cloud TPU 价格页面估算您的费用。请务必在使用完您创建的资源以后清理这些资源,以免产生不必要的费用。

设置资源

本部分介绍如何为教程设置 Cloud Storage、虚拟机和 Cloud TPU 资源。

  1. 打开一个 Cloud Shell 窗口。

    打开 Cloud Shell

  2. 为项目 ID 创建一个变量。

    export PROJECT_ID=project-id
    
  3. 配置 gcloud 命令行工具,以使用要在其中创建 Cloud TPU 的项目。

    gcloud config set project ${PROJECT_ID}
    

    当您第一次在新的 Cloud Shell 虚拟机中运行此命令时,系统会显示 Authorize Cloud Shell 页面。点击页面底部的 Authorize 以允许 gcloud 使用您的凭据进行 GCP API 调用。

  4. 为 Cloud TPU 项目创建服务帐号。

    gcloud beta services identity create --service tpu.googleapis.com --project $PROJECT_ID
    

    该命令将返回以下格式的 Cloud TPU 服务帐号:

    service-PROJECT_NUMBER@cloud-tpu.iam.gserviceaccount.com
    

  5. 使用以下命令创建 Cloud Storage 存储分区:

    gsutil mb -p ${PROJECT_ID} -c standard -l europe-west4 -b on gs://bucket-name
    

    此 Cloud Storage 存储分区存储您用于训练模型的数据和训练结果。本教程中使用的 gcloud compute tpus execution-groups 命令会为 Cloud TPU 服务帐号设置默认权限。如果您需要更精细的权限,请查看访问级层权限

    存储分区位置必须与虚拟机 (VM) 和 TPU 节点位于同一区域。虚拟机和 TPU 节点位于特定地区,即区域内的细分。

  6. 使用 gcloud compute tpus execution-groups 命令启动本教程所需的 Compute Engine 和 Cloud TPU 资源。

    gcloud compute tpus execution-groups create \
     --vm-only \
     --name=efficientnet-tutorial \
     --zone=europe-west4-a \
     --disk-size=300 \
     --machine-type=n1-standard-8 \
     --tf-version=1.15.5
    

    命令标志说明

    vm-only
    仅创建 Compute Engine 虚拟机,不创建 Cloud TPU。
    name
    要创建的 Cloud TPU 的名称。
    zone
    拟在其中创建 Cloud TPU 的区域
    disk-size
    gcloud 命令创建的虚拟机的硬盘大小(以 GB 为单位)。
    machine-type
    要创建的 Compute Engine 虚拟机的机器类型
    tf-version
    在虚拟机上安装的 Tensorflow gcloud 的版本。

    如需详细了解 gcloud 命令,请参阅 gcloud 参考文档

  7. 在出现提示时,按 y 创建 Cloud TPU 资源。

    gcloud compute tpus execution-groups 命令执行完毕后,验证 shell 提示符已从 username@projectname 更改为 username@vm-name。此变化表明您现已登录 Compute Engine 虚拟机。

    gcloud compute ssh efficientnet-tutorial --zone=europe-west4-a
    

    从现在开始,前缀 (vm)$ 表示您应该在 Compute Engine 虚拟机实例上运行该命令。

准备数据

设置以下环境变量,其中将 bucket-name 替换为 Cloud Storage 存储分区的名称:

  1. 为存储分区名称创建环境变量。将 bucket-name 替换为您的存储分区名称。

    (vm)$ export STORAGE_BUCKET=gs://bucket-name
    
  2. 创建一些其他环境变量。

    (vm)$ export MODEL_DIR=${STORAGE_BUCKET}/efficientnet
    (vm)$ export DATA_DIR=gs://cloud-tpu-test-datasets/fake_imagenet
    (vm)$ export TPU_NAME=efficientnet-tutorial
    (vm)$ export PYTHONPATH=$PYTHONPATH:/usr/share/tpu/models
    

训练应用应该能够访问 Cloud Storage 中的训练数据。在训练期间,训练应用还会使用您的 Cloud Storage 存储分区来存储检查点。

使用 fake_imagenet 来训练和评估 EfficientNet 模型

ImageNet 是一个图像数据库。数据库中的图片被整理为一个层次结构,该层次结构中的每个节点由成百上千个图片进行描述。

本教程使用演示版的完整 ImageNet 数据集,该数据集又称为 fake_imagenet。此演示版本可用于测试教程,同时降低通常与使用完整 ImageNet 数据库运行模型相关的存储和时间要求。

此 fake_imagenet 数据集位于 Cloud Storage 上的以下位置:

gs://cloud-tpu-test-datasets/fake_imagenet

此 fake_imagenet 数据集仅用于了解如何使用 Cloud TPU 并验证端到端性能。准确率数字和保存的模型并无实际意义。

如需了解如何下载和处理完整 ImageNet 数据集,请参阅下载、预处理和上传 ImageNet 数据集

  1. 启动 Cloud TPU 资源。

    (vm)$ gcloud compute tpus execution-groups create \
     --tpu-only \
     --name=efficientnet-tutorial \
     --zone=europe-west4-a \
     --disk-size=300 \
     --machine-type=n1-standard-8 \
     --tf-version=1.15.5
    

    命令标志说明

    tpu-only
    仅创建 Cloud TPU,不创建 Compute Engine。
    name
    要创建的 Cloud TPU 的名称。
    zone
    拟在其中创建 Cloud TPU 的区域
    disk-size
    gcloud 命令创建的虚拟机的硬盘大小(以 GB 为单位)。
    machine-type
    要创建的 Compute Engine 虚拟机的机器类型
    tf-version
    在虚拟机上安装的 Tensorflow gcloud 的版本。
  2. 导航到模型目录:

    (vm)$ cd /usr/share/tpu/models/official/efficientnet/
    
  3. 运行训练脚本。

    (vm)$ python3 main.py \
      --tpu=${TPU_NAME} \
      --data_dir=${DATA_DIR} \
      --model_dir=${MODEL_DIR} \
      --model_name='efficientnet-b0' \
      --skip_host_call=true \
      --train_batch_size=2048 \
      --train_steps=1000
    

    命令标志说明

    tpu
    使用 TPU_NAME 变量中指定的名称。
    data_dir
    用于指定训练输入的 Cloud Storage 路径。在此示例中,该路径设置为 fake_imagenet 数据集。
    model_dir
    在模型训练期间存储检查点和总结的 Cloud Storage 路径。您可以重复使用现有的文件夹来加载之前生成的检查点和存储其他检查点,只要先前的检查点是使用相同大小的 Cloud TPU 和相同 Tensorflow 版本创建的即可。
    model_name
    要训练的模型的名称。例如 efficientnet
    skip_host_call
    设置为 true 可指示脚本跳过每个训练步骤中执行的 host_call。这通常用于生成训练总结(训练损失、学习速率等)。如果为 skip_host_call=false,则在 host_call 函数运行缓慢且无法跟上 TPU 端计算的情况下,性能可能会降低。
    train_batch_size
    训练批次大小。
    train_steps
    用于训练的步骤数。 默认值为 218949 步,约为 350 个周期,批次大小为 2048。此标志应根据 train_batch_size 标志值进行调整。

这会对 EfficientNet 模型(efficientnet-b0 变体)仅训练 1000 步,因为它使用虚构的 ImageNet 数据集。使用完整的 ImageNet 数据集进行训练时,您可以使用以下命令训练到收敛:

(vm)$ python3 main.py \
  --tpu=${TPU_NAME} \
  --data_dir=${DATA_DIR} \
  --model_dir=${MODEL_DIR} \
  --model_name='efficientnet-b0' \
  --skip_host_call=true \
  --train_batch_size=2048 \
  --train_steps=218948

这会将 EfficientNet 模型训练 350 个周期,并且要在处理一批数据之后进行评估。使用指定的标志,该模型应该会在大约 23 小时内完成训练。这些设置应该可以针对 ImageNet 验证数据集实现约 76.5% 的 top-1 准确率。最佳模型检查点和相应的评估结果位于模型目录中的 archive 文件夹中:${STORAGE_BUCKET}/efficientnet/archive

使用 Cloud TPU Pod 扩缩模型

您可以使用 Cloud TPU Pod 扩缩模型,以便更快获得结果。这一完全受支持的模型可与以下 Pod 切片配合使用:

  • v2-32
  • v3-32

使用 Cloud TPU Pod 时,首先使用 Pod 训练模型,然后使用单台 Cloud TPU 设备评估模型。

使用 Cloud TPU Pod 进行训练

  1. 删除为在单台设备上训练模型而创建的 Cloud TPU 资源。

    (vm)$ gcloud compute tpus execution-groups delete efficientnet-tutorial \
      --zone=europe-west4-a \
      --tpu-only
    
  2. 运行 gcloud compute tpus execution-groups 命令,并使用 accelerator-type 参数指定要使用的 Pod 切片。例如,以下命令使用 v3-32 Pod 切片。

    (vm)$ gcloud compute tpus execution-groups  create --tpu-only \
      --name=efficientnet-tutorial \
      --zone=europe-west4-a \
      --accelerator-type=v2-32 \
      --tf-version=1.15.5
    

    命令标志说明

    tpu-only
    仅创建 Cloud TPU。默认情况下,gcloud 命令会同时创建虚拟机和 Cloud TPU。
    name
    要创建的 Cloud TPU 的名称。
    zone
    拟在其中创建 Cloud TPU 的区域
    accelerator-type
    要创建的 Cloud TPU 的类型
    tf-version
    在虚拟机上安装的 Tensorflow gcloud compute tpus execution-groups 的版本。
  3. 为 TPU 名称创建环境变量。

    (vm)$ export TPU_NAME=efficientnet-tutorial
    
  4. 更新 MODEL_DIR 目录以存储训练数据。

    (vm)$ export MODEL_DIR=${STORAGE_BUCKET}/efficientnet-tutorial
    
  5. 训练模型。

    (vm)$ python3 main.py \
      --tpu=${TPU_NAME} \
      --data_dir=${DATA_DIR} \
      --model_dir=${MODEL_DIR} \
      --model_name='efficientnet-b3' \
      --skip_host_call=true \
      --mode=train \
      --train_steps=1000 \
      --train_batch_size=4096 \
      --iterations_per_loop=100
    

    命令标志说明

    tpu
    Cloud TPU 的名称。
    data_dir
    训练输入的 Cloud Storage 路径。在此示例中,该路径设置为 fake_imagenet 数据集。
    model_dir
    在模型训练期间存储检查点和总结的 Cloud Storage 路径。您可以重复使用现有的文件夹来加载之前生成的检查点和存储其他检查点,只要先前的检查点是使用相同大小的 Cloud TPU 和相同 Tensorflow 版本创建的即可。
    model_name
    要训练的模型的名称。
    skip_host_call
    设置为 true 可指示脚本跳过每个训练步骤中执行的 host_call。这通常用于生成训练总结(训练损失、学习速率等)。如果为 skip_host_call=false,则在 host_call 函数运行缓慢且无法跟上 TPU 端计算的情况下,性能可能会降低。
    mode
    train_and_evaltraineval 之一。train_and_eval 用于训练和评估模型。train 用于训练模型。eval 用于评估模型。
    train_steps
    指定训练步数。
    train_batch_size
    训练批次大小。
    iterations_per_loop
    在将指标发送到 CPU 之前要在 TPU 上运行的训练步数。

此命令会对 EfficientNet 模型(efficientnet-b0 变体)仅训练 1000 步,因为它使用虚构的 ImageNet 数据集。使用完整的 ImageNet 数据集进行训练时,您可以使用以下命令训练到收敛:

(vm)$ python3 main.py \
  --tpu=${TPU_NAME} \
  --data_dir=${DATA_DIR} \
  --model_dir=${MODEL_DIR} \
  --model_name='efficientnet-b3' \
  --skip_host_call=true \
  --mode=train \
  --train_steps=109474 \
  --train_batch_size=4096 \
  --iterations_per_loop=100

此命令会为 EfficientNet 模型(efficientnet-b3 变体)训练 350 个周期。该模型应该可以针对 ImageNet 开发数据集实现 81.1% 的准确率,训练完成时间约为 20 小时。最佳模型检查点和相应的评估结果位于模型目录中的 archive 文件夹中:${STORAGE_BUCKET}/efficientnet/archive

评估模型

在这组步骤中,您将使用 Cloud TPU 针对 fake_imagenet 验证数据评估上述经过训练的模型。

  1. 删除您为在 Pod 上训练模型而创建的 Cloud TPU 资源。

    (vm)$ gcloud compute tpus execution-groups delete efficientnet-tutorial \
      --tpu-only \
      --zone=europe-west4-a
      
  2. 启动 v2-8 Cloud TPU 以运行评估。使用与 Compute Engine 虚拟机名称相同的名称,它应该仍在运行。

    (vm)$ gcloud compute tpus execution-groups  create --tpu-only \
     --name=efficientnet-tutorial \
     --accelerator-type=v2-8 \
     --zone=europe-west4-a \
     --tf-version=1.15.5
    

    命令标志说明

    tpu-only
    仅创建 Cloud TPU。默认情况下,gcloud 命令会同时创建虚拟机和 Cloud TPU。
    name
    要创建的 Cloud TPU 的名称。
    accelerator-type
    要创建的 Cloud TPU 的类型
    zone
    拟在其中创建 Cloud TPU 的区域
    tf-version
    在虚拟机上安装的 Tensorflow gcloud 的版本。
  3. 为 TPU 名称创建环境变量。

    (vm)$ export TPU_NAME=efficientnet-tutorial
    
  4. 运行模型评估。这一次,添加 mode 标志并将其设置为 eval

    (vm)$ python3 main.py \
       --tpu=${TPU_NAME} \
       --data_dir=${DATA_DIR} \
       --model_dir=${MODEL_DIR} \
       --model_name='efficientnet-b3' \
       --skip_host_call=true \
       --mode=eval
    

    命令标志说明

    tpu
    使用 TPU_NAME 变量中指定的名称。
    data_dir
    用于指定训练输入的 Cloud Storage 路径。在此示例中,该路径设置为 fake_imagenet 数据集。
    model_dir
    在模型训练期间存储检查点和总结的 Cloud Storage 路径。您可以重复使用现有的文件夹来加载之前生成的检查点和存储其他检查点,只要先前的检查点是使用相同大小的 Cloud TPU 和相同 Tensorflow 版本创建的即可。
    model_name
    要训练的模型的名称。例如,efficientnet 等。
    skip_host_call
    设置为 true 可指示脚本跳过每个训练步骤中执行的 host_call。这通常用于生成训练总结(训练损失、学习速率等)。如果为 skip_host_call=false,则在 host_call 函数运行缓慢且无法跟上 TPU 端计算的情况下,性能可能会降低。
    mode
    设置为 train_and_eval 时,此脚本会训练和评估模型。设置为 export_only 时,此脚本会导出已保存的模型。

    这将生成如下所示的输出:

    Eval results: {
    'loss': 7.532023,
    'top_1_accuracy': 0.0010172526,
    'global_step': 100,
    'top_5_accuracy': 0.005065918
    }
    Elapsed seconds: 88

清除数据

为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

  1. 断开与 Compute Engine 实例的连接(如果您尚未这样做):

    (vm)$ exit
    

    您的提示符现在应为 username@projectname,表明您位于 Cloud Shell 中。

  2. 在您的 Cloud Shell 中,使用以下命令删除您的 Compute Engine 虚拟机和 Cloud TPU:

    $ gcloud compute tpus execution-groups delete efficientnet-tutorial \
      --zone=europe-west4-a
    
  3. 通过运行 gcloud compute tpus execution-groups list 验证资源是否已删除。删除操作可能需要几分钟时间才能完成。如下所示的响应表明实例已成功删除:

    $ gcloud compute tpus execution-groups list \
     --zone=europe-west4-a
    

    您应该会看到如下所示的空白 TPU 列表:

       NAME             STATUS
    
  4. 使用 gsutil 删除 Cloud Storage 存储分区,如下所示。将 bucket-name 替换为您的 Cloud Storage 存储分区的名称。

    $ gsutil rm -r gs://bucket-name
    

后续步骤

TensorFlow Cloud TPU 教程通常使用示例数据集来训练模型。此训练的结果(在大多数情况下)不能用于推断。如需使用模型进行推断,您可以在公开提供的数据集或您自己的数据集上训练数据。在 Cloud TPU 上训练的 TensorFlow 模型通常要求数据集采用 TFRecord 格式。

您可以使用数据集转换工具示例将图片分类数据集转换为 TFRecord 格式。如果您未使用图片分类模型,则必须自行将数据集转换为 TFRecord 格式。如需了解详情,请参阅 TFRecord 和 tf.Example

超参数调节

如需使用数据集提升模型的性能,您可以调节模型的超参数。您可以在 GitHub 上寻找所有 TPU 支持模型通用的超参数的相关信息。您可以在每个模型的源代码中寻找模型专用超参数的相关信息。如需详细了解超参数调节,请参阅超参数调节概览使用超参数调节服务调节超参数

推断

训练模型后,您可以使用该模型进行推断(也称为预测)。AI Platform 是一款基于云的解决方案,用于开发、训练部署机器学习模型。部署模型后,您可以使用 AI Platform Prediction 服务