1. סקירה כללית
בשיעור ה-Lab הזה תשתמשו ב-Vertex AI כדי להריץ משימת אימון מרובה-עובדים עבור מודל TensorFlow.
מה לומדים
נסביר לכם איך:
- לשנות את קוד האפליקציה לאימון לצורך אימון עובדים מרובים
- הגדרה והשקה של משימת אימון לכמה עובדים דרך ממשק המשתמש של Vertex AI
- הגדרה והשקה של משימת אימון מרובה עובדים באמצעות Vertex SDK
העלות הכוללת של הפעלת שיעור ה-Lab הזה ב-Google Cloud היא כ-5$.
2. מבוא ל-Vertex AI
בשיעור ה-Lab הזה נעשה שימוש במוצר ה-AI החדש ביותר שזמין ב-Google Cloud. Vertex AI משלב את הצעות למידת המכונה ב-Google Cloud ליצירת חוויית פיתוח חלקה. בעבר, ניתן היה לגשת למודלים שעברו אימון באמצעות AutoML ומודלים בהתאמה אישית דרך שירותים נפרדים. המוצר החדש משלב את כל ממשקי ה-API האלה בממשק API אחד, לצד מוצרים חדשים אחרים. תוכלו גם להעביר פרויקטים קיימים ל-Vertex AI. יש לך משוב? אפשר למצוא אותו בדף התמיכה.
Vertex AI כולל מוצרים רבים ושונים לתמיכה בתהליכי עבודה של למידת מכונה מקצה לקצה. שיעור ה-Lab הזה יתמקד במוצרים שמודגשים בהמשך: הדרכה וWorkbench
3. סקירה כללית של תרחיש השימוש
בשיעור ה-Lab הזה תשתמשו בלמידת העברה כדי לאמן מודל לסיווג תמונות במערך הנתונים Cassava מ-TensorFlow Datasets. הארכיטקטורה שבה תשתמשו היא מודל ResNet50 מהספרייה tf.keras.applications
שעבר אימון מראש על מערך הנתונים של Imagenet.
למה הדרכה מבוזרת?
אם יש לכם יחידת GPU אחת, TensorFlow ישתמש במאיץ הזה כדי להאיץ את אימון המודלים בלי מאמץ נוסף מצידכם. עם זאת, אם אתם רוצים לקבל הגדלה של מספר מעבדי GPU במחשב אחד או בכמה מכונות (בכל אחת מהן יש כמה מעבדי GPU), תצטרכו להשתמש ב-tf.distribute
, שהיא הספרייה של TensorFlow להרצת חישוב בכמה מכשירים. מכשיר מתייחס למעבד (CPU) או למאיץ, כמו מעבדי GPU או מעבדי TPU, במכונות מסוימות ש-TensorFlow יכול להריץ בהן פעולות.
הדרך הפשוטה ביותר להתחיל באימון מבוזר היא מכונה אחת עם כמה מכשירי GPU. אסטרטגיית הפצה של TensorFlow מהמודול tf.distribute
תנהל את התיאום של הפצת נתונים ועדכונים הדרגתיים בין כל מעבדי ה-GPU. אם התבססתם על אימון מארח יחיד ואתם רוצים להרחיב עוד יותר, הוספת מספר מכונות לאשכול יכולה לשפר עוד יותר את הביצועים. אתם יכולים להשתמש באשכול של מכונות שהן מעבד (CPU) בלבד, או שלכל אחת מהן יש יחידת GPU אחת או יותר. בשיעור ה-Lab הזה תלמדו איך להשתמש ב-MultiWorkerMirroredStrategy
כדי להפיץ אימון של מודל TensorFlow במספר מכונות ב-Vertex AI.
MultiWorkerMirroredStrategy
היא אסטרטגיה סינכרונית של מקביליות נתונים שאפשר להשתמש בה רק בכמה שינויים בקוד. עותק של המודל נוצר בכל מכשיר באשכול. עדכוני ההדרגתיות הבאים יתבצעו באופן סינכרוני. כלומר, כל מכשיר של עובד מחשב את המעבר קדימה ואחורה במודל, בקטע שונה של נתוני הקלט. לאחר מכן, ההדרגתיות המחושבים מכל אחת מהפרוסות האלה נצברים בין כל המכשירים במכונה ובכל המכונות באשכול, ומצטמצמות (בדרך כלל בממוצע) בתהליך שנקרא 'צמצום מלא'. לאחר מכן כלי האופטימיזציה מעדכן את הפרמטר עם ההדרגתיות המופחתת האלה, ובכך שומר על סנכרון המכשירים. למידע נוסף על אימון מבוזר באמצעות TensorFlow, כדאי לצפות בסרטון הבא:
4. הגדרת הסביבה
כדי להריץ את ה-Codelab הזה צריך פרויקט ב-Google Cloud Platform שהחיוב מופעל בו. כדי ליצור פרויקט, יש לפעול לפי ההוראות האלה.
שלב 1: מפעילים את ממשק ה-API של Compute Engine
עוברים אל Compute Engine ובוחרים באפשרות Enable (הפעלה) אם היא לא מופעלת עדיין. תצטרכו את הקישור הזה כדי ליצור מכונה של ה-notebook.
שלב 2: מפעילים את Container Registry API
עוברים אל Container Registry ובוחרים באפשרות Enable אם עדיין לא משתמשים בו. אפשר להשתמש בו כדי ליצור מאגר למשימת האימון המותאמת אישית.
שלב 3: מפעילים את Vertex AI API
עוברים לקטע Vertex AI במסוף Cloud ולוחצים על Enable Vertex AI API.
שלב 4: יצירת מכונה של Vertex AI Workbench
בקטע Vertex AI במסוף Cloud, לוחצים על Workbench:
מפעילים את Notebooks API, אם עדיין לא פועלים.
לאחר ההפעלה, לוחצים על פנקסי רשימות מנוהלים:
לאחר מכן בוחרים פנקס רשימות חדש.
נותנים שם ל-notebook ולוחצים על הגדרות מתקדמות.
בקטע 'הגדרות מתקדמות', מפעילים כיבוי ללא פעילות ומגדירים את מספר הדקות ל-60. כלומר, המחשב יכבה באופן אוטומטי כשהוא לא בשימוש כדי שלא תצברו עלויות מיותרות.
בקטע אבטחה, בוחרים באפשרות 'הפעלת הטרמינל'. אם היא לא מופעלת עדיין.
אפשר להשאיר את כל שאר ההגדרות המתקדמות כפי שהן.
לאחר מכן, לוחצים על יצירה. הקצאה של המכונה תימשך כמה דקות.
אחרי שהמכונה נוצרה, בוחרים באפשרות Open JupyterLab.
בפעם הראשונה שתשתמשו במכונה חדשה, תתבקשו לבצע אימות. כדי לעשות זאת, פועלים לפי השלבים שבממשק המשתמש.
5. יצירת קונטיינרים של קוד אפליקציה לאימון
כדי לשלוח את משימת האימון הזו ל-Vertex, עליכם להכניס את הקוד של אפליקציית האימון לקונטיינר של Docker ולהעביר אותו בדחיפה אל Google Container Registry. כך תוכלו לאמן מודל שנוצר באמצעות כל מסגרת.
כדי להתחיל, פותחים חלון Terminal במכונה של ה-notebook מתפריט מרכז האפליקציות:
יוצרים ספרייה חדשה בשם cassava
ומוסיפים אליה cd:
mkdir cassava
cd cassava
שלב 1: יוצרים קובץ Docker
השלב הראשון ביצירת קונטיינרים לקוד הוא יצירת קובץ Docker. בקובץ ה-Docker, יכללו את כל הפקודות הנדרשות להפעלת התמונה. הוא יתקין את כל הספריות הנדרשות ותגדיר את נקודת הכניסה לקוד האימון.
בטרמינל, יוצרים קובץ Docker ריק:
touch Dockerfile
פותחים את קובץ ה-Docker ומעתיקים אליו את הפקודה הבאה:
FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-7
WORKDIR /
# 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"]
קובץ ה-Docker הזה משתמש בתמונת Docker של TensorFlow Enterprise 2.7 GPU ללמידה עמוקה (Deep Learning). בקונטיינרים של למידה עמוקה (Deep Learning) ב-Google Cloud מותקנים מראש הרבה מסגרות נפוצות של למידת מכונה ומדעי נתונים. אחרי שמורידים את התמונה, קובץ ה-Docker הזה מגדיר את נקודת הכניסה לקוד האימון. עדיין לא יצרת את הקבצים האלה – בשלב הבא צריך להוסיף את הקוד לצורך אימון וכוונון המודל.
שלב 2: יצירת קטגוריה של Cloud Storage
במשימת האימון הזו תייצאו את מודל TensorFlow המאומן לקטגוריה של Cloud Storage. ב-Terminal, מריצים את הפקודה הבאה כדי להגדיר משתנה env לפרויקט ומקפידים להחליף את your-cloud-project
במזהה הפרויקט:
PROJECT_ID='your-cloud-project'
לאחר מכן, מריצים את הפקודה הבאה בטרמינל כדי ליצור קטגוריה חדשה בפרויקט.
BUCKET="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET
שלב 3: מוסיפים קוד לאימון המודלים
בטרמינל, מריצים את הפקודה הבאה כדי ליצור ספרייה לקוד האימון וקובץ Python שאליו מוסיפים את הקוד:
mkdir trainer
touch trainer/task.py
עכשיו אמורים להיות בספרייה cassava/
הפריטים הבאים:
+ Dockerfile
+ trainer/
+ task.py
אחר כך פותחים את הקובץ task.py
שיצרתם ומעתיקים את הקוד שבהמשך. עליך להחליף את {your-gcs-bucket}
בשם של הקטגוריה של Cloud Storage שיצרת עכשיו.
import tensorflow as tf
import tensorflow_datasets as tfds
import os
PER_REPLICA_BATCH_SIZE = 64
EPOCHS = 2
# TODO: replace {your-gcs-bucket} with the name of the Storage bucket you created earlier
BUCKET = 'gs://{your-gcs-bucket}/mwms'
def preprocess_data(image, label):
'''Resizes and scales images.'''
image = tf.image.resize(image, (300,300))
return tf.cast(image, tf.float32) / 255., label
def create_dataset(batch_size):
'''Loads Cassava dataset and preprocesses data.'''
data, info = tfds.load(name='cassava', as_supervised=True, with_info=True)
number_of_classes = info.features['label'].num_classes
train_data = data['train'].map(preprocess_data,
num_parallel_calls=tf.data.experimental.AUTOTUNE)
train_data = train_data.shuffle(1000)
train_data = train_data.batch(batch_size)
train_data = train_data.prefetch(tf.data.experimental.AUTOTUNE)
# Set AutoShardPolicy
options = tf.data.Options()
options.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.DATA
train_data = train_data.with_options(options)
return train_data, number_of_classes
def create_model(number_of_classes):
'''Creates and compiles pretrained ResNet50 model.'''
base_model = tf.keras.applications.ResNet50(weights='imagenet', include_top=False)
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dense(1016, activation='relu')(x)
predictions = tf.keras.layers.Dense(number_of_classes, activation='softmax')(x)
model = tf.keras.Model(inputs=base_model.input, outputs=predictions)
model.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.Adam(0.0001),
metrics=['accuracy'])
return model
def _is_chief(task_type, task_id):
'''Helper function. Determines if machine is chief.'''
return task_type == 'chief'
def _get_temp_dir(dirpath, task_id):
'''Helper function. Gets temporary directory for saving model.'''
base_dirpath = 'workertemp_' + str(task_id)
temp_dir = os.path.join(dirpath, base_dirpath)
tf.io.gfile.makedirs(temp_dir)
return temp_dir
def write_filepath(filepath, task_type, task_id):
'''Helper function. Gets filepath to save model.'''
dirpath = os.path.dirname(filepath)
base = os.path.basename(filepath)
if not _is_chief(task_type, task_id):
dirpath = _get_temp_dir(dirpath, task_id)
return os.path.join(dirpath, base)
def main():
# Create strategy
strategy = tf.distribute.MultiWorkerMirroredStrategy()
# Get data
global_batch_size = PER_REPLICA_BATCH_SIZE * strategy.num_replicas_in_sync
train_data, number_of_classes = create_dataset(global_batch_size)
# Wrap variable creation within strategy scope
with strategy.scope():
model = create_model(number_of_classes)
model.fit(train_data, epochs=EPOCHS)
# Determine type and task of the machine from
# the strategy cluster resolver
task_type, task_id = (strategy.cluster_resolver.task_type,
strategy.cluster_resolver.task_id)
# Based on the type and task, write to the desired model path
write_model_path = write_filepath(BUCKET, task_type, task_id)
model.save(write_model_path)
if __name__ == "__main__":
main()
לפני שיוצרים את מאגר התגים, נבחן לעומק את הקוד, שמשתמש ב-MultiWorkerMirroredStrategy
מה-API של tf.distribute.Strategy
.
הקוד כולל מספר רכיבים שנדרשים כדי לעבוד עם MultiWorkerMirroredStrategy
.
- צריך לפצל את הנתונים – כלומר, לכל עובד מוקצית קבוצת משנה של כל מערך הנתונים. לכן, בכל שלב יתבצע עיבוד של גודל גלובלי באצווה של רכיבים לא חופפים של מערך נתונים. הפיצול הזה מתבצע באופן אוטומטי באמצעות הפקודה
tf.data.experimental.AutoShardPolicy
, שאפשר להגדיר אותה לערךFILE
או לערךDATA
. בדוגמה הזו, הפונקציהcreate_dataset()
מגדירה אתAutoShardPolicy
לערךDATA
כי לא מתבצעת הורדה של מערך הנתונים מסוג cassava כמספר קבצים. עם זאת, אם לא הגדרתם את המדיניות לערךDATA
, מדיניות ברירת המחדלAUTO
תיכנס לתוקף והתוצאה הסופית תהיה זהה. למידע נוסף על פיצול של מערך נתונים באמצעותMultiWorkerMirroredStrategy
- בפונקציה
main()
, נוצר האובייקטMultiWorkerMirroredStrategy
. לאחר מכן, אתם כוללים את היצירה של משתני המודל בתוך היקף האסטרטגיה. השלב החשוב הזה מורה ל-TensorFlow אילו משתנים צריך לשקף ברפליקות. - גודל קבוצת הקבצים מוגדל על ידי
num_replicas_in_sync
. כך אפשר להבטיח שכל עותק יעובד באותו מספר של דוגמאות בכל שלב. השיטה המומלצת היא שינוי גודל האצווה כשמשתמשים באסטרטגיות סינכרוניות של נתונים במקביל ב-TensorFlow. - שמירת המודל מורכבת מעט יותר במקרה של ריבוי עובדים, מכיוון שהיעד צריך להיות שונה לכל אחד מהעובדים. העובד הראשי ישמור את המודל בספריית המודלים הרצויה, בעוד שהעובדים האחרים ישמרו את המודל בספריות זמניות. חשוב שהספריות הזמניות האלה יהיו ייחודיות כדי למנוע מעובדים מרובים לכתוב לאותו מיקום. חיסכון יכול לכלול פעולות קבוצתיות – כלומר, כל העובדים צריכים להציל ולא רק את הראשי. הפונקציות
_is_chief()
,_get_temp_dir()
,write_filepath()
והפונקציותmain()
כוללות קוד סטנדרטי שעוזר לשמור את המודל.
הערה: אם השתמשתם ב-MultiWorkerMirroredStrategy
בסביבה אחרת, יכול להיות שהגדרתם את משתנה הסביבה TF_CONFIG
. מערכת Vertex AI מגדירה בשבילכם את TF_CONFIG
באופן אוטומטי, כך שאין צורך להגדיר את המשתנה הזה בכל מכונה באשכול.
שלב 4: יוצרים את המאגר
ב-Terminal, מריצים את הפקודה הבאה כדי להגדיר משתנה env לפרויקט ומקפידים להחליף את your-cloud-project
במזהה הפרויקט:
PROJECT_ID='your-cloud-project'
מגדירים משתנה עם ה-URI של תמונת הקונטיינר ב-Google Container Registry:
IMAGE_URI="gcr.io/$PROJECT_ID/multiworker:cassava"
הגדרת Docker
gcloud auth configure-docker
לאחר מכן, יוצרים את הקונטיינר על ידי הרצת הפקודה הבאה מהרמה הבסיסית (root) של הספרייה cassava
:
docker build ./ -t $IMAGE_URI
לסיום, מעבירים אותו ל-Google Container Registry:
docker push $IMAGE_URI
הקונטיינר הועבר ל-Container Registry. עכשיו אתם מוכנים להתחיל את משימת האימון.
6. הרצת משימת אימון מרובת עובדים ב-Vertex AI
בשיעור ה-Lab הזה נעשה שימוש באימון מותאם אישית באמצעות קונטיינר מותאם אישית ב-Google Container Registry, אבל תוכלו גם להריץ משימת אימון עם הקונטיינרים המוכנים מראש.
כדי להתחיל, עוברים לקטע Training בקטע Vertex במסוף Cloud:
שלב 1: הגדרה של משימת האימון
לוחצים על יצירה כדי להזין את הפרמטרים למשימת האימון.
- בקטע מערך נתונים, בוחרים באפשרות אין מערך נתונים מנוהל.
- לאחר מכן בוחרים באפשרות אימון מותאם אישית (למתקדמים) כשיטת האימון ולוחצים על המשך.
- מזינים
multiworker-cassava
(או כל שם אחר שרוצים לקרוא למודל) בשדה שם המודל - לוחצים על המשך.
בשלב Container settings (הגדרות מאגר תגים), בוחרים באפשרות CustomContainer (מאגר מותאם אישית):
בתיבה הראשונה (תמונה של קונטיינר), מזינים את הערך של המשתנה IMAGE_URI
מהקטע הקודם. הוא צריך להיות: gcr.io/your-cloud-project/multiworker:cassava
, עם מזהה הפרויקט שלכם. משאירים את שאר השדות ריקים ולוחצים על Continue (המשך).
מדלגים על השלב של ההיפר-פרמטרים בלחיצה על המשך שוב.
שלב 2: הגדרת אשכול המחשוב
Vertex AI מספק 4 מאגרי עובדים שיכולים לכסות את הסוגים השונים של משימות מכונות.
מאגר עובדים 0 מגדיר את הראשי, הראשי, המתזמן או ה'ראשי'. ב-MultiWorkerMirroredStrategy
, כל המכונות נקראות 'עובדים', שהן המכונות הפיזיות שבהן מתבצעת החישוב הרפליקציית. בנוסף לכך שכל מכונה היא worker, צריך להיות עובד אחד שמבצע עבודה נוספת כמו שמירת נקודות ביקורת וכתיבת קובצי סיכום ב-TensorBoard. המכונה הזו נקראת 'ראשי'. יש רק עובד ראשי אחד, כך שמספר העובדים במאגר 0 תמיד יהיה 1.
בקטע Compute and price, משאירים את האזור שנבחר כפי שהוא ומגדירים את Worker pool 0 באופן הבא:
מאגר עובדים 1 הוא המקום שבו מגדירים את העובדים באשכול.
מגדירים את מאגר עובדים 1 באופן הבא:
עכשיו האשכול מוגדר כך שיהיו בו שתי מכונות (CPU) בלבד. כשמריצים את קוד אפליקציית האימון, MultiWorkerMirroredStrategy
יפיץ את האימון בין שתי המכונות.
ב-MultiWorkerMirroredStrategy
יש רק משימות מסוג 'ראשי' ו'עובדים', כך שאין צורך להגדיר את מאגרי העובדים הנוספים. עם זאת, אם תשתמשו ב-ParameterServerStrategy
של TensorFlow, תצטרכו להגדיר את שרתי הפרמטרים במאגר עובדים 2. אם רוצים להוסיף מעריך לאשכול, צריך להגדיר את המכונה במאגר עובדים 3.
לוחצים על התחלת האימון כדי להתחיל את משימת הכוונון של ההיפר-פרמטרים. בקטע 'אימון' במסוף, בכרטיסייה TRAINING PIPELINES תוכלו לראות את המשימה החדשה שהושקה:
🎉 כל הכבוד! 🎉
למדתם איך להשתמש ב-Vertex AI כדי:
- השקת משימת אימון מרובת עובדים לאימון קוד שסופק בקונטיינר מותאם אישית. השתמשתם במודל TensorFlow בדוגמה הזו, אבל אפשר לאמן מודל שנוצר עם כל מסגרת באמצעות קונטיינרים מובנים או מותאמים אישית.
כדי לקבל מידע נוסף על החלקים השונים ב-Vertex, אתם יכולים לעיין במסמכי העזרה.
7. [אופציונלי] שימוש ב-Vertex SDK
בקטע הקודם ראינו איך להפעיל את משימת האימון דרך ממשק המשתמש. בקטע הזה תוצג דרך חלופית לשלוח את משימת האימון באמצעות Vertex Python API.
חוזרים למכונה של ה-notebook ויוצרים notebook של TensorFlow 2 ממרכז האפליקציות:
מייבאים את Vertex AI SDK.
from google.cloud import aiplatform
כדי להפעיל את משימת האימון של מספר עובדים, קודם צריך להגדיר את המפרט של מאגר העובדים. שימו לב שהשימוש במעבדי GPU במפרט הוא אופציונלי לחלוטין, ואפשר להסיר את accelerator_type
ואת accelerator_count
אם אתם רוצים אשכול של מעבדים בלבד (CPU), כפי שמוצג בקטע הקודם.
# The spec of the worker pools including machine type and Docker image
# Be sure to replace {YOUR-PROJECT-ID} with your project ID.
worker_pool_specs=[
{
"replica_count": 1,
"machine_spec": {
"machine_type": "n1-standard-8", "accelerator_type": "NVIDIA_TESLA_V100", "accelerator_count": 1
},
"container_spec": {"image_uri": "gcr.io/{YOUR-PROJECT-ID}/multiworker:cassava"}
},
{
"replica_count": 1,
"machine_spec": {
"machine_type": "n1-standard-8", "accelerator_type": "NVIDIA_TESLA_V100", "accelerator_count": 1
},
"container_spec": {"image_uri": "gcr.io/{YOUR-PROJECT-ID}/multiworker:cassava"}
}
]
בשלב הבא, יוצרים ומפעילים CustomJob
. צריך להחליף את {YOUR_BUCKET}
בקטגוריה בפרויקט כדי לבצע Staging. אתם יכולים להשתמש באותה קטגוריה שיצרתם קודם.
# Replace YOUR_BUCKET
my_multiworker_job = aiplatform.CustomJob(display_name='multiworker-cassava-sdk',
worker_pool_specs=worker_pool_specs,
staging_bucket='gs://{YOUR_BUCKET}')
my_multiworker_job.run()
בקטע 'אימון' במסוף, בכרטיסייה ועוד JOBS, תופיע משימת האימון:
8. הסרת המשאבים
בגלל שהגדרנו את ה-notebook להפסקה של הזמן הקצוב לתפוגה אחרי 60 דקות ללא פעילות, אנחנו לא צריכים לדאוג לכיבוי המכונה. כדי לכבות את המכונה באופן ידני, לוחצים על הלחצן Stop (עצירה) בקטע Vertex AI Workbench במסוף. אם אתה רוצה למחוק לגמרי את ה-notebook, לחץ על הלחצן 'מחיקה'.
כדי למחוק את קטגוריית האחסון, באמצעות תפריט הניווט במסוף Cloud, עוברים אל Storage (אחסון), בוחרים את הקטגוריה ולוחצים על סמל המחיקה: