آموزش و تنظیم هایپرپارامتر مدل PyTorch در پلتفرم Cloud AI

۱. مرور کلی

در این آزمایشگاه، شما یک گردش کار کامل آموزش یادگیری ماشین را در Google Cloud با استفاده از PyTorch برای ساخت مدل خود طی خواهید کرد. از یک محیط Cloud AI Platform Notebooks، یاد خواهید گرفت که چگونه کار آموزشی خود را برای اجرای آن در AI Platform Training با تنظیم هایپرپارامتر، بسته‌بندی کنید.

آنچه یاد می‌گیرید

شما یاد خواهید گرفت که چگونه:

  • یک نمونه نوت‌بوک پلتفرم هوش مصنوعی ایجاد کنید
  • ایجاد یک مدل PyTorch
  • مدل خود را با تنظیم هایپرپارامتر در آموزش پلتفرم هوش مصنوعی آموزش دهید

هزینه کل اجرای این آزمایشگاه در گوگل کلود حدود ۱ دلار است.

۲. محیط خود را راه‌اندازی کنید

برای اجرای این codelab به یک پروژه Google Cloud Platform با قابلیت پرداخت صورتحساب نیاز دارید. برای ایجاد یک پروژه، دستورالعمل‌های اینجا را دنبال کنید.

مرحله ۱: فعال کردن API مدل‌های پلتفرم هوش مصنوعی ابری

به بخش مدل‌های پلتفرم هوش مصنوعی در کنسول ابری خود بروید و اگر از قبل فعال نشده است، روی فعال کردن کلیک کنید.

d0d38662851c6af3.png

مرحله ۲: فعال کردن رابط برنامه‌نویسی کاربردی موتور محاسبات

به Compute Engine بروید و اگر از قبل فعال نشده است، آن را فعال کنید . برای ایجاد نمونه نوت‌بوک خود به این مورد نیاز خواهید داشت.

مرحله ۳: ایجاد یک نمونه از نوت‌بوک‌های پلتفرم هوش مصنوعی

به بخش AI Platform Notebooks در Cloud Console خود بروید و روی New Instance کلیک کنید. سپس آخرین نوع نمونه PyTorch (بدون GPU) را انتخاب کنید:

892b7588f940d145.png

از گزینه‌های پیش‌فرض استفاده کنید یا در صورت تمایل، یک نام دلخواه به آن بدهید و سپس روی «ایجاد» کلیک کنید. پس از ایجاد نمونه، «باز کردن JupyterLab» را انتخاب کنید:

63d2cf44801c2df5.png

سپس، یک نمونه از نوت‌بوک پایتون ۳ را از لانچر باز کنید:

de4c86c6c7f9438f.png

شما آماده شروع هستید!

مرحله ۵: وارد کردن بسته‌های پایتون

در سلول اول دفترچه یادداشت خود، موارد زیر را وارد کرده و سلول را اجرا کنید. می‌توانید آن را با فشار دادن دکمه فلش سمت راست در منوی بالا یا فشار دادن کلید ترکیبی command-enter اجرا کنید:

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

متوجه خواهید شد که ما اینجا PyTorch را وارد نمی‌کنیم. دلیلش این است که ما کار آموزشی را روی AI Platform Training اجرا می‌کنیم، نه از نمونه Notebook خودمان.

۳. یک بسته برای کار آموزشی ایجاد کنید

برای اجرای کار آموزشی خود در AI Platform Training، به کد آموزشی خود که به صورت محلی در نمونه Notebooks ما بسته‌بندی شده است و یک مخزن ذخیره‌سازی ابری برای ذخیره دارایی‌های مربوط به کارمان نیاز داریم. ابتدا، یک مخزن ذخیره‌سازی ایجاد می‌کنیم. اگر از قبل یکی دارید، می‌توانید از این مرحله صرف نظر کنید.

مرحله ۱: ایجاد یک فضای ذخیره‌سازی ابری برای مدل ما

بیایید ابتدا برخی از متغیرهای محیطی را که در ادامه‌ی کد از آنها استفاده خواهیم کرد، تعریف کنیم. مقادیر زیر را با نام پروژه‌ی گوگل کلود خود و نام باکت ذخیره‌سازی ابری که می‌خواهید ایجاد کنید، پر کنید (باید به صورت سراسری منحصر به فرد باشد):

# 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

مرحله ۲: ایجاد فایل‌های اولیه برای بسته پایتون

برای اجرای یک کار آموزشی در پلتفرم هوش مصنوعی، باید کد خود را به عنوان یک بسته پایتون پیکربندی کنیم. این شامل یک فایل 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.'
)

در مرحله بعد، بیایید دایرکتوری train/ و فایل خالی init.py را درون آن ایجاد کنیم. پایتون از این فایل برای تشخیص اینکه این یک بسته است استفاده می‌کند:

!mkdir trainer
!touch trainer/__init__.py

اکنون آماده‌ایم تا ایجاد شغل آموزشی خود را آغاز کنیم.

۴. پیش‌نمایش مجموعه داده‌ها

تمرکز این آزمایشگاه بر روی ابزارهای آموزش مدل‌ها است، اما بیایید نگاهی سریع به مجموعه داده‌هایی که برای آموزش مدل خود جهت درک آن استفاده خواهیم کرد، بیندازیم. ما از مجموعه داده‌های مربوط به تولد موجود در BigQuery استفاده خواهیم کرد. این مجموعه شامل داده‌های تولد از ایالات متحده در طول چندین دهه است. ما از چند ستون از این مجموعه داده‌ها برای پیش‌بینی وزن هنگام تولد نوزاد استفاده خواهیم کرد. مجموعه داده‌های اصلی بسیار بزرگ است و ما از زیرمجموعه‌ای از آن که در یک فضای ذخیره‌سازی ابری در اختیار شما قرار داده‌ایم، استفاده خواهیم کرد.

مرحله ۱: دانلود مجموعه داده‌های مربوط به تولد در BigQuery

بیایید نسخه‌ای از مجموعه داده‌ای که در فضای ذخیره‌سازی ابری در اختیار شما قرار داده‌ایم را در یک قاب داده Pandas دانلود کنیم و پیش‌نمایشی از آن را ببینیم.

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

این مجموعه داده کمی کمتر از ۱۰۰۰۰۰ ردیف دارد. ما از ۵ ویژگی برای پیش‌بینی وزن هنگام تولد نوزاد استفاده خواهیم کرد: سن مادر و پدر، هفته‌های بارداری، افزایش وزن مادر به پوند و جنسیت نوزاد که به صورت بولی نمایش داده می‌شود.

۵. تعریف کار آموزشی با تنظیم فراپارامتر

ما اسکریپت آموزشی خود را در فایلی به نام model.py در زیرشاخه trainer/ که قبلاً ایجاد کردیم، خواهیم نوشت. کار آموزشی ما روی AI Platform Training اجرا خواهد شد و همچنین از سرویس تنظیم هایپرپارامترهای AI Platform برای یافتن هایپرپارامترهای بهینه برای مدل ما با استفاده از بهینه‌سازی بیزی استفاده خواهد کرد.

مرحله ۱: ایجاد اسکریپت آموزشی

ابتدا، بیایید فایل پایتون را با اسکریپت آموزشی خود ایجاد کنیم. سپس آنچه را که در آن اتفاق می‌افتد، بررسی خواهیم کرد. اجرای دستور %%writefile کد مدل را در یک فایل پایتون محلی می‌نویسد:

%%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() : این تابع آرگومان‌های خط فرمانی که هنگام ایجاد کار آموزشی خود ارسال خواهیم کرد، به همراه ابرپارامترهایی که می‌خواهیم پلتفرم هوش مصنوعی آنها را بهینه کند، تجزیه می‌کند. در این مثال، لیست آرگومان‌های ما فقط شامل ابرپارامترهایی است که می‌خواهیم بهینه کنیم - نرخ یادگیری مدل، تکانه و تعداد نورون‌ها در لایه پنهان ما.
  • train_model() : در اینجا داده‌ها را در یک قاب داده Pandas دانلود می‌کنیم، آن را نرمال‌سازی می‌کنیم، به تانسورهای PyTorch تبدیل می‌کنیم و سپس مدل خود را تعریف می‌کنیم. برای ساخت مدل خود، از API مربوط به PyTorch nn.Sequential استفاده می‌کنیم که به ما امکان می‌دهد مدل خود را به عنوان پشته‌ای از لایه‌ها تعریف کنیم:
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
                      nn.ReLU(),
                      nn.Linear(args.hidden_layer_size, 1))

توجه داشته باشید که به جای کدنویسی دقیق اندازه لایه پنهان مدل، ما این را به یک پارامتر فوق العاده تبدیل می‌کنیم که پلتفرم هوش مصنوعی آن را برای ما تنظیم می‌کند. در بخش بعدی بیشتر در این مورد صحبت خواهیم کرد.

مرحله ۲: استفاده از سرویس تنظیم فراپارامتر پلتفرم هوش مصنوعی

به جای اینکه به صورت دستی مقادیر مختلف هایپرپارامتر را امتحان کنیم و هر بار مدل خود را دوباره آموزش دهیم، از سرویس بهینه‌سازی هایپرپارامتر پلتفرم هوش مصنوعی ابری استفاده خواهیم کرد. اگر کار آموزشی خود را با آرگومان‌های هایپرپارامتر تنظیم کنیم، پلتفرم هوش مصنوعی از بهینه‌سازی بیزی برای یافتن مقادیر ایده‌آل برای هایپرپارامترهایی که مشخص می‌کنیم استفاده خواهد کرد.

در تنظیم هایپرپارامتر، یک آزمایش واحد شامل یک اجرای آموزشی از مدل ما با ترکیبی خاص از مقادیر هایپرپارامتر است. بسته به تعداد آزمایش‌هایی که اجرا می‌کنیم، پلتفرم هوش مصنوعی از نتایج آزمایش‌های تکمیل‌شده برای بهینه‌سازی هایپرپارامترهایی که برای آزمایش‌های آینده انتخاب می‌کند، استفاده خواهد کرد. برای پیکربندی تنظیم هایپرپارامتر، باید هنگام شروع کار آموزشی خود، یک فایل پیکربندی با برخی داده‌ها در مورد هر یک از هایپرپارامترهایی که بهینه‌سازی می‌کنیم، ارسال کنیم.

سپس، آن فایل پیکربندی را به صورت محلی ایجاد کنید:

%%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() در بالا، هر بار که یک آزمایش کامل می‌شود، این معیار را به پلتفرم هوش مصنوعی گزارش می‌دهیم. در اینجا ما میانگین مربعات خطای مدل خود را به حداقل می‌رسانیم و بنابراین می‌خواهیم از ابرپارامترهایی استفاده کنیم که منجر به کمترین میانگین مربعات خطا برای مدل ما می‌شوند. نام این معیار ( val_mse ) با نامی که هنگام فراخوانی report_hyperparameter_tuning_metric() در پایان یک آزمایش برای گزارش آن استفاده می‌کنیم، مطابقت دارد.

۶. یک کار آموزشی را در پلتفرم هوش مصنوعی اجرا کنید

در این بخش، کار آموزش مدل خود را با تنظیم هایپرپارامتر در پلتفرم هوش مصنوعی آغاز خواهیم کرد.

مرحله ۱: تعریف برخی متغیرهای محیطی

بیایید ابتدا چند متغیر محیطی تعریف کنیم که برای شروع کار آموزشی خود از آنها استفاده خواهیم کرد. اگر می‌خواهید کار خود را در منطقه دیگری اجرا کنید، متغیر REGION را در زیر به‌روزرسانی کنید:

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

هر شغل آموزشی در پلتفرم هوش مصنوعی باید یک نام منحصر به فرد داشته باشد. برای تعریف یک متغیر برای نام شغل خود با استفاده از یک مهر زمانی، دستور زیر را اجرا کنید:

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

مرحله ۲: شروع کار آموزشی

ما کار آموزشی خود را با استفاده از 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

اگر شغل شما به درستی ایجاد شده است، برای نظارت بر گزارش‌ها به بخش مشاغل کنسول پلتفرم هوش مصنوعی خود بروید.

مرحله ۳: شغل خود را زیر نظر داشته باشید

وقتی در بخش مشاغل کنسول هستید، روی شغلی که تازه شروع کرده‌اید کلیک کنید تا جزئیات آن را مشاهده کنید:

c184167641bb7ed7.png

با شروع دور اول آزمایش‌های شما، می‌توانید مقادیر هایپرپارامتر انتخاب شده برای هر آزمایش را مشاهده کنید:

787c053ef9110e6b.png

با تکمیل آزمایش‌ها، مقدار حاصل از معیار بهینه‌سازی شما (در این مورد val_mse ) در اینجا ثبت می‌شود. اجرای کار باید ۱۵ تا ۲۰ دقیقه طول بکشد و داشبورد پس از پایان کار چیزی شبیه به این خواهد بود (مقادیر دقیق متفاوت خواهند بود):

47ef6b9b4ecb532c.png

برای رفع مشکلات احتمالی و نظارت دقیق‌تر بر کار خود، از صفحه جزئیات کارها روی «مشاهده گزارش‌ها» کلیک کنید:

18c32dcd36351930.png

هر دستور print() در کد آموزش مدل شما در اینجا نمایش داده می‌شود. اگر با مشکلی مواجه شدید، سعی کنید دستورات print بیشتری اضافه کنید و یک کار آموزشی جدید را شروع کنید.

پس از اتمام کار آموزشی، ابرپارامترهایی را که کمترین مقدار val_mse را داشته‌اند، پیدا کنید. می‌توانید از این پارامترها برای آموزش و خروجی گرفتن از نسخه نهایی مدل خود استفاده کنید، یا از آنها به عنوان راهنما برای شروع یک کار آموزشی دیگر با آزمایش‌های تنظیم ابرپارامترهای اضافی استفاده کنید.

۷. پاکسازی

اگر می‌خواهید به استفاده از این دفترچه یادداشت ادامه دهید، توصیه می‌شود وقتی از آن استفاده نمی‌کنید، آن را خاموش کنید. از رابط کاربری دفترچه یادداشت‌ها در کنسول ابری خود، دفترچه یادداشت را انتخاب کرده و سپس توقف را انتخاب کنید:

879147427150b6c7.png

اگر می‌خواهید تمام منابعی را که در این آزمایشگاه ایجاد کرده‌اید حذف کنید، به جای متوقف کردن آن، کافیست نمونه نوت‌بوک را حذف کنید.

با استفاده از منوی ناوبری در کنسول ابری خود، به بخش ذخیره‌سازی (Storage) بروید و هر دو باکتی را که برای ذخیره دارایی‌های مدل خود ایجاد کرده‌اید، حذف کنید.