1. סקירה כללית
בשיעור ה-Lab הזה תלמדו על תהליך העבודה המלא של אימון למידת מכונה ב-Google Cloud, באמצעות PyTorch כדי לפתח את המודל שלכם. בסביבת Cloud AI Platform Notebooks, תלמדו איך לארוז את משימת האימון כדי להריץ אותה באימון AI Platform באמצעות כוונון היפר-פרמטרים.
מה לומדים
נסביר לכם איך:
- יצירת מכונה של AI Platform Notebooks
- יצירת מודל PyTorch
- לאמן את המודל באמצעות כוונון היפר-פרמטרים באימון AI Platform
העלות הכוללת של הפעלת שיעור ה-Lab הזה ב-Google Cloud היא כ-$1.
2. הגדרת הסביבה
כדי להריץ את ה-Codelab הזה צריך פרויקט ב-Google Cloud Platform שהחיוב מופעל בו. כדי ליצור פרויקט, יש לפעול לפי ההוראות האלה.
שלב 1: הפעלת Cloud AI Platform Models API
עוברים לקטע 'מודלים של AI Platform במסוף Cloud ולוחצים על 'הפעלה' אם הוא עדיין לא מופעל.
שלב 2: מפעילים את Compute Engine API
עוברים אל Compute Engine ובוחרים באפשרות Enable (הפעלה) אם היא לא מופעלת עדיין. תצטרכו את הקישור הזה כדי ליצור מכונה של ה-notebook.
שלב 3: יצירת מכונה של AI Platform Notebooks
עוברים אל הקטע 'notebooks של AI Platform' במסוף Cloud ולוחצים על New Instance. לאחר מכן בוחרים את סוג המכונה האחרון של PyTorch (ללא מעבדי GPU):
אפשר להשתמש באפשרויות ברירת המחדל או לתת לו שם מותאם אישית אם רוצים, ולאחר מכן ללחוץ על יצירה. אחרי שיוצרים את המכונה, בוחרים באפשרות Open JupyterLab:
לאחר מכן, פותחים מופע של Python 3 Notebook במרכז האפליקציות:
הכול מוכן. עכשיו אפשר להתחיל.
שלב 5: מייבאים חבילות Python
בתא הראשון של ה-notebook, מוסיפים את פעולות הייבוא הבאות ומריצים את התא. אפשר להריץ אותו על ידי לחיצה על לחצן החץ ימינה בתפריט העליון או על ידי הקשה על מקש Enter:
import datetime
import numpy as np
import os
import pandas as pd
import time
תוכלו לראות שאנחנו לא מייבאים כאן את PyTorch. הסיבה לכך היא שאנחנו מריצים את משימת האימון בהדרכה של AI Platform, ולא במכונה של ה-notebook.
3. יצירת חבילה למשימת האימון
כדי להריץ את משימת האימון על הדרכת AI Platform, אנחנו זקוקים לקוד האימון שלנו שנארז באופן מקומי במכונה של 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
הבאה מתוך ה-notebook כדי ליצור קטגוריה:
!gsutil mb $BUCKET_URL
שלב 2: יוצרים את הקבצים הראשוניים לחבילת Python
כדי להריץ משימת אימון על AI Platform, צריך להגדיר את הקוד שלנו כחבילת Python. הקובץ הזה מורכב מקובץ setup.py
בתיקיית השורש שלנו שמציין יחסי תלות של חבילות חיצוניות, מספריית משנה עם שם החבילה שלנו (כאן ייקרא trainer/
) ומקובץ __init__.py
ריק בתוך ספריית המשנה הזו.
קודם כל, נכתוב את הקובץ setup.py שלנו. אנחנו משתמשים בקסם %%writefile של iPython כדי לשמור את הקובץ במכונה שלנו. ברשימה הזו מפורטות 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.'
)
השלב הבא הוא ליצור את הספרייה/ של המדריך שלנו ואת הקובץ init.py הריק שבתוכה. אפליקציית Python משתמשת בקובץ הזה כדי לזהות שזו חבילה:
!mkdir trainer
!touch trainer/__init__.py
עכשיו אנחנו מוכנים להתחיל ליצור את משימת האימון שלנו.
4. תצוגה מקדימה של מערך הנתונים
שיעור ה-Lab הזה מתמקד בכלים לאימון מודלים, אבל בואו נסתכל בקצרה על מערך הנתונים שבו נשתמש כדי לאמן את המודל שלנו להבין. נשתמש במערך הנתונים של שיעור הלידה שזמין ב-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 תכונות כדי לחזות את משקל הלידה של תינוק: גיל האם והאבא, שבועות היריון, עלייה במשקל של האם בקילוגרמים ומגדר התינוק שמיוצג כערך בוליאני.
5. הגדרה של משימת האימון באמצעות כוונון היפר-פרמטרים
נכתוב את סקריפט האימון שלנו לקובץ בשם model.py בספריית המשנה/ המדריך שיצרנו קודם. משימת האימון שלנו תפעל באימון AI Platform, ותתבסס גם על שירות כוונון ההיפר-פרמטרים של AI Platform כדי למצוא את ההיפר-פרמטרים האופטימליים למודל שלנו תוך שימוש באופטימיזציה בייסיאנית.
שלב 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 Tensor ואז מגדירים את המודל שלנו. כדי לבנות את המודל אנחנו משתמשים ב-API של PyTorchnn.Sequential
, שמאפשר להגדיר את המודל שלנו כערימה של שכבות:
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 תשתמש באופטימיזציה בייסיאנית כדי למצוא את הערכים האידיאליים להיפר-פרמטרים שנציין.
בכוונון היפר-פרמטרים, ניסוי בודד מורכב מהרצת אימון אחת של המודל שלנו עם שילוב ספציפי של ערכי היפר-פרמטרים. בהתאם למספר הניסויים שאנחנו מפעילים, 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: מתחילים את משימת האימון
ניצור את משימת האימון באמצעות gcloud, Google Cloud CLI. אנחנו יכולים להריץ את הפקודה הזו ישירות ב-notebook, תוך התייחסות למשתנים שהגדרנו למעלה:
!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 במסוף AI Platform כדי לעקוב אחר היומנים.
שלב 3: עוקבים אחרי העבודה
כשמגיעים לקטע 'משימות' במסוף, לוחצים על המשימה שהתחלתם להציג כדי להציג את הפרטים שלה:
כשסבב הניסיונות הראשון יתחיל, תוכלו לראות את ערכי ההיפר-פרמטרים שנבחרו לכל ניסוי:
בסיום תקופת הניסיון, הערך שיתקבל ממדד האופטימיזציה (במקרה הזה val_mse
) יתועד כאן. הרצת המשימה אמורה להימשך 15-20 דקות, ומרכז הבקרה ייראה בערך כך בסיום המשימה (הערכים המדויקים ישתנו):
כדי לנפות באגים שקשורים לבעיות פוטנציאליות ולעקוב אחרי המשימה בפירוט רב יותר, לוחצים על הצגת היומנים בדף הפרטים של המשימות:
כל הצהרה לגבי print()
בקוד לאימון המודל תופיע כאן. אם נתקלת בבעיות, כדאי לנסות להוסיף עוד דפי הדפסה ולהתחיל משימת אימון חדשה.
כשמשימת האימון תסתיים, מצאו את ההיפר-פרמטרים שהניבו את ערך ה-val_mse הנמוך ביותר. תוכלו להשתמש בהם כדי לאמן ולייצא גרסה סופית של המודל, או להשתמש בהם כהדרכה כדי להתחיל משימת אימון נוספת עם ניסויים נוספים של כוונון היפר-פרמטרים.
7. הסרת המשאבים
אם ברצונך להמשיך להשתמש ב-notebook הזה, מומלץ להשבית אותו כשהוא לא בשימוש. בממשק המשתמש של Notebooks במסוף Cloud, בוחרים את ה-notebook ואז לוחצים על Stop (עצירה):
כדי למחוק את כל המשאבים שיצרתם בשיעור ה-Lab הזה, תוכלו פשוט למחוק את המכונה של ה-notebook במקום לעצור אותה.
באמצעות תפריט הניווט במסוף Cloud, עוברים לקטע 'אחסון' ומוחקים את שתי הקטגוריות שיצרתם לצורך אחסון הנכסים של המודלים.