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

1. بررسی اجمالی

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

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

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

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

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

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

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

مرحله 1: Cloud AI Platforms Models API را فعال کنید

به بخش مدل‌های پلتفرم هوش مصنوعی در Cloud Console خود بروید و اگر قبلاً فعال نشده است روی Enable کلیک کنید.

d0d38662851c6af3.png

مرحله ۲: Compute Engine API را فعال کنید

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

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

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

892b7588f940d145.png

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

63d2cf44801c2df5.png

در مرحله بعد، یک نمونه نوت بوک پایتون 3 را از لانچر باز کنید:

de4c86c6c7f9438f.png

شما برای شروع آماده اید!

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

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

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

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

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

برای اجرای کار آموزشی خود در آموزش پلتفرم هوش مصنوعی، به کد آموزشی خود که به صورت محلی در نمونه Notebook ما بسته بندی شده است، و یک سطل Cloud Storage برای ذخیره دارایی های کارمان نیاز داریم. ابتدا یک سطل ذخیره سازی ایجاد می کنیم. اگر قبلاً یکی را دارید می توانید از این مرحله رد شوید.

مرحله 1: یک سطل Cloud Storage برای مدل خود ایجاد کنید

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

# 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: فایل های اولیه را برای بسته پایتون خود ایجاد کنید

برای اجرای یک کار آموزشی در پلتفرم هوش مصنوعی، باید کد خود را به عنوان یک بسته پایتون پیکربندی کنیم. این شامل یک فایل setup.py در دایرکتوری ریشه ما است که وابستگی های بسته خارجی را مشخص می کند، یک زیر شاخه با نام بسته ما (در اینجا ما آن را trainer/ می نامیم)، و یک فایل __init__.py خالی در این زیر شاخه.

ابتدا بیایید فایل setup.py خود را بنویسیم. ما از iPython %%writefile magic برای ذخیره فایل در نمونه خود استفاده می کنیم. در اینجا ما 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 را در آن ایجاد می کنیم. پایتون از این فایل برای تشخیص اینکه این یک بسته است استفاده می کند:

!mkdir trainer
!touch trainer/__init__.py

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

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

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

مرحله 1: دانلود مجموعه داده natality BigQuery

بیایید نسخه مجموعه داده‌ای را که در Cloud Storage برای شما در دسترس قرار داده‌ایم در Pandas DataFrame دانلود کرده و پیش‌نمایش آن را مشاهده کنید.

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

این مجموعه داده کمتر از 100000 ردیف دارد. ما از 5 ویژگی برای پیش‌بینی وزن نوزاد در هنگام تولد استفاده خواهیم کرد: سن مادر و پدر، هفته‌های بارداری، افزایش وزن مادر بر حسب پوند، و جنسیت نوزاد که به‌عنوان یک بولین نشان داده می‌شود.

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

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

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

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

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

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

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

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

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

%%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() فرا می‌خوانیم.

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

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

مرحله 1: برخی از متغیرهای محیطی را تعریف کنید

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

مرحله 2: کار آموزشی را آغاز کنید

ما کار آموزشی خود را با استفاده از gcloud، Google Cloud CLI ایجاد خواهیم کرد. ما می توانیم این دستور را مستقیماً در نوت بوک خود اجرا کنیم و به متغیرهایی که در بالا تعریف کردیم ارجاع دهیم:

!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

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

مرحله 3: بر کار خود نظارت کنید

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

c184167641bb7ed7.png

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

787c053ef9110e6b.png

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

47ef6b9b4ecb532c.png

برای اشکال زدایی مشکلات احتمالی و نظارت بر کار خود با جزئیات بیشتر، روی View Logs از صفحه جزئیات مشاغل کلیک کنید:

18c32dcd36351930.png

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

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

7. پاکسازی

اگر می خواهید به استفاده از این نوت بوک ادامه دهید، توصیه می شود در صورت عدم استفاده آن را خاموش کنید. از رابط کاربری Notebooks در Cloud Console خود، نوت بوک را انتخاب کنید و سپس Stop را انتخاب کنید:

879147427150b6c7.png

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

با استفاده از منوی پیمایش در Cloud Console، به Storage بروید و هر دو سطل را که برای ذخیره دارایی های مدل خود ایجاد کرده اید حذف کنید.