1. סקירה כללית
בשיעור ה-Lab הזה נשתמש ב-Vertex AI כדי להריץ משימת כוונון היפר-פרמטרים באימון של Vertex AI.
שיעור ה-Lab הזה הוא חלק מסדרת הסרטונים מאב טיפוס לייצור. חשוב להשלים את שיעור ה-Lab הקודם לפני שמנסים את השיעור הזה. אפשר לצפות בסדרת הסרטונים המצורפת כדי לקבל מידע נוסף:
.
מה תלמדו
תלמדו איך:
- שינוי קוד האפליקציה של האימון לצורך כוונון אוטומטי של פרמטרים היפר
- הגדרה והפעלה של משימת כוונון של היפר-פרמטרים באמצעות Vertex AI Python SDK
העלות הכוללת להרצת הסדנה הזו ב-Google Cloud היא כ-$1.
2. מבוא ל-Vertex AI
במעבדה הזו נעשה שימוש במוצרי ה-AI החדשים ביותר שזמינים ב-Google Cloud. Vertex AI משלבת את חבילות ה-ML ב-Google Cloud לחוויית פיתוח חלקה. בעבר, ניתן היה לגשת למודלים שעברו אימון באמצעות AutoML ומודלים בהתאמה אישית דרך שירותים נפרדים. המוצר החדש משלב את כל ממשקי ה-API האלה בממשק API אחד, לצד מוצרים חדשים אחרים. אפשר גם להעביר פרויקטים קיימים ל-Vertex AI.
Vertex AI כולל מוצרים רבים ושונים לתמיכה בתהליכי עבודה של למידת מכונה מקצה לקצה. בשיעור ה-Lab הזה נתמקד במוצרים הבאים: Training ו-Workbench
3. הגדרת הסביבה
כדי להגדיר את הסביבה, מבצעים את השלבים במאמר אימון מודלים מותאמים אישית באמצעות Vertex AI.
4. אריזה בקונטיינר של קוד אפליקציית האימון
כדי לשלוח את משימת האימון הזו ל-Vertex AI, צריך להכניס את הקוד של אפליקציית האימון לקונטיינר של Docker ולהעביר אותו בדחיפה אל Google Artifact Registry. בעזרת הגישה הזו, אפשר לאמן ולכוונן מודל שנוצר בכל מסגרת.
כדי להתחיל, פותחים חלון טרמינל מתפריט Launcher של ה-notebook ב-Workbench שיצרתם בסדנאות הקודמות.
שלב 1: כותבים קוד לאימון
יוצרים ספרייה חדשה בשם flowers-hptune
ומוסיפים אליה cd:
mkdir flowers-hptune
cd flowers-hptune
מריצים את הפקודות הבאות כדי ליצור ספרייה לקוד האימון וקובץ Python שבו מוסיפים את הקוד שבהמשך.
mkdir trainer
touch trainer/task.py
עכשיו אמורים להיות בספרייה flowers-hptune/
הפריטים הבאים:
+ trainer/
+ task.py
אחר כך פותחים את הקובץ task.py
שיצרתם ומעתיקים את הקוד שבהמשך.
צריך להחליף את {your-gcs-bucket}
באפליקציה BUCKET_ROOT
בקטגוריה של Cloud Storage שבה אחסנתם את מערך הנתונים של הפרחים ב-Lab 1.
import tensorflow as tf
import numpy as np
import os
import hypertune
import argparse
## Replace {your-gcs-bucket} !!
BUCKET_ROOT='/gcs/{your-gcs-bucket}'
# Define variables
NUM_CLASSES = 5
EPOCHS=10
BATCH_SIZE = 32
IMG_HEIGHT = 180
IMG_WIDTH = 180
DATA_DIR = f'{BUCKET_ROOT}/flower_photos'
def get_args():
'''Parses args. Must include all hyperparameters you want to tune.'''
parser = argparse.ArgumentParser()
parser.add_argument(
'--learning_rate',
required=True,
type=float,
help='learning rate')
parser.add_argument(
'--momentum',
required=True,
type=float,
help='SGD momentum value')
parser.add_argument(
'--num_units',
required=True,
type=int,
help='number of units in last hidden layer')
args = parser.parse_args()
return args
def create_datasets(data_dir, batch_size):
'''Creates train and validation datasets.'''
train_dataset = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(IMG_HEIGHT, IMG_WIDTH),
batch_size=batch_size)
validation_dataset = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(IMG_HEIGHT, IMG_WIDTH),
batch_size=batch_size)
train_dataset = train_dataset.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
validation_dataset = validation_dataset.cache().prefetch(buffer_size=tf.data.AUTOTUNE)
return train_dataset, validation_dataset
def create_model(num_units, learning_rate, momentum):
'''Creates model.'''
model = tf.keras.Sequential([
tf.keras.layers.Resizing(IMG_HEIGHT, IMG_WIDTH),
tf.keras.layers.Rescaling(1./255, input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
tf.keras.layers.Conv2D(16, 3, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(num_units, activation='relu'),
tf.keras.layers.Dense(NUM_CLASSES, activation='softmax')
])
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=momentum),
loss=tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=['accuracy'])
return model
def main():
args = get_args()
train_dataset, validation_dataset = create_datasets(DATA_DIR, BATCH_SIZE)
model = create_model(args.num_units, args.learning_rate, args.momentum)
history = model.fit(train_dataset, validation_data=validation_dataset, epochs=EPOCHS)
# DEFINE METRIC
hp_metric = history.history['val_accuracy'][-1]
hpt = hypertune.HyperTune()
hpt.report_hyperparameter_tuning_metric(
hyperparameter_metric_tag='accuracy',
metric_value=hp_metric,
global_step=EPOCHS)
if __name__ == "__main__":
main()
לפני שמפתחים את הקונטיינר, נבחן לעומק את הקוד. יש כמה רכיבים ספציפיים לשימוש בשירות לכוונון היפר-פרמטרים.
- הסקריפט מייבא את הספרייה
hypertune
. - הפונקציה
get_args()
מגדירה ארגומנט בשורת הפקודה לכל היפר-פרמטר שרוצים לכוונן. בדוגמה הזו, הפרמטרים ההיפר-מרחביים שיכוונו הם קצב הלמידה, ערך המומנטום באופטימיזטור ומספר היחידות בשכבה החבויה האחרונה של המודל, אבל אתם יכולים להתנסות בפרמטרים אחרים. לאחר מכן, הערך המועבר בארגומנטים האלה משמש להגדרת ההיפר-פרמטר התואם בקוד. - בסוף הפונקציה
main()
, הספרייהhypertune
משמשת להגדרת המדד שרוצים לבצע עבורו אופטימיזציה. ב-TensorFlow, השיטהmodel.fit
של keras מחזירה אובייקטHistory
. המאפייןHistory.history
הוא רשומה של ערכי אובדן האימון וערכי המדדים ברצפי תקופות אימון. אם מעבירים נתוני אימות אלmodel.fit
, המאפייןHistory.history
יכלול גם את הערכים של אובדן האימות והמדדים. לדוגמה, אם אימנתם מודל במשך שלוש תקופות אימון (epochs) עם נתוני אימות וציינתם אתaccuracy
כמדד, המאפייןHistory.history
ייראה דומה למילון הבא.
{
"accuracy": [
0.7795261740684509,
0.9471358060836792,
0.9870933294296265
],
"loss": [
0.6340447664260864,
0.16712145507335663,
0.04546636343002319
],
"val_accuracy": [
0.3795261740684509,
0.4471358060836792,
0.4870933294296265
],
"val_loss": [
2.044623374938965,
4.100203514099121,
3.0728273391723633
]
אם רוצים ששירות הכוונון של ההיפר-פרמטרים יגלה את הערכים שמשפרים את דיוק האימות של המודל, צריך להגדיר את המדד בתור הרשומה האחרונה (או NUM_EPOCS - 1
) ברשימה val_accuracy
. לאחר מכן, מעבירים את המדד הזה למכונה של HyperTune
. אפשר לבחור כל מחרוזת שרוצים עבור hyperparameter_metric_tag
, אבל תצטרכו להשתמש במחרוזת הזו שוב בהמשך, כשתפעילו את המשימה של כוונון הפרמטרים העל-היפר.
שלב 2: יוצרים קובץ Docker
כדי ליצור קונטיינרים לקוד שלכם, צריך ליצור קובץ Docker. בקובץ Dockerfile תכללו את כל הפקודות הנדרשות להרצת קובץ האימג'. הספריות הנדרשות יותקנו ותתבצע הגדרה של נקודת הכניסה לקוד האימון.
ב-Terminal, יוצרים קובץ Dockerfile ריק ברמה הבסיסית (root) של ספריית flowers-hptune
:
touch Dockerfile
עכשיו אמורים להופיע בספרייה flowers-hptune/
הפריטים הבאים:
+ Dockerfile
+ trainer/
+ task.py
פותחים את Dockerfile ומעתיקים אליו את הטקסט הבא. תוכלו לראות שהוא כמעט זהה לקובץ ה-Docker שבו השתמשנו בשיעור ה-Lab הראשון, אבל עכשיו אנחנו מתקינים את הספרייה cloudml-hyper המצב.
FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-8
WORKDIR /
# Installs hypertune library
RUN pip install cloudml-hypertune
# Copies the trainer code to the docker image.
COPY trainer /trainer
# Sets up the entry point to invoke the trainer.
ENTRYPOINT ["python", "-m", "trainer.task"]
שלב 3: יוצרים את המאגר
ב-Terminal, מריצים את הפקודה הבאה כדי להגדיר משתנה סביבה לפרויקט. חשוב להחליף את your-cloud-project
במזהה הפרויקט:
PROJECT_ID='your-cloud-project'
להגדיר מאגר ב-Artifact Registry. נשתמש במאגר שיצרנו במעבדה הראשונה.
REPO_NAME='flower-app'
מגדירים משתנה עם ה-URI של קובץ האימג' בקונטיינר ב-Google Artifact Registry:
IMAGE_URI=us-central1-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/flower_image_hptune:latest
הגדרת Docker
gcloud auth configure-docker \
us-central1-docker.pkg.dev
לאחר מכן, כדי ליצור את הקונטיינר, מריצים את הפקודה הבאה מהשורש של ספריית flower-hptune
:
docker build ./ -t $IMAGE_URI
לסיום, מעבירים אותו בדחיפה ל-Artifact Registry:
docker push $IMAGE_URI
אחרי שדחפתם את הקונטיינר ל-Artifact Registry, אתם מוכנים להתחיל את משימת האימון.
5. הפעלת משימה של כוונון היפר-פרמטרים באמצעות ה-SDK
בחלק הזה תלמדו איך להגדיר ולשלוח את משימת הכוונון ההיפר-פרמטרים באמצעות Vertex Python API.
יוצרים מסמך notebook של TensorFlow 2 במרכז האפליקציות.
מייבאים את Vertex AI SDK.
from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt
כדי להפעיל את המשימה של כוונון הפרמטרים העל-היפר, קודם צריך להגדיר את worker_pool_specs
, שמציין את סוג המכונה ואת קובץ האימג' של Docker. המפרט הבא מגדיר מכונה אחת עם שני מעבדי GPU מסוג NVIDIA Tesla V100.
צריך להחליף את {PROJECT_ID}
ב-image_uri
בשם הפרויקט שלכם.
# The spec of the worker pools including machine type and Docker image
# Be sure to replace PROJECT_ID in the `image_uri` with your project.
worker_pool_specs = [{
"machine_spec": {
"machine_type": "n1-standard-4",
"accelerator_type": "NVIDIA_TESLA_V100",
"accelerator_count": 1
},
"replica_count": 1,
"container_spec": {
"image_uri": "us-central1-docker.pkg.dev/{PROJECT_ID}/flower-app/flower_image_hptune:latest"
}
}]
בשלב הבא, מגדירים את parameter_spec
, שהוא מילון שמציין את הפרמטרים שרוצים לבצע להם אופטימיזציה. מפתח המילון הוא המחרוזת שהקצית לארגומנט בשורת הפקודה לכל היפר-פרמטר, וערך המילון הוא מפרט הפרמטר.
לכל היפר-פרמטר צריך להגדיר את הסוג ואת הגבולות של הערכים ששירות ההתאמה האישית ינסה. הפרמטרים היפרבאריים יכולים להיות מסוג Double, Integer, Categorical או Discrete. אם בוחרים בסוג 'כפול' או 'מספר שלם', צריך לציין ערך מינימלי ומקסימלי. אם בוחרים באפשרות 'קטגוריאלי' או 'דיסקרטי', צריך לספק את הערכים. עבור הסוגים Double ו-Integer, צריך גם לציין את ערך ההתאמה. בסרטון הזה מוסבר איך לבחור את התצוגה המתאימה ביותר.
# Dictionary representing parameters to optimize.
# The dictionary key is the parameter_id, which is passed into your training
# job as a command line argument,
# And the dictionary value is the parameter specification of the metric.
parameter_spec = {
"learning_rate": hpt.DoubleParameterSpec(min=0.001, max=1, scale="log"),
"momentum": hpt.DoubleParameterSpec(min=0, max=1, scale="linear"),
"num_units": hpt.DiscreteParameterSpec(values=[64, 128, 512], scale=None)
}
המפרט הסופי שצריך להגדיר הוא metric_spec
, שהוא מילון שמייצג את המדד שצריך לבצע אופטימיזציה. מפתח המילון הוא hyperparameter_metric_tag
שהגדרתם בקוד של אפליקציית האימון, והערך הוא יעד האופטימיזציה.
# Dictionary representing metric to optimize.
# The dictionary key is the metric_id, which is reported by your training job,
# And the dictionary value is the optimization goal of the metric.
metric_spec={'accuracy':'maximize'}
אחרי הגדרת המפרטים, יוצרים משימה של התאמה אישית, שהיא המפרט הנפוץ שישמשו להפעלת המשימה בכל אחד מניסויי הכוונון של ההיפר-פרמטרים.
צריך להחליף את {YOUR_BUCKET}
בקטגוריה שיצרתם קודם.
# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='flowers-hptune-job',
worker_pool_specs=worker_pool_specs,
staging_bucket='gs://{YOUR_BUCKET}')
לאחר מכן יוצרים את HyperparameterTuningJob
ומריצים אותו.
hp_job = aiplatform.HyperparameterTuningJob(
display_name='flowers-hptune-job',
custom_job=my_custom_job,
metric_spec=metric_spec,
parameter_spec=parameter_spec,
max_trial_count=15,
parallel_trial_count=3)
hp_job.run()
יש כמה ארגומנטים שחשוב לשים לב אליהם:
- max_trial_count: צריך להגדיר גבול עליון למספר הניסיונות שהשירות ירוץ. בדרך כלל, ככל שמבצעים יותר ניסויים, התוצאות טובות יותר. עם זאת, תגיע נקודה שבה התשואה תהיה פוחתת, ואז לניסויים נוספים תהיה השפעה קטנה או אפסית על המדד שאתם מנסים לבצע אופטימיזציה שלו. מומלץ להתחיל עם מספר קטן יותר של ניסויים ולקבל מושג לגבי ההשפעה של הפרמטרים האלגוריתמיים שנבחרו לפני שמגדילים את ההיקף.
- parallel_trial_count: אם משתמשים בניסויים מקבילים, השירות מקצה כמה אשכולות לעיבוד אימון. הגדלת מספר הניסיונות המקבילים מפחיתה את משך הזמן שנדרש לכוונון של ההיפר-פרמטרים, אבל היא עשויה לפגוע ביעילות הכוללת של המשימה. הסיבה לכך היא ששיטת ברירת המחדל לכוונון מתבססת על תוצאות של ניסויים קודמים כדי לקבוע את הקצאת הערכים בניסויים הבאים.
- search_algorithm: אפשר להגדיר את אלגוריתם החיפוש כרשימה, אקראי או ברירת מחדל (None). אפשרות ברירת המחדל מחילה אופטימיזציה בייסינית כדי לחפש את המרחב של ערכי ההיפארמטרים האפשריים, והיא האלגוריתם המומלץ. כאן אפשר למצוא מידע נוסף על האלגוריתם הזה.
במסוף תוכלו לראות את ההתקדמות של המשימה.
בסיום, תוכלו לראות את התוצאות של כל ניסוי ואת קבוצת הערכים שהניבו את הביצועים הטובים ביותר.
🎉 מזל טוב! 🎉
למדתם איך להשתמש ב-Vertex AI כדי:
- הפעלת משימה אוטומטית של כוונון היפר-פרמטרים
מידע נוסף על החלקים השונים של Vertex זמין במסמכי העזרה.
6. הסרת המשאבים
מכיוון שהגדרתנו ל-notebook זמן תפוגה של 60 דקות חוסר פעילות, אין צורך לדאוג לגבי כיבוי המכונה. כדי לכבות את המכונה באופן ידני, לוחצים על הלחצן Stop בקטע Vertex AI Workbench במסוף. כדי למחוק את המחברות כולה, לוחצים על הלחצן 'מחיקה'.
כדי למחוק את קטגוריית האחסון, עוברים לתפריט הניווט במסוף Cloud, לוחצים על Storage, בוחרים את הקטגוריה ולוחצים על Delete: