创建自定义训练作业

自定义训练作业(Vertex AI API 中的 CustomJob 资源)是在 Vertex AI 中运行自定义机器学习 (ML) 训练代码的基本方法。

提交作业之前

在在 Vertex AI 中创建 CustomJob 之前,您必须创建一个 Python 训练应用或自定义容器映像来定义要在 Vertex AI 上运行的训练代码和依赖项。

我们建议您使用本指南后面部分中描述的 Google Cloud CLI 的自动封装功能,从本地计算机上的代码创建 Docker 容器映像,将此容器映像推送到 Container Registry,并创建一个 CustomJob,所有这些用一个命令完成。

否则,您必须手动创建 Python 训练应用自定义容器映像。如需了解详情,请点击本部分第一段中的链接。

如果您不确定选择哪个选项,请参阅训练代码要求了解详情。

自定义作业包含的内容

创建自定义作业时,您需要指定 Vertex AI 运行训练代码所需的设置,包括:

在工作器池中,您可以指定以下设置:

配置分布式训练

您可以通过指定多个工作器池,为分布式训练分布式训练配置 CustomJob

此页面上的大多数示例均为使用一个工作器池的单副本训练作业。要修改它们以进行分布式训练,请执行以下操作:

  • 使用第一个工作器池配置主副本,并将副本计数设置为 1。
  • 添加更多工作器池来配置工作器副本、参数服务器副本或评估器副本(如果您的机器学习框架支持分布式训练的这些额外集群任务)。

详细了解如何使用分布式训练

创建 CustomJob

要创建 CustomJob,请按照以下标签页之一中的说明操作,具体取决于您要使用的工具。如果您使用 gcloud CLI,则可以使用单条命令将本地机器上的训练代码自动打包到 Docker 容器映像中,并将该容器映像推送到 Container Registry,然后创建 CustomJob。其他选项假定您已创建 Python 训练应用或自定义容器映像

gcloud

以下示例使用 gcloud ai custom-jobs create 命令

如果您的训练代码在本地计算机上,我们建议您按照使用自动封装部分进行操作。或者,如果您已创建 Python 训练应用或自定义容器映像,请直接跳到无自动封装部分。

使用自动封装

如果您的本地计算机上有训练代码,则可以使用单个命令执行以下操作:

  • 根据您的代码构建自定义 Docker 映像。
  • 将映像推送到 Container Registry。
  • 根据映像启动 CustomJob

结果类似于使用任何其他自定义容器创建 CustomJob:如果此命令对工作流来说很方便,您可以使用此版本的命令。

准备工作

由于此版本的命令会构建和推送 Docker 映像,因此您必须在本地计算机上执行以下配置:

  1. 安装 Docker Engine。

  2. 如果您使用的是 Linux,请配置 Docker,以便可以在没有 sudo 的情况下运行它

  3. 启用 Container Registry API。

    启用 API

  4. 为 Docker 配置身份验证,以便将 Docker 映像推送到 Container Registry:

    gcloud auth configure-docker
    

构建并推送 Docker 映像,然后创建 CustomJob

以下命令基于预构建的训练容器映像和本地 Python 代码构建 Docker 映像,将该映像推送到 Container Registry,然后创建 CustomJob

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --worker-pool-spec=machine-type=MACHINE_TYPE,replica-count=REPLICA_COUNT,executor-image-uri=EXECUTOR_IMAGE_URI,local-package-path=WORKING_DIRECTORY,script=SCRIPT_PATH

请替换以下内容:

  • LOCATION:将运行容器或 Python 软件包的区域。

  • JOB_NAME:必填。CustomJob 的显示名。

  • MACHINE_TYPE:机器类型。请参阅可用于训练的机器类型

  • REPLICA_COUNT:要使用的工作器副本的数量。在大多数情况下,对于第一个工作器池,请设置为 1

  • EXECUTOR_IMAGE_URI:运行所提供代码的容器映像的 URI。请参阅可用于训练的预构建容器

    此映像充当您使用此命令构建的新 Docker 映像的基础映像。

  • WORKING_DIRECTORY:本地文件系统中的目录,包含运行训练代码的入口点脚本(请参阅以下列表项)。

    您可以使用该脚本的父级目录或更高级别的目录。为了指定完全限定的 Python 模块名称,您可能需要使用更高级别的目录(请参阅下面的列表项)。如果更高级层的目录包含 requirements.txtsetup.py,您可能还需要使用更高级别目录。如需了解详情,请参阅下面的安装依赖项部分。

    请注意即使您指定更高级别的目录,此命令也会将入口点脚本的父目录复制到 Docker 映像。

  • SCRIPT_PATH:相对于本地文件系统上的 WORKING_DIRECTORY 的路径,指向作为训练代码入口点的脚本。该脚本可以是 Python 脚本(以 .py 结尾)或 Bash 脚本。

    例如,如果要运行 /hello-world/trainer/task.pyWORKING_DIRECTORY/hello-world,请使用 trainer/task.py 作为此值。

    使用 python-module,而不要使用 script

    您可以选择将 script=SCRIPT_PATH 替换为 python-module=PYTHON_MODULE,以指定 WORKING_DIRECTORY 中 Python 模块的名称,以作为训练的入口点运行。例如,您可以指定 python-module=trainer.task,而不是 script=trainer/task.py

    在这种情况下,生成的 Docker 容器会将代码作为模块加载而不是加载脚本。如果您的入口点脚本在 WORKING_DIRECTORY 中导入其他 Python 模块,则建议您使用此选项。

安装依赖项

使用自动封装功能时,您可以按照与使用 gcloud CLI 的 local-run 命令相同的方式在容器中安装 Python 依赖项。如需了解安装 Python 依赖项的各种方法,请参阅 local-run 命令指南的安装依赖项部分。

使用自动封装时,指定依赖项的语法与使用 local-run 命令时略有不同。您必须在 --worker-pool-spec 标志的值中使用选项,而不是使用命令行标志来指定依赖项。此外,这些选项中的值必须用分号(而不是逗号)分隔。。具体而言,语法

  • 使用 --worker-pool-spec 标志的值中的 local-package-path 选项,而不是 local-run 命令的 --local-package-path 标志。如果您使用此选项指定的工作目录包含 requirements.txtsetup.py 文件,则自动封装功能会根据此文件安装依赖项。

    上面的示例演示了此语法。

  • (可选)在 --worker-pool-spec 标志的值中使用 requirements 选项,而不是 --requirements 标志。请勿使用逗号分隔 PyPI 依赖项,而是使用分号。

  • (可选)在 --worker-pool-spec 标志的值中使用 extra-packages 选项,而不是 --extra-packages 标志。请勿使用逗号分隔本地依赖项,而是使用分号。

  • (可选)在 --worker-pool-spec 标志的值中使用 extra-dirs 选项,而不是 --extra-dirs 标志。请勿使用逗号分隔目录路径,而是使用分号。

以下示例展示了如何使用所有可选技术安装依赖项。(您可以指定其中的任何子集。)为了演示分号语法,该示例为每个选项指定了两个值。要缩短示例的长度,请将其他 --worker-pool-spec 选项替换为 [...]

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --worker-pool-spec=[...],requirements=PYPI_DEP_1;PYPI_DEP_2,extra-packages=LOCAL_DEP_1;LOCAL_DEP_2,extra-dirs=EXTRA_DIR_1;EXTRA_DIR_2

如需了解这些占位符的适当值,请参阅 local-run 命令指南中的“安装依赖项”。

不自动封装

如果您不使用自动封装,则可以使用类似于以下其中一项的命令创建 CustomJob。根据您是创建 Python 训练应用还是自定义容器映像,选择以下标签页之一:

Python 训练应用

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --python-package-uris=PYTHON_PACKAGE_URIS \
  --worker-pool-spec=machine-type=MACHINE_TYPE,replica-count=REPLICA_COUNT,executor-image-uri=EXECUTOR_IMAGE_URI,python-module=PYTHON_MODULE

替换以下内容:

  • LOCATION:将运行容器或 Python 软件包的区域。
  • JOB_NAME:必填。CustomJob 的显示名。
  • PYTHON_PACKAGE_URIS:以逗号分隔的 Cloud Storage URI 列表,指定作为训练程序的 Python 软件包文件及其从属软件包。软件包 URI 的数量上限为 100。
  • MACHINE_TYPE:机器类型。请参阅可用于训练的机器类型
  • REPLICA_COUNT:要使用的工作器副本的数量。在大多数情况下,对于第一个工作器池,请设置为 1
  • EXECUTOR_IMAGE_URI:运行所提供代码的容器映像的 URI。请参阅可用于训练的预构建容器
  • PYTHON_MODULE:安装软件包后要运行的 Python 模块名称。

自定义容器映像

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --worker-pool-spec=machine-type=MACHINE_TYPE,replica-count=REPLICA_COUNT,container-image-uri=CUSTOM_CONTAINER_IMAGE_URI

替换以下内容:

  • LOCATION:将运行容器或 Python 软件包的区域。
  • JOB_NAME:必填。CustomJob 的显示名。
  • MACHINE_TYPE:机器类型。请参阅可用于训练的机器类型
  • REPLICA_COUNT:要使用的工作器副本的数量。在大多数情况下,对于第一个工作器池,请设置为 1
  • CUSTOM_CONTAINER_IMAGE_URI:要在每个工作器副本上运行的容器映像的 Artifact Registry、Container Registry 或 Docker Hub URI。

分布式训练

要执行分布式训练,请多次指定 --worker-pool-spec 标志,每个工作器池一次。

如果您使用自动封装,则必须仅指定 local-package-pathscript 以及与第一个工作器池中的自动封装相关的其他选项。在后续工作器池中省略与训练代码相关的字段,所有字段都将使用通过自动封装构建的相同训练容器。

例如,以下命令会调整前面的自动封装示例以使用第二个工作器池:

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --worker-pool-spec=machine-type=MACHINE_TYPE,replica-count=REPLICA_COUNT,executor-image-uri=EXECUTOR_IMAGE_URI,local-package-path=WORKING_DIRECTORY,script=SCRIPT_PATH \
  --worker-pool-spec=machine-type=SECOND_POOL_MACHINE_TYPE,replica-count=SECOND_POOL_REPLICA_COUNT

如果您不使用自动封装,请完全独立地指定每个工作器池;请勿省略任何字段。

以下命令调整了之前的示例以使用第二个工作器池:

Python 训练应用

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --python-package-uris=PYTHON_PACKAGE_URIS \
  --worker-pool-spec=machine-type=MACHINE_TYPE,replica-count=REPLICA_COUNT,executor-image-uri=EXECUTOR_IMAGE_URI,python-module=PYTHON_MODULE \
  --worker-pool-spec=machine-type=SECOND_POOL_MACHINE_TYPE,replica-count=SECOND_POOL_REPLICA_COUNT,executor-image-uri=SECOND_POOL_EXECUTOR_IMAGE_URI,python-module=SECOND_POOL_PYTHON_MODULE

自定义容器映像

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --worker-pool-spec=machine-type=MACHINE_TYPE,replica-count=REPLICA_COUNT,container-image-uri=CUSTOM_CONTAINER_IMAGE_URI \
  --worker-pool-spec=machine-type=SECOND_POOL_MACHINE_TYPE,replica-count=SECOND_POOL_REPLICA_COUNT,container-image-uri=SECOND_POOL_CUSTOM_CONTAINER_IMAGE_URI

高级配置

如果您想指定前面示例中未提供的配置选项,则可以使用 --config 标志指定本地环境中的 config.yaml 文件的路径,该文件包含 CustomJobSpec 的字段。例如:

gcloud ai custom-jobs create \
  --region=LOCATION \
  --display-name=JOB_NAME \
  --config=config.yaml

请参阅 config.yaml 文件示例

控制台

在 Google Cloud 控制台中,您无法直接创建 CustomJob 资源。但是,您可以创建一个创建 CustomJobTrainingPipeline 资源。

以下说明介绍了如何创建 TrainingPipeline,用于创建 CustomJob 且不执行其他操作。如果您想要使用其他 TrainingPipeline 功能(例如使用代管式数据集进行训练或在训练结束时创建 Model 资源),请参阅创建训练流水线

  1. 在 Cloud 控制台的 Vertex AI 部分中,转到训练流水线页面。

    转到“训练流水线”

  2. 点击 创建以打开训练新模型窗格。

  3. 训练方法步骤中,指定以下设置:

    1. 数据集下拉列表中,选择无代管式数据集

    2. 选择自定义训练(高级)

    点击继续

  4. 模型详情步骤中,选择训练新模型训练新版本。如果您选择训练新模型,请为模型输入一个名称 MODEL_NAME。点击继续

  5. 训练容器步骤中,指定以下设置:

    1. 选择要使用预构建容器还是自定义容器进行训练。

    2. 根据您的选择,执行以下相应操作:

    3. Model output directory 字段中,您可以指定您有权访问的存储分区中的目录的 Cloud Storage URI。目录不需要已经存在。

      此值会在 baseOutputDirectory API 字段中传递给 Vertex AI,该字段设置训练应用在其运行时可以访问的几个环境变量

    4. 参数字段中,您可以视需要指定 Vertex AI 开始运行训练代码时要使用的参数。这些参数的行为因您使用的容器类型而异:

      • 如果您使用的是预构建容器,Vertex AI 会将参数作为命令行标志传递给 Python 模块

      • 如果您使用的是自定义容器,则 Vertex AI 会使用参数替换容器的 CMD 指令

    点击继续

  6. 超参数调节步骤中,确保未选中启用超参数调节复选框。点击继续

  7. 计算和价格步骤中,指定以下设置:

    1. 区域下拉列表中,选择一个支持自定义训练的区域

    2. 工作器池 0 部分中,指定用于训练的计算资源

      如果指定加速器,请确保所选加速器类型在所选区域可用

      如果您要执行分布式训练,则点击 Add more worker pools,并为您需要的每个额外工作器池指定一组额外的计算资源。

    点击继续

  8. 预测容器步骤中,选择 No prediction container

  9. 点击开始训练以启动自定义训练流水线。

REST 和命令行

在使用任何请求数据之前,请先进行以下替换:

  • LOCATION:将运行容器或 Python 软件包的区域。
  • PROJECT_ID:您的项目 ID 或项目编号。
  • JOB_NAME:必填。CustomJob 的显示名。
  • 定义自定义训练作业:
    • MACHINE_TYPE:机器类型。请参阅可用于训练的机器类型
    • ACCELERATOR_TYPE:(可选)附加到作业的加速器类型。
    • ACCELERATOR_COUNT:(可选)附加到作业的加速器数量。
    • DISK_TYPE:(可选)用于作业的启动磁盘类型:pd-standard(默认)或 pd-ssd详细了解磁盘类型
    • DISK_SIZE:(可选)用于作业的启动磁盘大小(以 GB 为单位)。默认值为 100。
    • REPLICA_COUNT:要使用的工作器副本的数量。在大多数情况下,对于第一个工作器池,请设置为 1
    • 如果训练应用在自定义容器中运行,请指定以下内容:
      • CUSTOM_CONTAINER_IMAGE_URI:要在每个工作器副本上运行的容器映像的 Artifact Registry、Container Registry 或 Docker Hub URI。
      • CUSTOM_CONTAINER_COMMAND:(可选)启动容器时要调用的命令。此命令会替换容器的默认入口点。
      • CUSTOM_CONTAINER_ARGS:(可选)启动容器时要传递的参数。
    • 如果训练应用是在预构建容器中运行的 Python 软件包,请指定以下内容:
      • EXECUTOR_IMAGE_URI:运行所提供代码的容器映像的 URI。请参阅可用于训练的预构建容器
      • PYTHON_PACKAGE_URIS:以逗号分隔的 Cloud Storage URI 列表,指定作为训练程序的 Python 软件包文件及其从属软件包。软件包 URI 的数量上限为 100。
      • PYTHON_MODULE:安装软件包后要运行的 Python 模块名称。
      • PYTHON_PACKAGE_ARGS:(可选)要传递给 Python 模块的命令行参数。
    • 了解作业调度选项
    • TIMEOUT:(可选)作业的最长运行时间。
  • 指定要应用于此自定义作业的任何标签的 LABEL_NAMELABEL_VALUE

HTTP 方法和网址:

POST https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/customJobs

请求 JSON 正文:

{
  "displayName": "JOB_NAME",
  "jobSpec": {
    "workerPoolSpecs": [
      {
        "machineSpec": {
          "machineType": MACHINE_TYPE,
          "acceleratorType": ACCELERATOR_TYPE,
          "acceleratorCount": ACCELERATOR_COUNT
        },
        "replicaCount": REPLICA_COUNT,
        "diskSpec": {
          "bootDiskType": DISK_TYPE,
          "bootDiskSizeGb": DISK_SIZE
        },

        // Union field task can be only one of the following:
        "containerSpec": {
          "imageUri": CUSTOM_CONTAINER_IMAGE_URI,
          "command": [
            CUSTOM_CONTAINER_COMMAND
          ],
          "args": [
            CUSTOM_CONTAINER_ARGS
          ]
        },
        "pythonPackageSpec": {
          "executorImageUri": EXECUTOR_IMAGE_URI,
          "packageUris": [
            PYTHON_PACKAGE_URIS
          ],
          "pythonModule": PYTHON_MODULE,
          "args": [
            PYTHON_PACKAGE_ARGS
          ]
        }
        // End of list of possible types for union field task.
      }
      // Specify one workerPoolSpec for single replica training, or multiple workerPoolSpecs
      // for distributed training.
    ],
    "scheduling": {
      "timeout": TIMEOUT
    }
  },
  "labels": {
    LABEL_NAME_1": LABEL_VALUE_1,
    LABEL_NAME_2": LABEL_VALUE_2
  }
}

如需发送请求,请选择以下方式之一:

curl

将请求正文保存在名为 request.json 的文件中,然后执行以下命令:

curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/customJobs"

PowerShell

将请求正文保存在名为 request.json 的文件中,然后执行以下命令:

$cred = gcloud auth application-default print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/customJobs" | Select-Object -Expand Content

响应包含有关规范的信息以及 TRAININGPIPELINE_ID

Node.js

如需了解如何安装和使用 Vertex AI 客户端库,请参阅 Vertex AI 客户端库。如需了解详情,请参阅 Vertex AI Node.js API 参考文档

/**
 * TODO(developer): Uncomment these variables before running the sample.\
 * (Not necessary if passing values as arguments)
 */

// const customJobDisplayName = 'YOUR_CUSTOM_JOB_DISPLAY_NAME';
// const containerImageUri = 'YOUR_CONTAINER_IMAGE_URI';
// const project = 'YOUR_PROJECT_ID';
// const location = 'YOUR_PROJECT_LOCATION';

// Imports the Google Cloud Job Service Client library
const {JobServiceClient} = require('@google-cloud/aiplatform');

// Specifies the location of the api endpoint
const clientOptions = {
  apiEndpoint: 'us-central1-aiplatform.googleapis.com',
};

// Instantiates a client
const jobServiceClient = new JobServiceClient(clientOptions);

async function createCustomJob() {
  // Configure the parent resource
  const parent = `projects/${project}/locations/${location}`;
  const customJob = {
    displayName: customJobDisplayName,
    jobSpec: {
      workerPoolSpecs: [
        {
          machineSpec: {
            machineType: 'n1-standard-4',
            acceleratorType: 'NVIDIA_TESLA_K80',
            acceleratorCount: 1,
          },
          replicaCount: 1,
          containerSpec: {
            imageUri: containerImageUri,
            command: [],
            args: [],
          },
        },
      ],
    },
  };
  const request = {parent, customJob};

  // Create custom job request
  const [response] = await jobServiceClient.createCustomJob(request);

  console.log('Create custom job response:\n', JSON.stringify(response));
}
createCustomJob();

Python

如需了解如何安装和使用 Vertex AI 客户端库,请参阅 Vertex AI 客户端库。如需了解详情,请参阅 Vertex AI Python API 参考文档

from google.cloud import aiplatform

def create_custom_job_sample(
    project: str,
    display_name: str,
    container_image_uri: str,
    location: str = "us-central1",
    api_endpoint: str = "us-central1-aiplatform.googleapis.com",
):
    # The AI Platform services require regional API endpoints.
    client_options = {"api_endpoint": api_endpoint}
    # Initialize client that will be used to create and send requests.
    # This client only needs to be created once, and can be reused for multiple requests.
    client = aiplatform.gapic.JobServiceClient(client_options=client_options)
    custom_job = {
        "display_name": display_name,
        "job_spec": {
            "worker_pool_specs": [
                {
                    "machine_spec": {
                        "machine_type": "n1-standard-4",
                        "accelerator_type": aiplatform.gapic.AcceleratorType.NVIDIA_TESLA_K80,
                        "accelerator_count": 1,
                    },
                    "replica_count": 1,
                    "container_spec": {
                        "image_uri": container_image_uri,
                        "command": [],
                        "args": [],
                    },
                }
            ]
        },
    }
    parent = f"projects/{project}/locations/{location}"
    response = client.create_custom_job(parent=parent, custom_job=custom_job)
    print("response:", response)

后续步骤

  • 请参阅创建训练流水线,了解如何创建训练流水线以在 Vertex AI 中运行自定义训练应用。