在 Cloud TPU 上运行 Inception

设置为 1 以显示清理块 #}

本教程介绍如何在 Cloud TPU 上训练 Inception 模型。

免责声明

本教程使用第三方数据集。Google 不对此数据集的有效性或任何其他方面提供任何表示、担保或其他保证。

模型说明

Inception v3 是一种广泛使用的图片识别模型,可以实现非常高的准确率。该模型是数年来多位研究人员提出的诸多想法积淀的成果。它以 Szegedy 等人发表的《Rethinking the Inception Architecture for Computer Vision》原创性论文为理论依据。

该模型由对称构件和不对称构件组成,包括:

  • 卷积
  • 平均池化
  • 最大池化
  • concat
  • 丢包
  • 全连接层

损失是通过 Softmax 计算的。

下图概括显示了该模型:

图片

您可以在 GitHub 上详细了解该模型。

该模型是使用高级 Estimator API 构建的。

此 API 通过封装大多数低级函数极大地简化了模型创建,使用户可以专注于模型开发,而非关注负责运行的底层硬件的内部工作。

目标

  • 创建 Cloud Storage 存储分区以保存数据集和模型输出。
  • 运行训练作业。
  • 验证输出结果。

费用

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

  • Compute Engine
  • Cloud TPU
  • Cloud Storage

请使用价格计算器根据您的预计使用情况来估算费用。

Google Cloud 新用户可能有资格申请免费试用

准备工作

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

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册一个新帐号

  2. 在 Cloud Console 的项目选择器页面上,选择或创建 Cloud 项目。

    转到项目选择器页面

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

  4. 本演示使用 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}
    
  4. 使用以下命令创建 Cloud Storage 存储分区。将 bucket-name 替换为存储分区的名称。

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

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

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

  5. 使用 ctpu up 命令启动此教程所需的 Compute Engine 资源。

    ctpu up --zone=us-central1-b \
      --vm-only \
      --machine-type=n1-standard-8 \
      --tf-version=1.15.3 \
      --name=inception-tutorial
    

    如需详细了解 CTPU 实用程序,请参阅 CTPU 参考

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

    ctpu up 命令执行完毕后,验证 shell 提示符已从 username@projectname 更改为 username@vm-name。此变化表明您现已登录 Compute Engine 虚拟机。如果您未连接到 Compute Engine 实例,则可通过运行以下命令进行连接:

    gcloud compute ssh inception-tutorial --zone=us-central1-b
    

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

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

    (vm)$ export STORAGE_BUCKET=gs://bucket-name
    
  8. 为 TPU 名称创建环境变量。

    (vm)$ export TPU_NAME=inception-tutorial

训练数据集

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

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

本教程使用演示版的完整 ImageNet 数据集,该数据集称为“fake_imagenet”数据集。此演示版本可用于测试本教程,节省了下载模型和对完整的 ImageNet 数据库运行模型所需的存储空间或时间。以下是有关使用随机生成的 fake_imagenet 数据集测试该模型的说明。或者,您也可以使用完整的 ImageNet 数据集

下文所述的 DATA_DIR 环境变量用于指定要利用哪个数据集进行训练。

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

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

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

(可选)设置 TensorBoard

TensorBoard 提供了一套工具,可直观地呈现 TensorFlow 数据。当用于监控时,TensorBoard 可以帮助识别处理过程中的瓶颈,并提出改进性能的方法。

如果目前不需要监控模型的输出,则可以跳过 TensorBoard 设置步骤。

如果想要监控模型的输出和性能,请参照设置 TensorBoard 指南。

运行模型

现在您可以使用 ImageNet 数据训练和评估 Inception v3 模型了。

Inception v3 模型已预安装在您的 Compute Engine 虚拟机的 /usr/share/tpu/models/experimental/inception/ 目录中。

在以下步骤中,前缀 (vm)$ 表示您应该在 Compute Engine 虚拟机上运行该命令:

  1. 设置包含下列某个值的 DATA_DIR 环境变量:

    • 如果您使用的是 fake_imagenet 数据集:

      (vm)$ export DATA_DIR=gs://cloud-tpu-test-datasets/fake_imagenet
      
    • 如果您已将一组训练数据上传到您的 Cloud Storage 存储分区:

      (vm)$ export DATA_DIR=${STORAGE_BUCKET}/data
      
  2. 运行 Inception v3 模型:

    (vm)$ python /usr/share/tpu/models/experimental/inception/inception_v3.py \
        --tpu=$TPU_NAME \
        --learning_rate=0.165 \
        --train_steps=250000 \
        --iterations=500 \
        --use_tpu=True \
        --use_data=real \
        --mode=train_and_eval \
        --train_steps_per_eval=2000 \
        --data_dir=${DATA_DIR} \
        --model_dir=${STORAGE_BUCKET}/inception
    • --tpu 用于指定 Cloud TPU 的名称。请注意,ctpu 会将此名称以环境变量 (TPU_NAME) 的形式传递给 Compute Engine 虚拟机。
    • --use_data 用于指定此程序在训练期间必须使用哪种类型的数据(是虚构的还是真实的)。默认值为 fake(虚构数据)。
    • --data_dir 用于指定训练输入的 Cloud Storage 路径。如果您使用的是 fake_imagenet 数据,应用会忽略此参数。
    • --model_dir 用于指定在模型训练期间存储检查点和摘要的目录。如果指定的文件夹不存在,此程序会自行创建。使用 Cloud TPU 时,model_dir 必须是 Cloud Storage 路径 (gs://...)。您可以重复使用现有的文件夹来加载当前检查点数据和存储其他检查点,只要先前的检查点是使用相同大小的 TPU 和 Tensorflow 版本创建的即可。

预期结果

Inception v3 可对 299x299 图片执行操作。默认训练批量大小为 1024,即每次迭代处理其中 1024 个图片。

您可以使用 --mode 标志选择以下三种操作模式之一:train(训练)、eval(评估)和 train_and_eval(训练并评估)。

  • --mode=train--mode=eval 用于指定仅限训练的作业或仅限评估的作业。
  • --mode=train_and_eval 用于指定同时执行训练和评估的混合式作业。

仅限训练的作业会运行 train_steps 中定义的指定步数,并且可以遍历整个训练集(如果需要)。

Train_and_eval 作业会循环执行训练和评估部分。每个训练周期都运行 train_steps_per_eval,然后运行评估作业(使用训练到当时的权重)。

训练周期数的计算方式是对 train_steps/train_steps_per_eval 向下取整(通过 floor 函数实现)。

floor(train_steps / train_steps_per_eval)

默认情况下,基于 Estimator API 的模型会报告每过特定步数的损失值。报告格式如下:

step = 15440, loss = 12.6237

讨论:专门针对 TPU 对模型进行修改

为了使基于 Estimator API 的模型可在 TPU 上运行,仅需进行极少量的修改。此程序会导入以下库:

from google.third_party.tensorflow.contrib.tpu.python.tpu import tpu_config
from google.third_party.tensorflow.contrib.tpu.python.tpu import tpu_estimator
from google.third_party.tensorflow.contrib.tpu.python.tpu import tpu_optimizer

CrossShardOptimizer 函数会封装优化器,如下所示:

if FLAGS.use_tpu:
  optimizer = tpu_optimizer.CrossShardOptimizer(optimizer)

定义该模型的函数会使用以下命令返回 Estimator 规范:

return tpu_estimator.TPUEstimatorSpec(
    mode=mode, loss=loss, train_op=train_op, eval_metrics=eval_metrics)

main 函数使用以下方法定义了 Estimator 兼容配置:

run_config = tpu_config.RunConfig(
    master=tpu_grpc_url,
    evaluation_master=tpu_grpc_url,
    model_dir=FLAGS.model_dir,
    save_checkpoints_secs=FLAGS.save_checkpoints_secs,
    save_summary_steps=FLAGS.save_summary_steps,
    session_config=tf.ConfigProto(
        allow_soft_placement=True,
        log_device_placement=FLAGS.log_device_placement),
    tpu_config=tpu_config.TPUConfig(
        iterations_per_loop=iterations,
        num_shards=FLAGS.num_shards,
        per_host_input_for_training=per_host_input_for_training))

此程序使用此定义的配置和模型定义函数来创建 Estimator 对象:

inception_classifier = tpu_estimator.TPUEstimator(
    model_fn=inception_model_fn,
    use_tpu=FLAGS.use_tpu,
    config=run_config,
    params=params,
    train_batch_size=FLAGS.train_batch_size,
    eval_batch_size=eval_batch_size,
    batch_axis=(batch_axis, 0))

仅限训练的作业只调用 train 函数:

inception_classifier.train(
    input_fn=imagenet_train.input_fn, steps=FLAGS.train_steps)

仅限评估的作业会从可用检查点获取数据,并一直等到有新的检查点可用:

for checkpoint in get_next_checkpoint():
  eval_results = inception_classifier.evaluate(
      input_fn=imagenet_eval.input_fn,
      steps=eval_steps,
      hooks=eval_hooks,
      checkpoint_path=checkpoint)

当您选择选项 train_and_eval 时,训练和评估作业会并行运行。在评估过程中,会从最新的可用检查点加载可训练变量。训练和评估周期按标志中指定的方式重复:

for cycle in range(FLAGS.train_steps // FLAGS.train_steps_per_eval):
  inception_classifier.train(
      input_fn=imagenet_train.input_fn, steps=FLAGS.train_steps_per_eval)

  eval_results = inception_classifier.evaluate(
      input_fn=imagenet_eval.input_fn, steps=eval_steps, hooks=eval_hooks)

如果您使用 fake_imagenet 数据集训练模型,请转到清理部分。

使用完整的 Imagenet 数据集

ImageNet 数据集包括三个部分:训练数据、验证数据和图片标签。

训练数据包含 1000 个类别和 120 万张图片,已打包好以便可以轻松下载。验证数据和测试数据不包含在 ImageNet 训练数据中(重复项已移除)。

验证数据和测试数据由 15 万张照片组成,这些照片是通过 Flickr 和其他搜索引擎收集而来,并标记是否存在 1000 个对象类别。1000 个对象类别同时包含 ImageNet 的内部节点和叶节点,但彼此不重叠。发布了带有标签的 50000 个寻机图片子集作为验证数据,以及包含 1000 个类别的列表。 其余图片用于评估,并已发布且不带标签。

预处理完整的 ImageNet 数据集的步骤

准备完整的 ImageNet 数据集以供机器学习模型使用,这个过程分为五个步骤:

  1. 验证下载目标上是否有空间。
  2. 设置目标目录。
  3. 在 ImageNet 网站上注册并申请下载权限。
  4. 将数据集下载到本地磁盘或 Compute Engine 虚拟机。

  5. 运行预处理并上传脚本。

验证空间要求

无论您是将数据集下载到本地机器还是下载到 Compute Engine 虚拟机,下载目标都需要大约 300GB 的空间。在虚拟机上,您可以使用 df -ha 命令检查可用存储空间。

您可以使用以下任一方法来增加虚拟机磁盘的大小:

  • 使用要分配的大小(以 GB 为单位)在 ctpu up 命令行上指定 --disk-size-gb 标志。
  • 按照 Compute Engine 指南向您的虚拟机添加磁盘
    • 删除实例时设置为删除磁盘,以确保在您移除虚拟机后,相应磁盘也会一并移除。
    • 记下新磁盘的路径,例如:/mnt/disks/mnt-dir

设置目标目录

在本地机器或 Compute Engine 虚拟机上,设置目录结构来存储下载的数据。

  1. 创建并导出 ImageNet 数据集的主目录。

    在本地机器或虚拟机上的主目录下创建一个目录,例如 imagenet。在此目录下,创建两个子目录:trainvalidation。将主目录导出为 IMAGENET_HOME:

    export IMAGENET_HOME=~/imagenet
    

注册并申请下载数据集的权限

  1. Imagenet 网站上注册。注册可能需要一些时间,但注册完成后,请转到下载网站

下载 ImageNet 数据集

  1. 下载网站中,转到页面上的“图片”部分,然后右键点击“训练图片(任务 1 和 2)”。这样,您就能够获取下载训练集的最大部分所需的网址。保存网址。

    右键点击“训练图片(任务 3)”以获取第二个训练集的网址。保存网址。

    右键点击“验证图片(所有任务)”,获取验证数据集的网址。保存网址。

    如果将 ImageNet 文件下载到本地机器,则下载完成后,需要将本地机器上的目录复制到 Compute Engine 虚拟机上的相应 $IMAGENET_HOME 目录。 将 ImageNet 数据集从本地主机复制到虚拟机大约需要 13 个小时。

    例如,运行以下命令以将本地机器上 $IMAGENET_HOME 下的所有文件复制到显示 Shell 提示符 username@vm-name 的虚拟机:

    gcloud compute scp --recurse $IMAGENET_HOME username@vm-name:~/imagenet
    
  2. 在 $IMAGENET_HOME 中,使用 wget 从保存的网址下载训练和验证文件。

    “训练图片(任务 1 和 2)”文件是大型训练集。大小为 138GB,如果您使用 Cloud Shell 将其下载到 Compute Engine 虚拟机,则预计下载时间大约为 40 个小时。对于这种特别大的文件,您可以在命令前面添加 nohup,或使用筛选以避免在 Cloud Shell 断开连接时终止下载。

    cd $IMAGENET_HOME \
    nohup wget http://image-net.org/challenges/LSVRC/2012/dd31405981ef5f776aa17412e1f0c112/ILSVRC2012_img_train.tar
    

    此操作会下载大型 tar 文件:ILSVRC2012_img_train.tar。

    从虚拟机上的 $IMAGENET_HOME 中,使用以下命令将各个训练目录提取到 $IMAGENET_HOME/train 目录中。 提取过程需要 1 到 3 小时。

    tar xf ILSVRC2012_img_train.tar
    

    “训练图片(任务 3)”文件为 728 MB,下载只需几分钟时间,因此您无需采取预防措施以避免中断 Cloud Shell 连接。

    下载此文件时,它会将各个训练目录提取到现有 $IMAGENET_HOME/train 目录中。

    wget http://www.image-net.org/challenges/LSVRC/2012/dd31405981ef5f776aa17412e1f0c112/ILSVRC2012_img_train_t3.tar
    

    “验证图片(所有任务)”文件为 6GB,因此您可能希望使用 nohup筛选来避免在断开 Cloud Shell 连接时终止下载。

    wget http://www.image-net.org/challenges/LSVRC/2012/dd31405981ef5f776aa17412e1f0c112/ILSVRC2012_img_val.tar
    

    此下载过程大约需要 30 分钟。当您下载此文件时,会将各个验证目录提取到 $IMAGENET_HOME/validation 目录中。

    如果已将验证文件下载到本地机器,则需要将本地机器上的 $IMAGENET_HOME/validation 目录复制到 Compute Engine 虚拟机上的 $IMAGENET_HOME/validation 目录。此复制操作大约需要 30 分钟。

    下载标签文件。此过程只需几秒钟时间。

    wget -O $IMAGENET_HOME/synset_labels.txt \
    https://raw.githubusercontent.com/tensorflow/models/master/research/inception/inception/data/imagenet_2012_validation_synset_labels.txt
    

    如果已将标签文件下载到本地机器,则需要将其复制到本地机器上的 $IMAGENET_HOME 目录,然后复制到 Compute Engine 虚拟机上的 $IMAGENET_HOME 目录。此复制操作需要几秒钟的时间。

    训练子目录名称(例如,n03062245)是“WordNet ID”(wnid)。ImageNet APIsynset_labels.txt 文件中显示了 WordNet ID 与其相关联的验证标签之间的映射。此上下文中的同义词集是视觉上类似的一组图片。

处理 Imagenet 数据集,并视情况将其上传到 Cloud Storage

  1. 从 GitHub 下载 imagenet_to_gcs.py 脚本:

    wget https://raw.githubusercontent.com/tensorflow/tpu/master/tools/datasets/imagenet_to_gcs.py
    
  2. 如果要将数据集上传到 Cloud Storage,请指定存储分区位置来上传 ImageNet 数据集:

    export STORAGE_BUCKET=gs://bucket-name
    
  3. 如果要将数据集上传到 Cloud Storage,请指定存储分区目录以保存数据集:

    (vm)$ export DATA_DIR=$STORAGE_BUCKET/dataset-directory
    
  4. 运行脚本,将原始数据集作为 TFRecord 进行预处理,并使用下列命令将其上传到 Cloud Storage:

     python3 imagenet_to_gcs.py \
      --project=$PROJECT \
      --gcs_output_path=$DATA_DIR  \
      --raw_data_dir=$IMAGENET_HOME \
      --local_scratch_dir=$IMAGENET_HOME/tf_records
    

该脚本会生成一组以下形式的目录(用于存储训练和验证数据):

${DATA_DIR}/train-00000-of-01024
${DATA_DIR}/train-00001-of-01024
 ...
${DATA_DIR}/train-01023-of-01024

${DATA_DIR}/validation-00000-of-00128
S{DATA_DIR}/validation-00001-of-00128
 ...
${DATA_DIR}/validation-00127-of-00128

将数据上传到您的 Cloud 存储分区后,请运行模型并设置 --data_dir=${DATA_DIR}

清理

为避免系统因本主题中使用的资源向您的 GCP 帐号收取费用,请执行以下操作:

  1. 与 Compute Engine 虚拟机断开连接:

    (vm)$ exit
    

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

  2. 在您的 Cloud Shell 中,使用您在设置 Cloud TPU 时所用的 --zone 标志运行 ctpu delete,以删除 Compute Engine 虚拟机和 Cloud TPU:

    $ ctpu delete [optional: --zone]
    
  3. 运行 ctpu status 以确保未分配任何实例,避免产生不必要的 TPU 使用费。删除操作可能需要几分钟时间才能完成。 如下所示的响应表明不再有已分配的实例:

    $ ctpu status --zone=europe-west4-a
    
    2018/04/28 16:16:23 WARNING: Setting zone to "--zone=europe-west4-a"
    No instances currently exist.
        Compute Engine VM:     --
        Cloud TPU:             --
    
  4. 如下所示运行 gsutil,将 bucket-name 替换为您为本教程创建的 Cloud Storage 存储分区的名称:

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

Inception v4

Inception v4 模型是一种深度神经网络模型,它使用 Inception v3 构件来实现比 Inception v3 更高的准确率。Szegedy 等人的《Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning》对此进行了介绍。

Inception v4 模型已预安装在您的 Compute Engine 虚拟机的 /usr/share/tpu/models/experimental/inception/ 目录中。

在以下步骤中,前缀 (vm)$ 表示您应该在 Compute Engine 虚拟机上运行该命令:

  1. 如果您已在 Cloud Shell 标签页中运行了 TensorBoard,则需要另打开一个标签页。在 Cloud Shell 中打开另一个标签页,并在新 shell 中使用 ctpu 连接到您的 Compute Engine 虚拟机:

    $ ctpu up
  2. 设置包含下列某个值的 DATA_DIR 环境变量:

    • 如果您使用的是 fake_imagenet 数据集:

      (vm)$ export DATA_DIR=gs://cloud-tpu-test-datasets/fake_imagenet
      
    • 如果您已将一组训练数据上传到您的 Cloud Storage 存储分区:

      (vm)$ export DATA_DIR=${STORAGE_BUCKET}/data
      
  3. 运行 Inception v4 模型:

    (vm)$ python /usr/share/tpu/models/experimental/inception/inception_v4.py \
        --tpu=$TPU_NAME \
        --learning_rate=0.36 \
        --train_steps=1000000 \
        --iterations=500 \
        --use_tpu=True \
        --use_data=real \
        --train_batch_size=256 \
        --mode=train_and_eval \
        --train_steps_per_eval=2000 \
        --data_dir=${DATA_DIR} \
        --model_dir=${STORAGE_BUCKET}/inception
    • --tpu 用于指定 Cloud TPU 的名称。请注意,ctpu 会将此名称以环境变量 (TPU_NAME) 的形式传递给 Compute Engine 虚拟机。
    • --use_data 用于指定此程序在训练期间必须使用哪种类型的数据(是虚构的还是真实的)。默认值为 fake(虚构数据)。
    • --train_batch_size 将训练批量大小指定为 256。由于 Inception v4 模型大于 Inception v3 模型,因此它必须以更小的批量大小在每个 TPU 核心中运行。
    • --data_dir 用于指定训练输入的 Cloud Storage 路径。如果您使用的是 fake_imagenet 数据,应用会忽略此参数。
    • --model_dir 用于指定在模型训练期间存储检查点和摘要的目录。如果指定的文件夹不存在,此程序会自行创建。使用 Cloud TPU 时,model_dir 必须是 Cloud Storage 路径 (gs://...)。您可以重复使用现有的文件夹来加载当前检查点数据和存储其他检查点,只要先前的检查点是使用相同大小的 TPU 和相同 Tensorflow 版本创建的即可。

清理

后续步骤

## 后续步骤 {: #whats-next } 在本教程中,您已使用示例数据集训练 Inception 模型。此训练的结果(在大多数情况下)不能用于推断。要使用模型进行推断,您可以在公开提供的数据集或您自己的数据集上训练数据。在 Cloud TPU 上训练的模型要求数据集采用 TFRecord 格式。

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

超参数调节

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

推理

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