1. 개요
이 실습에서는 PyTorch를 사용하여 모델을 빌드하며 Google Cloud에서 전체 ML 학습 워크플로를 살펴봅니다. Cloud AI Platform Notebooks 환경에서 초매개변수 조정을 통해 학습 작업을 패키징하여 AI Platform Training에서 실행하는 방법을 알아봅니다.
학습 내용
다음 작업을 수행하는 방법을 배우게 됩니다.
- AI Platform Notebooks 인스턴스 만들기
- PyTorch 모델 만들기
- AI Platform Training에서 초매개변수 조정으로 모델 학습
Google Cloud에서 이 실습을 진행하는 데 드는 총 비용은 약 $1입니다.
2. 환경 설정
이 Codelab을 실행하려면 결제가 사용 설정된 Google Cloud Platform 프로젝트가 필요합니다. 프로젝트를 만들려면 여기의 안내를 따르세요.
1단계: Cloud AI Platform 모델 API 사용 설정
Cloud 콘솔의 AI Platform 모델 섹션으로 이동하고 아직 사용 설정되지 않은 경우 '사용 설정'을 클릭합니다.
2단계: Compute Engine API 사용 설정
아직 사용 설정되지 않은 경우 Compute Engine으로 이동하고 사용 설정을 선택합니다. 이것은 노트북 인스턴스를 생성하는 데 필요합니다.
3단계: AI Platform Notebooks 인스턴스 만들기
Cloud 콘솔의 AI Platform Notebooks 섹션으로 이동하여 새 인스턴스를 클릭합니다. 그런 다음 최신 PyTorch 인스턴스 유형을 선택합니다 (GPU 제외).
기본 옵션을 사용하거나 원하는 경우 맞춤 이름을 지정한 다음 만들기를 클릭합니다. 인스턴스가 생성되면 JupyterLab 열기를 선택합니다.
그런 다음 런처에서 Python 3 Notebook 인스턴스를 엽니다.
이제 시작할 준비가 되었습니다.
5단계: Python 패키지 가져오기
노트북의 첫 번째 셀에서 다음 가져오기를 추가하고 셀을 실행합니다. 상단 메뉴에서 오른쪽 화살표 버튼을 누르거나 Command-Enter를 눌러 실행할 수 있습니다.
import datetime
import numpy as np
import os
import pandas as pd
import time
여기서는 PyTorch를 가져오지 않습니다. 이는 Notebook 인스턴스가 아닌 AI Platform Training에서 학습 작업을 실행하고 있기 때문입니다.
3. 학습 작업용 패키지 만들기
AI Platform Training에서 학습 작업을 실행하려면 Notebooks 인스턴스에 로컬로 패키징된 학습 코드와 작업에 사용할 애셋을 저장할 Cloud Storage 버킷이 필요합니다. 먼저 스토리지 버킷을 만들어 보겠습니다. 이미 계정이 있는 경우 이 단계를 건너뛰어도 됩니다.
1단계: 모델을 위한 Cloud Storage 버킷 만들기
먼저 Codelab의 나머지 부분에서 사용할 몇 가지 환경 변수를 정의해 보겠습니다. 아래에 Google Cloud 프로젝트의 이름과 만들려는 Cloud Storage 버킷의 이름을 입력합니다 (전역적으로 고유해야 함).
# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'
이제 학습 작업을 시작할 때 가리킬 저장소 버킷을 만들 준비가 되었습니다.
노트북 내에서 이 gsutil
명령어를 실행하여 버킷을 만듭니다.
!gsutil mb $BUCKET_URL
2단계: Python 패키지의 초기 파일 만들기
AI Platform에서 학습 작업을 실행하려면 코드를 Python 패키지로 구성해야 합니다. 이 파일은 외부 패키지 종속 항목을 지정하는 루트 디렉터리의 setup.py
파일, 패키지 이름이 있는 하위 디렉터리 (여기서는 trainer/
) 및 이 하위 디렉터리 내의 빈 __init__.py
파일로 구성됩니다.
먼저 setup.py 파일을 작성해 보겠습니다. iPython %%writefile 매직을 사용하여 파일을 인스턴스에 저장합니다. 여기서는 학습 코드에 사용할 3가지 외부 라이브러리인 PyTorch, scikit-learn, Pandas를 지정했습니다.
%%writefile setup.py
from setuptools import find_packages
from setuptools import setup
REQUIRED_PACKAGES = ['torch>=1.5', 'scikit-learn>=0.20', 'pandas>=1.0']
setup(
name='trainer',
version='0.1',
install_requires=REQUIRED_PACKAGES,
packages=find_packages(),
include_package_data=True,
description='My training application package.'
)
다음으로 trainer/ 디렉터리와 그 안에 빈 init.py 파일을 생성해 보겠습니다. Python은 이 파일을 사용하여 이 파일이 패키지임을 인식합니다.
!mkdir trainer
!touch trainer/__init__.py
이제 학습 작업을 만들 준비가 되었습니다.
4. 데이터 세트 미리보기
이 실습에서는 모델 학습용 도구에 중점을 두지만, 이해하도록 모델을 학습시키는 데 사용할 데이터 세트를 간단히 살펴보겠습니다. BigQuery에서 제공되는 출생률 데이터 세트를 사용하겠습니다. 여기에는 수십 년간 미국에서 수집된 출생 데이터가 포함되어 있습니다. 데이터 세트의 몇 개의 열을 사용하여 아기의 출생 시 체중을 예측하겠습니다. 원본 데이터 세트는 상당히 크고 Cloud Storage 버킷에서 제공되던 하위 집합을 사용합니다.
1단계: BigQuery 출생률 데이터 세트 다운로드
Cloud Storage에서 사용할 수 있도록 준비한 데이터 세트 버전을 Pandas DataFrame으로 다운로드하고 미리 보겠습니다.
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()
이 데이터 세트에는 100,000개 미만의 행이 있습니다. 아기의 출생 시 체중을 예측하기 위해 산모 연령, 임신 주수, 산모의 체중 증가(파운드), 아기의 성별을 부울로 예측해 보겠습니다.
5. 초매개변수 조정으로 학습 작업 정의
앞서 만든 trainer/ 하위 디렉터리 내의 model.py 파일에 학습 스크립트를 작성해 보겠습니다. 학습 작업은 AI Platform Training에서 실행되며, AI Platform의 초매개변수 조정 서비스를 사용하여 Bayesian 최적화를 활용하는 모델에 가장 적합한 초매개변수를 찾습니다.
1단계: 학습 스크립트 만들기
먼저 학습 스크립트를 사용하여 Python 파일을 만들어 보겠습니다. 그런 다음 그 안에서 어떤 일이 일어나고 있는지 분석해 보겠습니다. 이 %%writefile 명령어를 실행하면 모델 코드가 로컬 Python 파일에 작성됩니다.
%%writefile trainer/model.py
import argparse
import hypertune
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.utils import shuffle
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import normalize
def get_args():
"""Argument parser.
Returns:
Dictionary of arguments.
"""
parser = argparse.ArgumentParser(description='PyTorch MNIST')
parser.add_argument('--job-dir', # handled automatically by AI Platform
help='GCS location to write checkpoints and export ' \
'models')
parser.add_argument('--lr', # Specified in the config file
type=float,
default=0.01,
help='learning rate (default: 0.01)')
parser.add_argument('--momentum', # Specified in the config file
type=float,
default=0.5,
help='SGD momentum (default: 0.5)')
parser.add_argument('--hidden-layer-size', # Specified in the config file
type=int,
default=8,
help='hidden layer size')
args = parser.parse_args()
return args
def train_model(args):
# Get the data
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality = natality.dropna()
natality = shuffle(natality, random_state = 2)
natality.head()
natality_labels = natality['weight_pounds']
natality = natality.drop(columns=['weight_pounds'])
train_size = int(len(natality) * 0.8)
traindata_natality = natality[:train_size]
trainlabels_natality = natality_labels[:train_size]
testdata_natality = natality[train_size:]
testlabels_natality = natality_labels[train_size:]
# Normalize and convert to PT tensors
normalized_train = normalize(np.array(traindata_natality.values), axis=0)
normalized_test = normalize(np.array(testdata_natality.values), axis=0)
train_x = torch.Tensor(normalized_train)
train_y = torch.Tensor(np.array(trainlabels_natality))
test_x = torch.Tensor(normalized_test)
test_y = torch.Tensor(np.array(testlabels_natality))
# Define our data loaders
train_dataset = torch.utils.data.TensorDataset(train_x, train_y)
train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)
test_dataset = torch.utils.data.TensorDataset(test_x, test_y)
test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=128, shuffle=False)
# Define the model, while tuning the size of our hidden layer
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
criterion = nn.MSELoss()
# Tune hyperparameters in our optimizer
optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum)
epochs = 20
for e in range(epochs):
for batch_id, (data, label) in enumerate(train_dataloader):
optimizer.zero_grad()
y_pred = model(data)
label = label.view(-1,1)
loss = criterion(y_pred, label)
loss.backward()
optimizer.step()
val_mse = 0
num_batches = 0
# Evaluate accuracy on our test set
with torch.no_grad():
for i, (data, label) in enumerate(test_dataloader):
num_batches += 1
y_pred = model(data)
mse = criterion(y_pred, label.view(-1,1))
val_mse += mse.item()
avg_val_mse = (val_mse / num_batches)
# Report the metric we're optimizing for to AI Platform's HyperTune service
# In this example, we're mimizing error on our test set
hpt = hypertune.HyperTune()
hpt.report_hyperparameter_tuning_metric(
hyperparameter_metric_tag='val_mse',
metric_value=avg_val_mse,
global_step=epochs
)
def main():
args = get_args()
print('in main', args)
train_model(args)
if __name__ == '__main__':
main()
학습 작업은 많은 작업이 발생하는 두 가지 기능으로 구성됩니다.
get_args()
: 학습 작업을 만들 때 전달할 명령줄 인수와 AI Platform에서 최적화할 초매개변수를 파싱합니다. 이 예에서 인수 목록에는 최적화할 초매개변수, 즉 모델의 학습률, 모멘텀, 히든 레이어의 뉴런 수만 포함됩니다.train_model()
: 데이터를 Pandas DataFrame으로 다운로드하여 정규화하고, PyTorch 텐서로 변환하고, 모델을 정의합니다. 모델을 빌드하기 위해 모델을 레이어 스택으로 정의할 수 있는 PyTorchnn.Sequential
API를 사용합니다.
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
모델의 히든 레이어 크기를 하드코딩하는 대신 이 초매개변수를 AI Platform에서 자동으로 조정하도록 만듭니다. 이에 대해서는 다음 섹션에서 자세히 설명합니다.
2단계: AI Platform의 초매개변수 조정 서비스 사용
매번 수동으로 다양한 초매개변수 값을 시도하고 모델을 다시 학습시키는 대신 Cloud AI Platform의 초매개변수 최적화 서비스를 사용할 것입니다. 초매개변수 인수로 학습 작업을 설정하면 AI Platform은 Bayesian 최적화를 사용하여 지정한 초매개변수에 대한 이상적인 값을 찾습니다.
초매개변수 조정에서 단일 시도는 초매개변수 값의 특정 조합을 사용한 모델의 학습 실행 1회로 구성됩니다. 시도 횟수에 따라 AI Platform에서 완료된 시도의 결과를 사용하여 이후 시도에 사용할 초매개변수를 최적화합니다. 초매개변수 조정을 구성하려면 최적화 중인 각 초매개변수의 일부 데이터로 학습 작업을 시작할 때 구성 파일을 전달해야 합니다.
다음으로 이 구성 파일을 로컬로 만듭니다.
%%writefile config.yaml
trainingInput:
hyperparameters:
goal: MINIMIZE
maxTrials: 10
maxParallelTrials: 5
hyperparameterMetricTag: val_mse
enableTrialEarlyStopping: TRUE
params:
- parameterName: lr
type: DOUBLE
minValue: 0.0001
maxValue: 0.1
scaleType: UNIT_LINEAR_SCALE
- parameterName: momentum
type: DOUBLE
minValue: 0.0
maxValue: 1.0
scaleType: UNIT_LINEAR_SCALE
- parameterName: hidden-layer-size
type: INTEGER
minValue: 8
maxValue: 32
scaleType: UNIT_LINEAR_SCALE
각 초매개변수에 대해 유형, 검색할 값의 범위, 여러 시도에서 값을 증가시키는 척도를 지정합니다.
작업을 시작할 때 최적화할 측정항목도 지정합니다. 시도가 완료될 때마다 위의 train_model()
함수 끝에서 이 측정항목을 AI Platform에 보고합니다. 여기서는 모델의 평균 제곱 오차를 최소화하기 때문에 모델에서 평균 제곱 오차가 가장 낮은 초매개변수를 사용하려고 합니다. 이 측정항목의 이름 (val_mse
)은 시도가 끝날 때 report_hyperparameter_tuning_metric()
를 호출할 때 보고할 때 사용하는 이름과 일치합니다.
6. AI Platform에서 학습 작업 실행
이 섹션에서는 AI Platform에서 초매개변수 조정을 사용하여 모델 학습 작업을 시작합니다.
1단계: 일부 환경 변수 정의
먼저 학습 작업을 시작하는 데 사용할 몇 가지 환경 변수를 정의해 보겠습니다. 다른 리전에서 작업을 실행하려면 아래의 REGION 변수를 업데이트하세요.
MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"
AI Platform의 각 학습 작업에는 고유한 이름이 있어야 합니다. 다음을 실행하여 타임스탬프를 사용하는 작업 이름의 변수를 정의합니다.
timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))
2단계: 학습 작업 시작하기
Google Cloud CLI인 gcloud를 사용하여 학습 작업을 만들어 보겠습니다. 이 명령어를 노트북에서 직접 실행하여 위에서 정의한 변수를 참조할 수 있습니다.
!gcloud ai-platform jobs submit training $JOB_NAME \
--scale-tier basic \
--package-path $TRAIN_DIR \
--module-name $MAIN_TRAINER_MODULE \
--job-dir $JOB_DIR \
--region $REGION \
--runtime-version 2.1 \
--python-version 3.7 \
--config config.yaml
작업이 올바르게 생성되었다면 AI Platform Console의 작업 섹션으로 이동하여 로그를 모니터링합니다.
3단계: 작업 모니터링
콘솔의 작업 섹션에서 방금 시작한 작업을 클릭하여 세부정보를 확인합니다.
첫 번째 시도가 시작되면 각 시도에 대해 선택된 초매개변수 값을 볼 수 있습니다.
시도가 완료되면 최적화 측정항목의 결과 값 (이 경우 val_mse
)이 여기에 기록됩니다. 작업을 실행하는 데 15~20분이 소요되며 작업이 완료되면 대시보드가 다음과 같이 표시됩니다 (정확한 값은 다를 수 있음).
잠재적 문제를 디버그하고 작업을 자세히 모니터링하려면 작업 세부정보 페이지에서 로그 보기를 클릭합니다.
모델 학습 코드의 모든 print()
문이 여기에 표시됩니다. 문제가 발생하면 print 문을 더 추가하고 새 학습 작업을 시작해 보세요.
학습 작업이 완료되면 가장 낮은 val_mse를 산출한 초매개변수를 찾습니다. 이를 사용하여 모델의 최종 버전을 학습시키고 내보내거나 추가 초매개변수 조정 시도로 다른 학습 작업을 시작하기 위한 지침으로 사용할 수 있습니다.
7. 삭제
이 노트북을 계속 사용하려면 사용하지 않을 때 노트북을 끄는 것이 좋습니다. Cloud 콘솔의 Notebooks UI에서 노트북을 선택한 다음 중지를 선택합니다.
이 실습에서 만든 모든 리소스를 삭제하려면 노트북 인스턴스를 중지하는 대신 삭제하면 됩니다.
Cloud 콘솔의 탐색 메뉴를 사용하여 Storage로 이동하고 모델 애셋을 저장하기 위해 만든 두 버킷을 모두 삭제합니다.