Vertex AI: 분산 초매개변수 조정

1. 개요

이 실습에서는 초매개변수 조정 및 분산 학습에 Vertex AI를 사용하는 방법을 알아봅니다. 이 실습에서는 모델 코드에 TensorFlow를 사용하지만 다른 ML 프레임워크에도 개념이 적용됩니다.

학습 내용

다음 작업을 수행하는 방법을 배우게 됩니다.

  • 커스텀 컨테이너에서 분산 학습을 사용하여 모델 학습
  • 자동화된 초매개변수 조정을 위해 학습 코드의 여러 시도 실행

Google Cloud에서 이 실습을 진행하는 데 드는 총 비용은 약 $6(USD)입니다.

2. Vertex AI 소개

이 실습에서는 Google Cloud에서 제공되는 최신 AI 제품을 사용합니다. Vertex AI는 Google Cloud 전반의 ML 제품을 원활한 개발 환경으로 통합합니다. 이전에는 AutoML로 학습된 모델과 커스텀 모델은 별도의 서비스를 통해 액세스할 수 있었습니다. 새 서비스는 다른 새로운 제품과 함께 두 가지 모두를 단일 API로 결합합니다. 기존 프로젝트를 Vertex AI로 이전할 수도 있습니다. 의견이 있는 경우 지원 페이지를 참고하세요.

Vertex AI에는 엔드 투 엔드 ML 워크플로를 지원하는 다양한 제품이 포함되어 있습니다. 이 실습은 학습Workbench에 중점을 둡니다.

Vertex 제품 개요

3. 사용 사례 개요

이 실습에서는 초매개변수 조정을 사용하여 TensorFlow 데이터 세트말 또는 인간 데이터 세트에서 학습된 이미지 분류 모델에 대한 최적의 매개변수를 찾습니다.

초매개변수 조정

Vertex AI Training을 사용한 초매개변수 조정은 지정된 한도 내에서 선택한 초매개변수의 값을 사용하여 학습 애플리케이션의 여러 시도를 실행하는 방식으로 작동합니다. Vertex AI는 각 시도의 결과를 추적하고 후속 시도에 맞게 조정합니다.

Vertex AI Training과 함께 초매개변수 조정을 사용하려면 학습 코드에서 2가지를 변경해야 합니다.

  1. 기본 학습 모듈에서 조정 대상인 각 초매개변수에 대한 명령줄 인수를 정의합니다.
  2. 애플리케이션의 코드에서 이러한 인수에 전달된 값을 사용하여 초매개변수를 설정합니다.

분산 학습

단일 GPU가 있는 경우 TensorFlow가 이 액셀러레이터를 사용하여 추가 작업 없이 모델 학습 속도를 높입니다. 그러나 여러 GPU를 사용하여 성능을 더욱 높이려면 여러 기기에서 연산을 실행하는 TensorFlow 모듈인 tf.distribute를 사용해야 합니다.

이 실습에서는 코드를 몇 번만 변경하여 학습 애플리케이션에 추가할 수 있는 tf.distribute.MirroredStrategy를 사용합니다. 이 전략은 시스템의 각 GPU에 모델 사본을 만듭니다. 후속 경사 업데이트는 동기 방식으로 진행됩니다. 즉, 각 GPU가 입력 데이터의 여러 슬라이스에서 모델을 정방향 및 역방향으로 전달합니다. 그런 다음 각 슬라이스의 계산된 경사는 모든 GPU에서 집계되며 all-reduce라고 하는 프로세스로 평균화됩니다. 모델 매개변수는 이러한 평균 경사를 사용하여 업데이트됩니다.

이 실습을 완료하기 위해 세부정보를 알아야 할 필요는 없지만 TensorFlow에서 분산 학습이 작동하는 방식을 자세히 알아보려면 아래 동영상을 확인하세요.

4. 환경 설정하기

이 Codelab을 실행하려면 결제가 사용 설정된 Google Cloud Platform 프로젝트가 필요합니다. 프로젝트를 만들려면 여기의 안내를 따르세요.

1단계: Compute Engine API 사용 설정

Compute Engine으로 이동하고 아직 사용 설정되지 않았다면 사용 설정을 선택합니다.

2단계: Container Registry API 사용 설정

Container Registry로 이동하여 아직 사용 설정되지 않은 경우 사용 설정을 선택합니다. 이를 사용하여 커스텀 학습 작업을 위한 컨테이너를 생성합니다.

3단계: Vertex AI API 사용 설정

Cloud Console의 Vertex AI 섹션으로 이동하고 Vertex AI API 사용 설정을 클릭합니다.

Vertex AI 대시보드

4단계: Vertex AI Workbench 인스턴스 만들기

Cloud Console의 Vertex AI 섹션에서 Workbench를 클릭합니다.

Vertex AI 메뉴

Notebooks API를 아직 사용 설정하지 않은 경우 사용 설정합니다.

Notebook_api

사용 설정했으면 관리형 노트북을 클릭합니다.

Notebooks_UI

그런 다음 새 노트북을 선택합니다.

new_notebook

노트북 이름을 지정한 후 고급 설정을 클릭합니다.

create_notebook

고급 설정에서 유휴 상태 종료를 사용 설정하고 분을 60으로 설정합니다. 즉, 노트북을 사용하지 않을 때는 자동으로 종료되므로 불필요한 비용이 발생하지 않습니다.

idle_timeout

보안에서 '터미널 사용 설정'이 아직 사용 설정되지 않은 경우 선택합니다.

enable-terminal

다른 고급 설정은 모두 그대로 두면 됩니다.

그런 다음 만들기를 클릭합니다. 인스턴스를 프로비저닝하는 데 몇 분 정도 걸립니다.

인스턴스가 생성되면 JupyterLab 열기를 선택합니다.

open_jupyterlab

새 인스턴스를 처음 사용하는 경우 인증하라는 메시지가 표시됩니다. 진행하려면 UI의 단계를 따릅니다.

인증

5. 학습 코드 작성

시작하려면 런처 메뉴에서 노트북 인스턴스의 터미널 창을 엽니다.

launcher_terminal

vertex-codelab이라는 새 디렉터리를 만들고 여기로 CD합니다.

mkdir vertex-codelab
cd vertex-codelab

다음을 실행하여 학습 코드 디렉터리와 코드를 추가할 Python 파일을 만듭니다.

mkdir trainer
touch trainer/task.py

이제 vertex-codelab 디렉터리에 다음이 포함됩니다.

+ trainer/
    + task.py

방금 만든 task.py 파일을 열고 아래의 모든 코드를 붙여넣습니다.

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

NUM_EPOCHS = 10
BATCH_SIZE = 64

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(batch_size):
  '''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(batch_size)

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

  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()

  # Create distribution strategy
  strategy = tf.distribute.MirroredStrategy()

  # Get data
  GLOBAL_BATCH_SIZE = BATCH_SIZE * strategy.num_replicas_in_sync
  train_data, validation_data = create_dataset(GLOBAL_BATCH_SIZE)

  # Wrap variable creation within strategy scope
  with strategy.scope():
    model = create_model(args.num_units, args.learning_rate, args.momentum)

  # Train model
  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. main() 함수에 MirroredStrategy 객체가 생성됩니다. 다음은 전략 범위 내에 모델 변수 생성을 래핑합니다. 이 단계는 모든 GPU에서 미러링해야 하는 변수를 TensorFlow에 알려줍니다.
  2. 배치 크기는 num_replicas_in_sync에 의해 확장됩니다. TensorFlow에서 동기 데이터 동시 로드 전략을 사용할 때는 배치 크기를 확장하는 것이 좋습니다. 자세한 내용은 여기를 참조하세요.

초매개변수 조정

  1. 스크립트가 hypertune 라이브러리를 가져옵니다. 나중에 컨테이너 이미지를 빌드할 때 이 라이브러리를 설치해야 합니다.
  2. get_args() 함수는 조정하려는 각 초매개변수의 명령줄 인수를 정의합니다. 이 예시에서 조정될 초매개변수는 학습률, 옵티마이저의 모멘텀 값, 모델의 마지막 히든 레이어의 단위 수이지만 자유롭게 실험해도 됩니다. 그런 다음 이러한 인수에 전달된 값은 코드에서 해당 초매개변수를 설정하는 데 사용됩니다(예: learning_rate = args.learning_rate 설정).
  3. main() 함수의 끝에서 hypertune 라이브러리를 사용하여 최적화하려는 측정항목을 정의합니다. TensorFlow에서 Keras model.fit 메서드는 History 객체를 반환합니다. History.history 속성은 연속된 에포크의 학습 손실 값 및 측정항목 값에 대한 레코드입니다. 유효성 검사 데이터를 model.fit에 전달하면 History.history 속성에 유효성 검사 손실 및 측정항목 값도 포함됩니다. 예를 들어 유효성 검사 데이터로 3개의 에포크에 대한 모델을 학습하고 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에 대해 원하는 문자열을 선택할 수 있지만 나중에 초매개변수 조정 작업을 시작할 때 문자열을 다시 사용해야 합니다.

6. 코드 컨테이너화

코드를 컨테이너화하는 첫 번째 단계는 Dockerfile을 만드는 것입니다. Dockerfile에는 이미지를 실행하는 데 필요한 모든 명령어가 포함됩니다. 필요한 모든 라이브러리를 설치하고 학습 코드의 진입점을 설정합니다.

1단계: Dockerfile 작성

터미널에서 vertex-codelab 디렉터리에 있는지 확인하고 빈 Dockerfile을 만듭니다.

touch Dockerfile

이제 vertex-codelab 디렉터리에 다음이 포함됩니다.

+ Dockerfile
+ trainer/
    + task.py

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은 Deep Learning Container TensorFlow Enterprise 2.7 GPU Docker 이미지를 사용합니다. Google Cloud의 Deep Learning Containers에는 많은 수의 일반적인 ML 및 데이터 과학 프레임워크가 사전 설치된 상태로 제공됩니다. 해당 이미지를 다운로드한 후 이 Dockerfile은 학습 코드의 진입점을 설정합니다.

2단계: 컨테이너 빌드

터미널에서 다음을 실행하여 프로젝트의 env 변수를 정의하고 your-cloud-project를 프로젝트의 ID로 바꿉니다.

PROJECT_ID='your-cloud-project'

Google Container Registry에서 컨테이너 이미지의 URI로 변수를 정의합니다.

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

Docker 구성

gcloud auth configure-docker

그런 다음 vertex-codelab 디렉터리의 루트에서 다음을 실행하여 컨테이너를 빌드합니다.

docker build ./ -t $IMAGE_URI

마지막으로 Google Container Registry에 푸시합니다.

docker push $IMAGE_URI

3단계: Cloud Storage 버킷 만들기

이번 학습 작업에서는 스테이징 버킷의 경로를 전달해 보겠습니다.

터미널에서 다음을 실행하여 프로젝트에 새 버킷을 만듭니다.

BUCKET_NAME="gs://${PROJECT_ID}-hptune-bucket"
gsutil mb -l us-central1 $BUCKET_NAME

7. 초매개변수 조정 작업 실행

1단계: 초매개변수 조정으로 커스텀 학습 작업 만들기

런처에서 새로운 TensorFlow 2 노트북을 엽니다.

new_notebook

Vertex AI Python SDK를 가져옵니다.

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

초매개변수 조정 작업을 시작하려면 먼저 머신 유형과 Docker 이미지를 지정하는 worker_pool_specs를 정의해야 합니다. 다음 사양은 NVIDIA Tesla V100 GPU 2개를 갖춘 머신 1개를 정의합니다.

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": 2
    },
    "replica_count": 1,
    "container_spec": {
        "image_uri": "gcr.io/{PROJECT_ID}/horse-human-codelab:latest"
    }
}]

다음은 최적화할 매개변수를 지정하는 사전인 parameter_spec을 정의합니다. 사전 키는 각 초매개변수의 명령줄 인수에 할당한 문자열이며 사전 값은 매개변수 사양입니다.

각 초매개변수의 경우 조정 서비스에서 시도할 값의 경계와 유형을 정의해야 합니다. 초매개변수는 Double, Integer, Categorical 또는 Discrete 유형일 수 있습니다. Double 또는 Integer 유형을 선택한 경우 최솟값과 최댓값을 제공해야 합니다. Categorical 또는 Discrete을 선택한 경우 해당 값을 제공해야 합니다. Double 및 Integer 유형의 경우 확장 값도 제공해야 합니다. 최적의 조정을 선택하는 방법에 대해 자세히 알아보려면 이 동영상을 참조하세요.

# 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)
}

정의할 최종 사양은 최적화할 측정항목을 나타내는 사전인 metric_spec입니다. 사전 키는 학습 애플리케이션 코드에 설정한 hyperparameter_metric_tag이며 이 값은 최적화 목표입니다.

# Dicionary 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'}

사양이 정의되면 각 초매개변수 조정 시도에서 작업을 실행하는 데 사용되는 일반 사양인 CustomJob을 만듭니다.

{YOUR_BUCKET}을 이전에 만든 버킷으로 바꿔야 합니다.

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

그런 다음 HyperparameterTuningJob을 만들고 실행합니다.

hp_job = aiplatform.HyperparameterTuningJob(
    display_name='horses-humans',
    custom_job=my_custom_job,
    metric_spec=metric_spec,
    parameter_spec=parameter_spec,
    max_trial_count=6,
    parallel_trial_count=2,
    search_algorithm=None)

hp_job.run()

다음은 주의해야 할 몇 가지 인수입니다.

  • max_trial_count: 서비스가 실행될 시도 횟수의 상한값을 설정해야 합니다. 더 많이 시도하면 일반적으로 결과가 향상되지만, 반환되는 결과가 감소하는 시점이 있습니다. 그 이후에는 추가로 시도해도 최적화할 측정항목에 거의 또는 전혀 영향을 미치지 않습니다. 시도 횟수를 늘리기 전에 선택한 초매개변수가 미치는 영향을 판별하기 위해 시도 횟수를 적게 설정하는 것이 좋습니다.
  • parallel_trial_count: 병렬 시도를 사용하는 경우 서비스에서 여러 학습 처리 클러스터를 프로비저닝합니다. 병렬 시도 횟수를 늘리면 초매개변수 조정 작업을 실행하는 데 걸리는 시간이 줄어듭니다. 하지만 전체적으로 작업의 효율성이 떨어질 수 있습니다. 기본 조정 전략이 이전 시도의 결과를 사용하여 후속 시도에서 값 할당을 알리기 때문입니다.
  • search_algorithm: 검색 알고리즘을 그리드, 무작위 또는 기본값(없음)으로 설정할 수 있습니다. 기본 옵션은 Bayesian 최적화를 적용하여 가능한 초매개변수 값의 공간을 검색하며 권장되는 알고리즘입니다. 이 알고리즘에 대한 자세한 내용은 여기에서 확인할 수 있습니다.

작업이 시작되면 UI의 HYPERPARAMETER TUNING JOBS 탭에서 상태를 추적할 수 있습니다.

HP_job

작업이 완료되면 시도한 결과를 보고 정렬하여 최적의 초매개변수 값 조합을 찾을 수 있습니다.

HP_results

🎉 수고하셨습니다. 🎉

Vertex AI를 사용하여 다음을 수행하는 방법을 배웠습니다.

  • 분산 학습으로 초매개변수 조정 작업 실행

Vertex AI의 다른 부분에 대해 자세히 알아보려면 문서를 확인하세요.

8. 정리

노트북이 유휴 시간 60분 후에 타임아웃되도록 구성했으므로 인스턴스를 종료할 필요가 없습니다. 인스턴스를 수동으로 종료하려면 콘솔의 Vertex AI Workbench 섹션에서 중지 버튼을 클릭합니다. 노트북을 완전히 삭제하려면 삭제 버튼을 클릭합니다.

삭제

스토리지 버킷을 삭제하려면 Cloud Console의 탐색 메뉴를 사용하여 스토리지로 이동하고 버킷을 선택하고 삭제를 클릭합니다.

스토리지 삭제