Vertex AI:超參數調整

1. 總覽

在本研究室中,您將使用 Vertex AI 為 TensorFlow 模型執行超參數調整工作。雖然本研究室使用 TensorFlow 編寫模型程式碼,但這些概念也適用於其他機器學習架構。

課程內容

您將學習下列內容:

  • 針對自動化超參數調整修改訓練應用程式程式碼
  • 透過 Vertex AI UI 設定及啟動超參數調整工作
  • 使用 Vertex AI Python SDK 設定及啟動超參數調整工作

在 Google Cloud 中執行這個研究室的總費用約為 $3 美元。

2. Vertex AI 簡介

這個研究室使用 Google Cloud 最新的 AI 產品服務。Vertex AI 將 Google Cloud 中的機器學習產品整合到流暢的開發體驗中。先前使用 AutoML 訓練的模型和自訂模型,都能透過不同的服務存取。這項新產品會與其他新產品一起合併為一個 API。您也可以將現有專案遷移至 Vertex AI。如有任何意見,請參閱支援頁面

Vertex AI 提供許多不同的產品,可支援端對端機器學習工作流程。本研究室將著重介紹下列產品:訓練Workbench

Vertex 產品總覽

3. 設定環境

您需要已啟用計費功能的 Google Cloud Platform 專案,才能執行這個程式碼研究室。如要建立專案,請按照這裡的操作說明進行。

步驟 1:啟用 Compute Engine API

前往「Compute Engine」,並選取「啟用」 (如果尚未啟用)。建立筆記本執行個體時會用到。

步驟 2:啟用 Container Registry API

前往「Container Registry」,然後選取「Enable」(啟用) (如果尚未啟用)。您將使用這個選項為自訂訓練工作建立容器。

步驟 3:啟用 Vertex AI API

前往 Cloud 控制台的 Vertex AI 專區,然後按一下「啟用 Vertex AI API」

Vertex AI 資訊主頁

步驟 4:建立 Vertex AI Workbench 執行個體

在 Cloud 控制台的 Vertex AI 專區中,按一下 Workbench:

Vertex AI 選單

啟用 Notebooks API (如果尚未啟用)。

Notebook_api

啟用後,按一下「代管的筆記本」

Notebooks_UI

然後選取「新增筆記本」

new_notebook

為筆記本命名,然後按一下「進階設定」

create_notebook

在進階設定下方啟用閒置關閉,並將時間長度設為 60。也就是說,您的筆記本在未使用時自動關閉,因此不會產生不必要的費用。

idle_timeout

選取「安全性」下方的「啟用終端機」(如果尚未啟用)。

enable_terminal

其他進階設定皆可保持原樣。

接著點選「建立」。執行個體的佈建作業會在幾分鐘內完成。

執行個體建立完成後,請選取「Open JupyterLab」

open_jupyterlab

首次使用新的執行個體時,系統會要求您進行驗證。請按照 UI 中的步驟操作。

驗證

4. 將訓練應用程式程式碼容器化

在本研究室中,您要訓練及調整的模型是圖片分類模型,由 TensorFlow 資料集中的馬或人工資料集訓練而成。

您必須將訓練應用程式的程式碼放入 Docker 容器,並將這個容器推送至 Google Container Registry,藉此將這個超參數調整工作提交至 Vertex AI。透過這種方法,您可以針對以任何架構建構的模型調整超參數。

如要開始使用,請透過「啟動器」選單開啟筆記本執行個體中的「終端機」視窗:

在筆記本中開啟終端機

建立名為 horses_or_humans 的新目錄,並使用 cd 加入該目錄:

mkdir horses_or_humans
cd horses_or_humans

步驟 1:建立 Dockerfile

將程式碼容器化的第一步,就是建立 Dockerfile。而 Dockerfile 包含執行映像檔所需的所有指令。系統會安裝所有必要的程式庫 (包括 CloudML Hypertune 程式庫),並設定訓練程式碼的進入點。

在終端機中建立空白的 Dockerfile:

touch Dockerfile

開啟 Dockerfile,並將下列內容複製到該檔案中:

FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-7

WORKDIR /

# Installs hypertune library
RUN pip install cloudml-hypertune

# Copies the trainer code to the docker image.
COPY trainer /trainer

# Sets up the entry point to invoke the trainer.
ENTRYPOINT ["python", "-m", "trainer.task"]

這個 Dockerfile 使用深度學習容器 TensorFlow 企業版 2.7 GPU Docker 映像檔。Google Cloud 中的深度學習容器已預先安裝許多常見的機器學習和數據資料學架構。下載該映像檔後,這個 Dockerfile 會設定訓練程式碼的進入點。您尚未建立這些檔案。在下一個步驟中,您將新增程式碼來訓練和調整模型。

步驟 2:新增模型訓練程式碼

在終端機執行下列指令,為訓練程式碼建立目錄,以及您要新增程式碼的 Python 檔案:

mkdir trainer
touch trainer/task.py

現在 horses_or_humans/ 目錄中應會顯示以下內容:

+ Dockerfile
+ trainer/
    + task.py

接著,開啟剛剛建立的 task.py 檔案,並複製以下程式碼。

import tensorflow as tf
import tensorflow_datasets as tfds
import argparse
import hypertune

NUM_EPOCHS = 10


def get_args():
  '''Parses args. Must include all hyperparameters you want to tune.'''

  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--learning_rate',
      required=True,
      type=float,
      help='learning rate')
  parser.add_argument(
      '--momentum',
      required=True,
      type=float,
      help='SGD momentum value')
  parser.add_argument(
      '--num_units',
      required=True,
      type=int,
      help='number of units in last hidden layer')
  args = parser.parse_args()
  return args


def preprocess_data(image, label):
  '''Resizes and scales images.'''

  image = tf.image.resize(image, (150,150))
  return tf.cast(image, tf.float32) / 255., label


def create_dataset():
  '''Loads Horses Or Humans dataset and preprocesses data.'''

  data, info = tfds.load(name='horses_or_humans', as_supervised=True, with_info=True)

  # Create train dataset
  train_data = data['train'].map(preprocess_data)
  train_data  = train_data.shuffle(1000)
  train_data  = train_data.batch(64)

  # Create validation dataset
  validation_data = data['test'].map(preprocess_data)
  validation_data  = validation_data.batch(64)

  return train_data, validation_data


def create_model(num_units, learning_rate, momentum):
  '''Defines and compiles model.'''

  inputs = tf.keras.Input(shape=(150, 150, 3))
  x = tf.keras.layers.Conv2D(16, (3, 3), activation='relu')(inputs)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(32, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(64, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Flatten()(x)
  x = tf.keras.layers.Dense(num_units, activation='relu')(x)
  outputs = tf.keras.layers.Dense(1, activation='sigmoid')(x)
  model = tf.keras.Model(inputs, outputs)
  model.compile(
      loss='binary_crossentropy',
      optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=momentum),
      metrics=['accuracy'])
  return model


def main():
  args = get_args()
  train_data, validation_data = create_dataset()
  model = create_model(args.num_units, args.learning_rate, args.momentum)
  history = model.fit(train_data, epochs=NUM_EPOCHS, validation_data=validation_data)

  # DEFINE METRIC
  hp_metric = history.history['val_accuracy'][-1]

  hpt = hypertune.HyperTune()
  hpt.report_hyperparameter_tuning_metric(
      hyperparameter_metric_tag='accuracy',
      metric_value=hp_metric,
      global_step=NUM_EPOCHS)


if __name__ == "__main__":
    main()

建構容器之前,讓我們先進一步瞭解程式碼。使用超參數調整服務有幾個專門的元件。

  1. 指令碼會匯入 hypertune 程式庫。請注意,步驟 1 的 Dockerfile 包含指示 pip 安裝這個程式庫的指示。
  2. 函式 get_args() 會為您要調整的每個超參數定義指令列引數。在這個範例中,要調整的超參數包括學習率、最佳化工具中的動量值,以及模型最後一個隱藏層中的單位數量,不過您可以自由測試其他參數。接著,系統會使用這些引數中傳送的值,在程式碼中設定對應的超參數。
  3. main() 函式的結尾,hypertune 程式庫是用來定義您要最佳化的指標。在 TensorFlow 中,keras 的 model.fit 方法會傳回 History 物件。History.history 屬性是連續訓練週期的訓練損失值和指標值記錄。如果將驗證資料傳遞至 model.fitHistory.history 屬性也會包含驗證損失和指標值。舉例來說,假設您使用驗證資料來訓練三個訓練週期的模型,並將 accuracy 做為指標,History.history 屬性看起來應該會與以下字典類似。
{
 "accuracy": [
   0.7795261740684509,
   0.9471358060836792,
   0.9870933294296265
 ],
 "loss": [
   0.6340447664260864,
   0.16712145507335663,
   0.04546636343002319
 ],
 "val_accuracy": [
   0.3795261740684509,
   0.4471358060836792,
   0.4870933294296265
 ],
 "val_loss": [
   2.044623374938965,
   4.100203514099121,
   3.0728273391723633
 ]

如要讓超參數調整服務找出可將模型驗證準確率最大化的值,請將指標定義為 val_accuracy 清單的最後一個項目 (或 NUM_EPOCS - 1)。然後將這個指標傳遞至 HyperTune 的執行個體。您可以為 hyperparameter_metric_tag 挑選任何喜歡的字串,但稍後當您啟動超參數調整工作時,就需要再次使用該字串。

步驟 3:建構容器

在終端機執行下列指令,定義專案的環境變數;請務必將 your-cloud-project 替換為您的專案 ID:

PROJECT_ID='your-cloud-project'

使用 Google Container Registry 中容器映像檔的 URI 定義變數:

IMAGE_URI="gcr.io/$PROJECT_ID/horse-human:hypertune"

設定 Docker

gcloud auth configure-docker

接著,從 horses_or_humans 目錄的根目錄執行下列指令,以建構容器:

docker build ./ -t $IMAGE_URI

最後,將其推送至 Google Container Registry:

docker push $IMAGE_URI

將容器推送至 Container Registry 後,您現在可以開始執行自訂模型超參數調整工作。

5. 在 Vertex AI 中執行超參數調整工作

本研究室透過 Google Container Registry 中的自訂容器使用自訂容器,但您也能透過 Vertex AI 預先建構的容器執行超參數調整工作。

首先,請前往 Cloud 控制台「Vertex」專區中的「訓練」部分:

uCAIP 選單

步驟 1:設定訓練工作

按一下「建立」,輸入超參數調整工作的參數。

  • 在「資料集」下方,選取「沒有代管資料集」
  • 接著選取「自訂訓練 (進階)」做為訓練方法,然後按一下「繼續」
  • 在「Model name」(模型名稱) 中輸入 horses-humans-hyptertune (或是您想要呼叫模型的任何字詞)
  • 按一下 [Continue] (繼續)

在「容器設定」步驟中,選取「自訂容器」

自訂容器選項

在第一個方塊 (「容器映像檔」) 中輸入上一節的 IMAGE_URI 變數值。應該是 gcr.io/your-cloud-project/horse-human:hypertune,使用您自己的專案名稱。將其餘欄位留白,並按一下「繼續」

步驟 2:設定超參數調整工作

選取「啟用超參數調整功能」

超參數

設定超參數

接下來,您需要在訓練應用程式程式碼中,新增設為指令列引數的超參數。新增超參數時,您必須先提供名稱。這應與您傳遞至 argparse 的引數名稱相符。

learning_rate_name

接著選取類型,以及調整服務將嘗試使用的值邊界。如果選取雙精度浮點數或整數,就必須提供最小值和最大值。如果您選取「類別」或「離散」,就需要提供這些值。

learning_rate_typelearning_rate_name

對於 Double 和 Integer 類型,您還需要提供資源調度值。

learning_rate_scale

新增 learning_rate 超參數後,新增 momentumnum_units 的參數。

momentum_config

numneruons_config

設定指標

加入超參數後,接下來要提供要最佳化的指標以及目標。這應與您在訓練應用程式中設定的 hyperparameter_metric_tag 相同。

metric_config

Vertex AI 超參數調整服務會根據您在先前步驟中設定的值,執行訓練應用程式的多次試驗。設定服務執行的試驗次數上限。測試量越多,通常成效就會越佳,但經過額外試驗後,成效就幾乎或完全沒有影響您要改善的指標。最佳做法是先從少量試驗著手,然後瞭解所選超參數的影響程度,再擴充大量試驗。

你還需要設定同時執行的測試數量上限。如增加平行試驗數量,就能縮短超參數調整工作的執行時間。但可能會降低整體的工作效益這是因為預設調整策略會根據先前試驗的結果,在後續試驗中指派值。如果同時執行太多測試,將會有測試開始,無法享有仍在進行的試驗結果。

為了示範,您可以將測試數量設為 15,而同時執行的測試數量上限則為 3。您可以使用不同的數字進行實驗,但這麼做可能會拉長調整時間並增加費用。

trial_config

最後一步是選取 [預設] 做為搜尋演算法,之後會使用 Google Vizier 對超參數調整執行貝葉斯最佳化作業。若想進一步瞭解這個演算法,請參閱這篇文章

algorithm_config

按一下「繼續」

步驟 3:設定運算資源

在「運算和定價」中,維持所選區域的原樣,然後設定「工作站集區 0」,如下所示。

機器類型

按一下「開始訓練」,開始執行超參數調整工作。在控制台「HYPERPARAMETER TUNING JOBS」分頁下方的「Training」專區中,會顯示如下的內容:

超參數工作

完成後,您就能點選工作名稱並查看調整用試驗的結果。

超參數輸出

🎉 恭喜!🎉

您已瞭解如何使用 Vertex AI 執行下列作業:

  • 針對自訂容器中提供的訓練程式碼啟動超參數調整工作。在這個範例中,您使用了 TensorFlow 模型,但可以透過自訂容器,以任何架構建構的模型。

如要進一步瞭解 Vertex 的其他部分,請參閱說明文件

6. [選用] 使用 Vertex SDK

上一節將說明如何透過使用者介面啟動超參數調整工作。在本節中,您可以瞭解如何使用 Vertex Python API 提交超參數調整工作。

在 Launcher 中建立 TensorFlow 2 筆記本。

new_notebook

匯入 Vertex AI SDK。

from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt

如要啟動超參數調整工作,您必須先定義下列規格。您需要將 image_uri 中的 {PROJECT_ID} 替換為您的專案。

# The spec of the worker pools including machine type and Docker image
# Be sure to replace PROJECT_ID in the `image_uri` with your project.

worker_pool_specs = [{
    "machine_spec": {
        "machine_type": "n1-standard-4",
        "accelerator_type": "NVIDIA_TESLA_V100",
        "accelerator_count": 1
    },
    "replica_count": 1,
    "container_spec": {
        "image_uri": "gcr.io/{PROJECT_ID}/horse-human:hypertune"
    }
}]


# Dictionary representing metrics to optimize.
# The dictionary key is the metric_id, which is reported by your training job,
# And the dictionary value is the optimization goal of the metric.
metric_spec={'accuracy':'maximize'}

# Dictionary representing parameters to optimize.
# The dictionary key is the parameter_id, which is passed into your training
# job as a command line argument,
# And the dictionary value is the parameter specification of the metric.
parameter_spec = {
    "learning_rate": hpt.DoubleParameterSpec(min=0.001, max=1, scale="log"),
    "momentum": hpt.DoubleParameterSpec(min=0, max=1, scale="linear"),
    "num_units": hpt.DiscreteParameterSpec(values=[64, 128, 512], scale=None)
}

接下來,建立 CustomJob。為了進行測試,您需要將 {YOUR_BUCKET} 替換為專案中的值區。

# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='horses-humans-sdk-job',
                              worker_pool_specs=worker_pool_specs,
                              staging_bucket='gs://{YOUR_BUCKET}')

接著,請建立並執行 HyperparameterTuningJob

hp_job = aiplatform.HyperparameterTuningJob(
    display_name='horses-humans-sdk-job',
    custom_job=my_custom_job,
    metric_spec=metric_spec,
    parameter_spec=parameter_spec,
    max_trial_count=15,
    parallel_trial_count=3)

hp_job.run()

7. 清除

因為我們設定了筆記本在 60 分鐘閒置後逾時,所以我們不必擔心如何關閉執行個體。如要手動關閉執行個體,請前往控制台的「Vertex AI Workbench」專區,然後按一下「Stop」按鈕。如想完全刪除筆記本,請按一下「刪除」按鈕。

停止執行個體

如要刪除 Storage 值區,請使用 Cloud 控制台中的導覽選單前往「Storage」(儲存空間)、選取值區,然後點選「Delete」(刪除):

刪除儲存空間