Pelatihan dan penyesuaian hyperparameter model PyTorch di Cloud AI Platform

1. Ringkasan

Di lab ini, Anda akan mempelajari alur kerja pelatihan ML lengkap di Google Cloud, menggunakan PyTorch untuk membangun model. Dari lingkungan Cloud AI Platform Notebooks, Anda akan mempelajari cara memaketkan tugas pelatihan untuk menjalankannya di AI Platform Training dengan penyesuaian hyperparameter.

Yang Anda pelajari

Anda akan mempelajari cara:

  • Membuat instance AI Platform Notebooks
  • Membuat model PyTorch
  • Melatih model dengan penyesuaian hyperparameter di AI Platform Training

Total biaya untuk menjalankan lab ini di Google Cloud adalah sekitar $1.

2. Menyiapkan lingkungan Anda

Anda memerlukan project Google Cloud Platform dengan penagihan yang diaktifkan untuk menjalankan codelab ini. Untuk membuat project, ikuti petunjuk di sini.

Langkah 1: Aktifkan Cloud AI Platform Models API

Buka bagian Model AI Platform di Konsol Cloud Anda, lalu klik Aktifkan jika belum diaktifkan.

d0d38662851c6af3.png

Langkah 2: Aktifkan Compute Engine API

Buka Compute Engine dan pilih Aktifkan jika belum diaktifkan. Anda akan memerlukan ini untuk membuat instance notebook.

Langkah 3: Buat instance AI Platform Notebooks

Buka bagian AI Platform Notebooks di Cloud Console Anda, lalu klik Instance Baru. Kemudian, pilih jenis instance PyTorch terbaru (tanpa GPU):

892b7588f940d145.png

Gunakan opsi default atau beri nama kustom jika Anda mau, lalu klik Buat. Setelah instance dibuat, pilih Open JupyterLab:

63d2cf44801c2df5.png

Selanjutnya, buka instance Notebook Python 3 dari peluncur:

de4c86c6c7f9438f.png

Anda sudah siap untuk memulai!

Langkah 5: Impor paket Python

Di sel pertama notebook Anda, tambahkan impor berikut dan jalankan sel. Anda dapat menjalankannya dengan menekan tombol panah kanan di menu atas atau menekan command-enter:

import datetime
import numpy as np
import os
import pandas as pd
import time

Anda akan melihat bahwa kita tidak mengimpor PyTorch di sini. Hal ini karena kita menjalankan tugas pelatihan di AI Platform Training, bukan dari instance Notebook.

3. Buat paket untuk tugas pelatihan

Untuk menjalankan tugas pelatihan di AI Platform Training, kita memerlukan kode pelatihan yang dikemas secara lokal di instance Notebook, dan bucket Cloud Storage untuk menyimpan aset tugas. Pertama, kita akan membuat bucket penyimpanan. Anda dapat melewati langkah ini jika sudah memilikinya.

Langkah 1: Buat bucket Cloud Storage untuk model kita

Pertama, mari kita tentukan beberapa variabel lingkungan yang akan kita gunakan di seluruh codelab ini. Isi nilai di bawah dengan nama project Google Cloud Anda dan nama bucket Cloud Storage yang ingin Anda buat (harus unik secara global):

# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'

Sekarang kita siap membuat bucket penyimpanan, yang akan kita tunjuk saat memulai tugas pelatihan.

Jalankan perintah gsutil ini dari dalam notebook Anda untuk membuat bucket:

!gsutil mb $BUCKET_URL

Langkah 2: Buat file awal untuk paket Python kita

Untuk menjalankan tugas pelatihan di AI Platform, kita perlu mengonfigurasi kode sebagai paket Python. Ini terdiri dari file setup.py di direktori root yang menentukan dependensi paket eksternal, subdirektori dengan nama paket (di sini kita akan menyebutnya trainer/), dan file __init__.py kosong dalam subdirektori ini.

Pertama, mari kita tulis file setup.py. Kita menggunakan %%writefile magics iPython untuk menyimpan file ke instance kita. Di sini kita telah menentukan 3 library eksternal yang akan kita gunakan dalam kode pelatihan: PyTorch, Scikit-learn, dan 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.'
)

Selanjutnya, buat direktori trainer/ dan file init.py kosong di dalamnya. Python menggunakan file ini untuk mengenali bahwa ini adalah paket:

!mkdir trainer
!touch trainer/__init__.py

Sekarang kita siap untuk mulai membuat tugas pelatihan.

4. Melihat pratinjau set data

Lab ini berfokus pada alat untuk melatih model di sini, tetapi mari kita lihat sekilas set data yang akan kita gunakan untuk melatih model kita agar dapat dipahami. Kita akan menggunakan set data kelahiran yang tersedia di BigQuery. Set data ini berisi data kelahiran dari AS selama beberapa dekade. Kita akan menggunakan beberapa kolom dari set data untuk memprediksi berat badan bayi saat lahir. Dataset asli cukup besar, dan kita akan menggunakan subset yang telah kami sediakan untuk Anda di bucket Cloud Storage.

Langkah 1: Mendownload set data kelahiran BigQuery

Mari kita download versi set data yang telah kami sediakan untuk Anda di Cloud Storage ke Pandas DataFrame dan lihat pratinjaunya.

natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()

Set data ini memiliki kurang dari 100.000 baris. Kita akan menggunakan 5 fitur untuk memprediksi berat lahir bayi: usia ibu dan ayah, minggu kehamilan, kenaikan berat badan ibu dalam pound, dan jenis kelamin bayi yang ditampilkan sebagai boolean.

5. Tentukan tugas pelatihan dengan penyesuaian hyperparameter

Kita akan menulis skrip pelatihan ke file bernama model.py dalam subdirektori trainer/ yang kita buat sebelumnya. Tugas pelatihan kita akan berjalan di AI Platform Training, dan juga akan menggunakan layanan penyesuaian hyperparameter AI Platform untuk menemukan hyperparameter yang optimal untuk model kita menggunakan pengoptimalan Bayesian.

Langkah 1: Buat skrip pelatihan

Pertama, mari buat file Python dengan skrip pelatihan kita. Kemudian, kita akan menganalisis apa yang terjadi di dalamnya. Menjalankan perintah %%writefile ini akan menulis kode model ke file Python lokal:

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

Tugas pelatihan terdiri dari dua fungsi yang melakukan sebagian besar pekerjaan.

  • get_args(): Mengurai argumen command line yang akan kita teruskan saat membuat tugas pelatihan, beserta hyperparameter yang ingin dioptimalkan AI Platform. Dalam contoh ini, daftar argumen kita hanya mencakup hyperparameter yang akan kita optimalkan – kecepatan pembelajaran model, momentum, dan jumlah neuron di lapisan tersembunyi.
  • train_model(): Di sini kita mendownload data ke Pandas DataFrame, menormalisasinya, mengonversinya ke PyTorch Tensor, lalu menentukan model kita. Untuk membuat model, kita menggunakan PyTorch nn.Sequential API, yang memungkinkan kita menentukan model sebagai stack lapisan:
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
                      nn.ReLU(),
                      nn.Linear(args.hidden_layer_size, 1))

Perhatikan bahwa alih-alih meng-hardcode ukuran lapisan tersembunyi model, kita menjadikannya hyperparameter yang akan disesuaikan oleh AI Platform untuk kita. Informasi selengkapnya akan dibahas di bagian berikutnya.

Langkah 2: Menggunakan layanan penyesuaian hyperparameter AI Platform

Daripada mencoba nilai hyperparameter yang berbeda secara manual dan melatih ulang model setiap kali, kita akan menggunakan layanan pengoptimalan hyperparameter Cloud AI Platform. Jika kita menyiapkan tugas pelatihan dengan argumen hyperparameter, AI Platform akan menggunakan pengoptimalan Bayesian untuk menemukan nilai ideal bagi hyperparameter yang kita tentukan.

Dalam penyesuaian hyperparameter, satu uji coba terdiri dari satu proses pelatihan model dengan kombinasi nilai hyperparameter tertentu. Bergantung pada jumlah uji coba yang kita jalankan, AI Platform akan menggunakan hasil uji coba yang telah selesai untuk mengoptimalkan hyperparameter yang dipilihnya untuk uji coba berikutnya. Untuk mengonfigurasi penyesuaian hyperparameter, kita perlu meneruskan file konfigurasi saat memulai tugas pelatihan dengan beberapa data pada setiap hyperparameter yang kita optimalkan.

Selanjutnya, buat file konfigurasi tersebut secara lokal:

%%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

Untuk setiap hyperparameter, kita menentukan jenis, rentang nilai yang ingin kita telusuri, dan skala untuk meningkatkan nilai di berbagai uji coba.

Di awal tugas, kita juga menentukan metrik yang kita optimalkan. Perhatikan bahwa di akhir fungsi train_model() di atas, kita melaporkan metrik ini ke AI Platform setiap kali uji coba selesai. Di sini, kita meminimalkan mean squared error model, sehingga kita ingin menggunakan hyperparameter yang menghasilkan mean squared error terendah untuk model kita. Nama metrik ini (val_mse) cocok dengan nama yang kami gunakan untuk melaporkannya saat kami memanggil report_hyperparameter_tuning_metric() di akhir uji coba.

6. Menjalankan tugas pelatihan di AI Platform

Di bagian ini, kita akan memulai tugas pelatihan model dengan penyesuaian hyperparameter di AI Platform.

Langkah 1: Tentukan beberapa variabel lingkungan

Pertama, mari kita tentukan beberapa variabel lingkungan yang akan kita gunakan untuk memulai tugas pelatihan. Jika Anda ingin menjalankan tugas di wilayah lain, perbarui variabel REGION di bawah:

MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"

Setiap tugas pelatihan di AI Platform harus memiliki nama yang unik. Jalankan perintah berikut untuk menentukan variabel untuk nama tugas Anda menggunakan stempel waktu:

timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))

Langkah 2: Mulai tugas pelatihan

Kita akan membuat tugas pelatihan menggunakan gcloud, Google Cloud CLI. Kita dapat menjalankan perintah ini langsung di notebook, dengan mereferensikan variabel yang kita tentukan di atas:

!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

Jika tugas Anda dibuat dengan benar, buka bagian Jobs di konsol AI Platform untuk memantau log.

Langkah 3: Pantau pekerjaan Anda

Setelah Anda berada di bagian Jobs di konsol, klik tugas yang baru saja Anda mulai untuk melihat detailnya:

c184167641bb7ed7.png

Saat putaran pertama uji coba dimulai, Anda dapat melihat nilai hyperparameter yang dipilih untuk setiap uji coba:

787c053ef9110e6b.png

Setelah uji coba selesai, nilai metrik pengoptimalan Anda (dalam hal ini val_mse) akan dicatat di sini. Tugas ini akan memerlukan waktu 15-20 menit untuk dijalankan, dan dasbor akan terlihat seperti ini setelah tugas selesai (nilai yang tepat akan bervariasi):

47ef6b9b4ecb532c.png

Untuk men-debug potensi masalah dan memantau tugas Anda secara lebih mendetail, klik Lihat Log dari halaman detail tugas:

18c32dcd36351930.png

Setiap pernyataan print() dalam kode pelatihan model Anda akan muncul di sini. Jika Anda mengalami masalah, coba tambahkan lebih banyak pernyataan cetak dan mulai tugas pelatihan baru.

Setelah tugas pelatihan selesai, temukan hyperparameter yang menghasilkan val_mse terendah. Anda dapat menggunakan hasil ini untuk melatih dan mengekspor versi akhir model, atau menggunakannya sebagai panduan untuk memulai tugas pelatihan lain dengan uji coba penyesuaian hyperparameter tambahan.

7. Pembersihan

Jika Anda ingin terus menggunakan notebook ini, sebaiknya matikan notebook saat tidak digunakan. Dari UI Notebook di Konsol Cloud Anda, pilih notebook, lalu pilih Stop:

879147427150b6c7.png

Jika Anda ingin menghapus semua resource yang telah dibuat di lab ini, cukup hapus instance notebook, bukan menghentikannya.

Menggunakan menu Navigasi di Konsol Cloud, jelajahi Penyimpanan dan hapus kedua bucket yang Anda buat untuk menyimpan aset model.