Vertex AI: Vertex AI Training에서 자동 패키징을 사용하여 Hugging Face로 BERT 미세 조정

1. 개요

이 실습에서는 자동 패키징 기능을 사용하여 Vertex AI 학습에서 커스텀 학습 작업을 실행하는 방법을 알아봅니다. Vertex AI의 커스텀 학습 작업은 컨테이너를 사용합니다. 자체 이미지를 빌드하고 싶지 않다면 자동 패키징을 사용하면 됩니다. 자동 패키징은 코드를 기반으로 맞춤 Docker 이미지를 빌드하고, 이미지를 Container Registry에 푸시하고, 이미지를 기반으로 CustomJob를 시작합니다.

학습 내용

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

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

2. 사용 사례 개요

Hugging Face의 라이브러리를 사용하여 IMDB 데이터 세트에서 BERT 모델을 미세 조정합니다. 모델은 영화 리뷰가 긍정적인 리뷰인지 부정적인 리뷰인지 예측합니다. 데이터 세트는 Hugging Face 데이터 세트 라이브러리에서, Bert 모델은 Hugging Face Transformers 라이브러리에서 다운로드됩니다.

3. Vertex AI 소개

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

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

Vertex 제품 개요

4. 환경 설정하기

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

1단계: Compute Engine API 사용 설정

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

2단계: Vertex AI API 사용 설정

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

Vertex AI 대시보드

3단계: Container Registry API 사용 설정

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

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

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

Vertex AI 메뉴

여기에서 관리형 노트북을 클릭합니다.

Notebooks_UI

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

new_notebook

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

create_notebook

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

idle_timeout

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

그런 다음 만들기를 클릭합니다.

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

open_jupyterlab

새 인스턴스를 처음 사용하는 경우 인증하라는 메시지가 표시됩니다.

인증

5. 학습 코드 작성

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

launcher_terminal

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

mkdir autopkg-codelab
cd autopkg-codelab

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

mkdir trainer
touch trainer/task.py

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

+ trainer/
    + task.py

다음으로, 방금 만든 task.py 파일을 열고 아래의 코드를 복사합니다.

import argparse

import tensorflow as tf
from datasets import load_dataset
from transformers import AutoTokenizer
from transformers import TFAutoModelForSequenceClassification

CHECKPOINT = "bert-base-cased"

def get_args():
  '''Parses args.'''

  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--epochs',
      required=False,
      default=3,
      type=int,
      help='number of epochs')
  parser.add_argument(
      '--job_dir',
      required=True,
      type=str,
      help='bucket to store saved model, include gs://')
  args = parser.parse_args()
  return args


def create_datasets():
    '''Creates a tf.data.Dataset for train and evaluation.'''

    raw_datasets = load_dataset('imdb')
    tokenizer = AutoTokenizer.from_pretrained(CHECKPOINT)
    tokenized_datasets = raw_datasets.map((lambda examples: tokenize_function(examples, tokenizer)), batched=True)

    # To speed up training, we use only a portion of the data.
    # Use full_train_dataset and full_eval_dataset if you want to train on all the data.
    small_train_dataset = tokenized_datasets['train'].shuffle(seed=42).select(range(1000))
    small_eval_dataset = tokenized_datasets['test'].shuffle(seed=42).select(range(1000))
    full_train_dataset = tokenized_datasets['train']
    full_eval_dataset = tokenized_datasets['test']

    tf_train_dataset = small_train_dataset.remove_columns(['text']).with_format("tensorflow")
    tf_eval_dataset = small_eval_dataset.remove_columns(['text']).with_format("tensorflow")

    train_features = {x: tf_train_dataset[x] for x in tokenizer.model_input_names}
    train_tf_dataset = tf.data.Dataset.from_tensor_slices((train_features, tf_train_dataset["label"]))
    train_tf_dataset = train_tf_dataset.shuffle(len(tf_train_dataset)).batch(8)

    eval_features = {x: tf_eval_dataset[x] for x in tokenizer.model_input_names}
    eval_tf_dataset = tf.data.Dataset.from_tensor_slices((eval_features, tf_eval_dataset["label"]))
    eval_tf_dataset = eval_tf_dataset.batch(8)

    return train_tf_dataset, eval_tf_dataset


def tokenize_function(examples, tokenizer):
    '''Tokenizes text examples.'''

    return tokenizer(examples['text'], padding='max_length', truncation=True)


def main():
    args = get_args()
    train_tf_dataset, eval_tf_dataset = create_datasets()
    model = TFAutoModelForSequenceClassification.from_pretrained(CHECKPOINT, num_labels=2)

    model.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
        metrics=tf.metrics.SparseCategoricalAccuracy(),
    )

    model.fit(train_tf_dataset, validation_data=eval_tf_dataset, epochs=args.epochs)
    model.save(f'{args.job_dir}/model_output')


if __name__ == "__main__":
    main()

코드에 관한 몇 가지 참고사항은 다음과 같습니다.

  • CHECKPOINT은 미세 조정하려는 모델입니다. 이 경우 Bert를 사용합니다.
  • TFAutoModelForSequenceClassification 메서드는 TensorFlow에 지정된 언어 모델 아키텍처 + 가중치를 로드하고 무작위로 초기화된 가중치가 있는 분류 헤드를 맨 위에 추가합니다. 이 경우 이진 분류 문제 (양성 또는 음성)이므로 이 분류기에 num_labels=2를 지정합니다.

6. 로컬에서 학습 코드 컨테이너화 및 실행

gcloud ai custom-jobs local-run 명령어를 사용하여 학습 코드를 기반으로 Docker 컨테이너 이미지를 빌드하고 로컬 머신에서 컨테이너로 이미지를 실행할 수 있습니다. 컨테이너를 로컬에서 실행하면 학습 코드는 Vertex AI 학습에서 실행되는 방식과 유사한 방식으로 실행되며, Vertex AI에서 커스텀 학습을 수행하기 전에 코드 문제를 디버깅하는 데 도움이 될 수 있습니다.

이 학습 작업에서는 학습된 모델을 Cloud Storage 버킷으로 내보냅니다. 터미널에서 다음을 실행하여 프로젝트의 env 변수를 정의하고 your-cloud-project를 프로젝트의 ID로 바꿉니다.

PROJECT_ID='your-cloud-project'

그런 다음 버킷을 만듭니다. 기존 버킷이 있는 경우 대신 해당 버킷을 사용해도 됩니다.

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

Vertex AI 학습에서 커스텀 학습 작업을 실행할 때 GPU를 사용합니다. 하지만 GPU가 있는 Workbench 인스턴스를 지정하지 않았으므로 로컬 테스트에는 CPU 기반 이미지를 사용합니다. 이 예에서는 Vertex AI 학습 사전 빌드된 컨테이너를 사용합니다.

다음을 실행하여 컨테이너의 기반으로 사용할 Docker 이미지의 URI를 설정합니다.

BASE_CPU_IMAGE=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-7:latest

그런 다음 local run 명령어로 빌드된 결과 Docker 이미지의 이름을 설정합니다.

OUTPUT_IMAGE=$PROJECT_ID-local-package-cpu:latest

학습 코드는 Hugging Face 데이터 세트와 트랜스포머 라이브러리를 사용합니다. 이러한 라이브러리는 기본 이미지로 선택한 이미지에 포함되어 있지 않으므로 요구사항으로 제공해야 합니다. 이렇게 하려면 autopkg-codelab 디렉터리에 requirements.txt 파일을 만듭니다.

현재 위치가 autopkg-codelab 디렉터리인지 확인하고 터미널에 다음을 입력합니다.

touch requirements.txt

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

+ requirements.txt
+ trainer/
    + task.py

요구사항 파일을 열고 다음을 붙여넣습니다.

datasets==1.18.2
transformers==4.16.2

마지막으로 gcloud ai custom-jobs local-run 명령어를 실행하여 Workbench 관리 인스턴스에서 학습을 시작합니다.

gcloud ai custom-jobs local-run \
--executor-image-uri=$BASE_CPU_IMAGE \
--python-module=trainer.task \
--output-image-uri=$OUTPUT_IMAGE \
-- \
--job_dir=$BUCKET_NAME

Docker 이미지가 빌드되는 것을 볼 수 있습니다. requirements.txt 파일에 추가한 종속 항목이 pip 설치됩니다. 이 명령어를 처음 실행할 때는 완료되는 데 몇 분 정도 걸릴 수 있습니다. 이미지가 빌드되면 task.py 파일이 실행되기 시작하고 모델 학습이 표시됩니다. 다음과 같은 결과를 확인할 수 있습니다.

local_training

로컬에서 GPU를 사용하지 않으므로 모델 학습에 시간이 오래 걸립니다. 작업이 완료될 때까지 기다리는 대신 Ctrl+C를 눌러 로컬 학습을 취소할 수 있습니다.

추가 테스트를 수행하려면 리패키징하지 않고 위에 빌드된 이미지를 직접 실행할 수도 있습니다.

gcloud beta ai custom-jobs local-run \
--executor-image-uri=$OUTPUT_IMAGE \
-- \
--job_dir=$BUCKET_NAME \
--epochs=1

7. 커스텀 작업 만들기

이제 로컬 모드를 테스트했으므로 자동 패키징 기능을 사용하여 Vertex AI Training에서 커스텀 학습 작업을 실행해 보겠습니다. 이 기능을 사용하면 단일 명령어로 다음 작업을 할 수 있습니다.

  • 코드를 기반으로 커스텀 Docker 이미지를 빌드합니다.
  • 이미지를 Container Registry로 내보내기
  • 이미지를 기반으로 CustomJob을 시작합니다.

터미널로 돌아가 autopkg-codelab 디렉터리보다 한 수준 위로 이동합니다.

+ autopkg-codelab
  + requirements.txt
  + trainer/
      + task.py

Vertex AI 학습 사전 빌드된 TensorFlow GPU 이미지를 커스텀 학습 작업의 기본 이미지로 지정합니다.

BASE_GPU_IMAGE=us-docker.pkg.dev/vertex-ai/training/tf-gpu.2-7:latest

그런 다음 gcloud ai custom-jobs create 명령어를 실행합니다. 먼저 이 명령어는 학습 코드를 기반으로 커스텀 Docker 이미지를 빌드합니다. 기본 이미지는 BASE_GPU_IMAGE로 설정된 Vertex AI 학습 사전 빌드 컨테이너입니다. 그러면 자동 패키징 기능이 requirements.txt 파일에 지정된 대로 데이터 세트 및 변환기 라이브러리를 pip 설치합니다.

gcloud ai custom-jobs create \
--region=us-central1 \
--display-name=fine_tune_bert \
--args=--job_dir=$BUCKET_NAME \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,accelerator-type=NVIDIA_TESLA_V100,executor-image-uri=$BASE_GPU_IMAGE,local-package-path=autopkg-codelab,python-module=trainer.task

worker-pool-spec 인수를 살펴보겠습니다. 이는 커스텀 작업에 사용되는 작업자 풀 구성을 정의합니다. 분산 학습을 위한 여러 작업자 풀이 있는 커스텀 작업을 만들기 위해 여러 작업자 풀 사양을 지정할 수 있습니다. 이 예에서는 학습 코드가 분산 학습용으로 구성되지 않았으므로 단일 작업자 풀만 지정합니다.

다음은 이 사양의 주요 필드입니다.

  • machine-type (필수): 머신 유형입니다. 지원되는 유형을 확인하려면 여기를 클릭하세요.
  • replica-count: 이 작업자 풀에 사용할 작업자 복제본 수입니다. 기본값은 1입니다.
  • accelerator-type: GPU 유형입니다. 지원되는 유형을 확인하려면 여기를 클릭하세요. 이 예에서는 NVIDIA Tesla V100 GPU 1개를 지정했습니다.
  • accelerator-count: 작업자 풀의 각 VM에서 사용할 GPU 수입니다. 기본값은 1입니다.
  • executor-image-uri: 제공된 패키지를 실행할 컨테이너 이미지의 URI입니다. 기본 이미지로 설정됩니다.
  • local-package-path: 학습 코드가 포함된 폴더의 로컬 경로입니다.
  • python-module: 제공된 패키지 내에서 실행할 Python 모듈 이름입니다.

로컬 명령어를 실행할 때와 마찬가지로 Docker 이미지가 빌드되고 학습 작업이 시작됩니다. 단, 학습 작업의 출력이 표시되는 대신 학습 작업이 시작되었음을 확인하는 다음 메시지가 표시됩니다. custom-jobs create 명령어를 처음 실행하면 이미지가 빌드되고 푸시되는 데 몇 분 정도 걸릴 수 있습니다.

training_started

Cloud 콘솔의 Vertex AI Training 섹션으로 돌아가면 커스텀 작업 아래에 작업이 실행 중인 것을 확인할 수 있습니다.

training_job

작업이 완료되는 데 약 20분이 소요됩니다.

완료되면 버킷의 model_output 디렉터리에 다음과 같이 저장된 모델 아티팩트가 표시됩니다.

model_output

🎉 수고하셨습니다. 🎉

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

  • 로컬에서 학습 코드 컨테이너화 및 실행
  • 자동 패키징으로 Vertex AI 학습에 학습 작업 제출

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

8. 정리

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

삭제

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

스토리지 삭제