1. סקירה כללית
בשיעור ה-Lab הזה תשתמשו ב-Vertex AI כדי לאמן ולהציג מודל TensorFlow באמצעות קוד בקונטיינר מותאם אישית.
אנחנו משתמשים כאן ב-TensorFlow כקוד המודל, אבל אפשר להחליף אותו בקלות במסגרת אחרת.
מה תלמדו
נסביר לכם איך:
- פיתוח קוד לאימון מודלים ב-Vertex Workbench והעברתו לקונטיינרים
- שליחת משימה לאימון מודלים בהתאמה אישית ל-Vertex AI
- פורסים את המודל המאומן בנקודת קצה ומשתמשים בנקודת הקצה הזו כדי לקבל חיזויים
העלות הכוללת של הפעלת שיעור ה-Lab הזה ב-Google Cloud היא כ-$1.
2. מבוא ל-Vertex AI
בשיעור ה-Lab הזה נעשה שימוש במוצר ה-AI החדש ביותר שזמין ב-Google Cloud. Vertex AI משלב את הצעות למידת המכונה ב-Google Cloud ליצירת חוויית פיתוח חלקה. בעבר, ניתן היה לגשת למודלים שעברו אימון באמצעות AutoML ומודלים בהתאמה אישית דרך שירותים נפרדים. המוצר החדש משלב את כל ממשקי ה-API האלה בממשק API אחד, לצד מוצרים חדשים אחרים. אפשר גם להעביר פרויקטים קיימים ל-Vertex AI. יש לך משוב? אפשר למצוא אותו בדף התמיכה.
Vertex AI כולל מוצרים רבים ושונים לתמיכה בתהליכי עבודה של למידת מכונה מקצה לקצה. בשיעור ה-Lab הזה נתמקד במוצרים שמודגשים בהמשך: Training, Prediction ו-Workbench.
3. הגדרת הסביבה
כדי להריץ את סדנת הקוד הזו, צריך פרויקט ב-Google Cloud Platform שבו החיוב מופעל. כדי ליצור פרויקט, יש לפעול לפי ההוראות האלה.
שלב 1: מפעילים את Compute Engine API
עוברים אל Compute Engine ובוחרים באפשרות Enable (הפעלה) אם היא לא מופעלת עדיין. תצטרכו את הקישור הזה כדי ליצור מכונה של ה-notebook.
שלב 2: מפעילים את Vertex AI API
עוברים לקטע Vertex AI במסוף Cloud ולוחצים על Enable Vertex AI API.
שלב 3: מפעילים את Container Registry API
עוברים אל Container Registry ובוחרים באפשרות Enable אם עדיין לא משתמשים בו. אפשר להשתמש בו כדי ליצור מאגר למשימת האימון המותאמת אישית.
שלב 4: יצירת מכונה של Vertex AI Workbench
בקטע Vertex AI במסוף Cloud, לוחצים על Workbench:
משם, בתוך notebooks בניהול המשתמשים, לוחצים על New Notebook:
אחר כך בוחרים בגרסה העדכנית ביותר של סוג המכונה TensorFlow Enterprise (עם LTS) ללא GPUs:
משתמשים באפשרויות ברירת המחדל ואז לוחצים על יצירה.
המודל שנלמד ונציג בשיעור ה-Lab הזה מבוסס על המדריך הזה ממסמכי TensorFlow. המדריך משתמש במערך הנתונים של Auto MPG מ-Kaggle כדי לחזות את צריכת הדלק של רכב.
4. יצירת קונטיינרים של קוד אימון
נשלח את משימת האימון הזו ל-Vertex על ידי הצבת קוד האימון שלנו בקונטיינר של Docker, והעברת הקונטיינר הזה אל Google Container Registry. בעזרת הגישה הזו, אנחנו יכולים לאמן מודל שנוצר בכל מסגרת.
כדי להתחיל, פותחים חלון Terminal במכונה של ה-notebook מתפריט מרכז האפליקציות:
יוצרים ספרייה חדשה בשם mpg
ונכנסים אליה באמצעות cd:
mkdir mpg
cd mpg
שלב 1: יוצרים קובץ Docker
השלב הראשון ביצירת קונטיינרים לקוד שלנו הוא יצירת קובץ Docker. בקובץ ה-Docker נכלול את כל הפקודות הנדרשות כדי להריץ את קובץ האימג' שלנו. הקוד יטמיע את כל הספריות שבהן אנחנו משתמשים ויגדיר את נקודת הכניסה לקוד האימון שלנו. יוצרים קובץ Dockerfile ריק ב-Terminal:
touch Dockerfile
פותחים את קובץ ה-Docker ומעתיקים אליו את הפקודה הבאה:
FROM gcr.io/deeplearning-platform-release/tf2-cpu.2-6
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.train"]
קובץ ה-Docker הזה משתמש בתמונת Docker של TensorFlow Enterprise 2.3 ללמידה עמוקה. בקונטיינרים של למידה עמוקה (Deep Learning) ב-Google Cloud מותקנים מראש הרבה מסגרות נפוצות של למידת מכונה ומדעי נתונים. הפלטפורמה שבה אנחנו משתמשים כוללת את TF Enterprise 2.3, Pandas, Scikit-learn ועוד. אחרי שמורידים את התמונה, קובץ ה-Docker הזה מגדיר את נקודת הכניסה לקוד האימון שלנו. עדיין לא יצרנו את הקבצים האלה – בשלב הבא נוסיף את הקוד לצורכי אימון וייצוא של המודל.
שלב 2: יצירת קטגוריה של Cloud Storage
במשימת האימון שלנו, נייצא את מודל TensorFlow המאומן שלנו לקטגוריה של Cloud Storage. מערכת Vertex תשתמש בזה כדי לקרוא את נכסי המודל שיוצאו ולפרוס את המודל. ב-Terminal, מריצים את הפקודה הבאה כדי להגדיר משתנה env לפרויקט ומקפידים להחליף את your-cloud-project
במזהה הפרויקט:
PROJECT_ID='your-cloud-project'
לאחר מכן, מריצים את הפקודה הבאה בטרמינל כדי ליצור קטגוריה חדשה בפרויקט. הדגל -l
(מיקום) חשוב כי הוא צריך להופיע באותו אזור שבו פורסים נקודת קצה של מודל בשלב מאוחר יותר במדריך:
BUCKET_NAME="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET_NAME
שלב 3: מוסיפים את הקוד לאימון המודל
בטרמינל, מריצים את הפקודה הבאה כדי ליצור ספרייה לקוד האימון שלנו וקובץ Python שאליו נוסיף את הקוד:
mkdir trainer
touch trainer/train.py
עכשיו אמורים להופיע הפריטים הבאים בספרייה mpg/:
+ Dockerfile
+ trainer/
+ train.py
אחר כך פותחים את הקובץ train.py
שיצרתם ומעתיקים את הקוד שלמטה (הקוד מותאם מהמדריך במסמכי TensorFlow).
בתחילת הקובץ, מעדכנים את המשתנה BUCKET
בשם של קטגוריית האחסון שיצרתם בשלב הקודם:
import numpy as np
import pandas as pd
import pathlib
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
print(tf.__version__)
"""## The Auto MPG dataset
The dataset is available from the [UCI Machine Learning Repository](https://archive.ics.uci.edu/ml/).
### Get the data
First download the dataset.
"""
dataset_path = keras.utils.get_file("auto-mpg.data", "http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")
dataset_path
"""Import it using pandas"""
column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight',
'Acceleration', 'Model Year', 'Origin']
dataset = pd.read_csv(dataset_path, names=column_names,
na_values = "?", comment='\t',
sep=" ", skipinitialspace=True)
dataset.tail()
# TODO: replace `your-gcs-bucket` with the name of the Storage bucket you created earlier
BUCKET = 'gs://your-gcs-bucket'
"""### Clean the data
The dataset contains a few unknown values.
"""
dataset.isna().sum()
"""To keep this initial tutorial simple drop those rows."""
dataset = dataset.dropna()
"""The `"Origin"` column is really categorical, not numeric. So convert that to a one-hot:"""
dataset['Origin'] = dataset['Origin'].map({1: 'USA', 2: 'Europe', 3: 'Japan'})
dataset = pd.get_dummies(dataset, prefix='', prefix_sep='')
dataset.tail()
"""### Split the data into train and test
Now split the dataset into a training set and a test set.
We will use the test set in the final evaluation of our model.
"""
train_dataset = dataset.sample(frac=0.8,random_state=0)
test_dataset = dataset.drop(train_dataset.index)
"""### Inspect the data
Have a quick look at the joint distribution of a few pairs of columns from the training set.
Also look at the overall statistics:
"""
train_stats = train_dataset.describe()
train_stats.pop("MPG")
train_stats = train_stats.transpose()
train_stats
"""### Split features from labels
Separate the target value, or "label", from the features. This label is the value that you will train the model to predict.
"""
train_labels = train_dataset.pop('MPG')
test_labels = test_dataset.pop('MPG')
"""### Normalize the data
Look again at the `train_stats` block above and note how different the ranges of each feature are.
It is good practice to normalize features that use different scales and ranges. Although the model *might* converge without feature normalization, it makes training more difficult, and it makes the resulting model dependent on the choice of units used in the input.
Note: Although we intentionally generate these statistics from only the training dataset, these statistics will also be used to normalize the test dataset. We need to do that to project the test dataset into the same distribution that the model has been trained on.
"""
def norm(x):
return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset)
normed_test_data = norm(test_dataset)
"""This normalized data is what we will use to train the model.
Caution: The statistics used to normalize the inputs here (mean and standard deviation) need to be applied to any other data that is fed to the model, along with the one-hot encoding that we did earlier. That includes the test set as well as live data when the model is used in production.
## The model
### Build the model
Let's build our model. Here, we'll use a `Sequential` model with two densely connected hidden layers, and an output layer that returns a single, continuous value. The model building steps are wrapped in a function, `build_model`, since we'll create a second model, later on.
"""
def build_model():
model = keras.Sequential([
layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),
layers.Dense(64, activation='relu'),
layers.Dense(1)
])
optimizer = tf.keras.optimizers.RMSprop(0.001)
model.compile(loss='mse',
optimizer=optimizer,
metrics=['mae', 'mse'])
return model
model = build_model()
"""### Inspect the model
Use the `.summary` method to print a simple description of the model
"""
model.summary()
"""Now try out the model. Take a batch of `10` examples from the training data and call `model.predict` on it.
It seems to be working, and it produces a result of the expected shape and type.
### Train the model
Train the model for 1000 epochs, and record the training and validation accuracy in the `history` object.
Visualize the model's training progress using the stats stored in the `history` object.
This graph shows little improvement, or even degradation in the validation error after about 100 epochs. Let's update the `model.fit` call to automatically stop training when the validation score doesn't improve. We'll use an *EarlyStopping callback* that tests a training condition for every epoch. If a set amount of epochs elapses without showing improvement, then automatically stop the training.
You can learn more about this callback [here](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/EarlyStopping).
"""
model = build_model()
EPOCHS = 1000
# The patience parameter is the amount of epochs to check for improvement
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
early_history = model.fit(normed_train_data, train_labels,
epochs=EPOCHS, validation_split = 0.2,
callbacks=[early_stop])
# Export model and save to GCS
model.save(BUCKET + '/mpg/model')
שלב 4: פיתוח ובדיקה של הקונטיינר באופן מקומי
ב-Terminal, מגדירים משתנה עם ה-URI של קובץ האימג' בקונטיינר ב-Google Container Registry:
IMAGE_URI="gcr.io/$PROJECT_ID/mpg:v1"
לאחר מכן, יוצרים את הקונטיינר על ידי הרצת הפקודה הבאה מהרמה הבסיסית (root) של הספרייה mpg
:
docker build ./ -t $IMAGE_URI
מריצים את הקונטיינר במכונה של ה-notebook כדי לוודא שהוא פועל בצורה תקינה:
docker run $IMAGE_URI
המודל צריך לסיים את האימון תוך 1-2 דקות, עם רמת דיוק של כ-72% באימות (רמת הדיוק המדויקת עשויה להשתנות). לאחר שמסיימים להפעיל את הקונטיינר באופן מקומי, מעבירים אותו בדחיפה ל-Google Container Registry:
docker push $IMAGE_URI
בעקבות העברת הקונטיינר שלנו ל-Container Registry, אנחנו מוכנים להתחיל משימה לאימון מודלים מותאמים אישית.
5. הרצת משימת אימון על Vertex AI
ב-Vertex AI יש שתי אפשרויות למודלים לאימון:
- AutoML: אימון מודלים באיכות גבוהה עם מומחיות בלמידת מכונה ובמאמץ מינימלי.
- הדרכה מותאמת אישית: אפשר להריץ אפליקציות אימון מותאמות אישית בענן באמצעות אחד מקונטיינרים מוכנים מראש של Google Cloud או להשתמש בקונטיינרים משלכם.
בשיעור ה-Lab הזה נשתמש באימון מותאם אישית באמצעות מאגר מותאם אישית משלנו ב-Google Container Registry. כדי להתחיל, עוברים לקטע Models בקטע Vertex במסוף Cloud:
שלב 1: מתחילים את משימת האימון
לוחצים על Create (יצירה) כדי להזין את הפרמטרים של משימה האימון והמודל שנפרס:
- בקטע מערך נתונים, בוחרים באפשרות אין מערך נתונים מנוהל.
- לאחר מכן בוחרים באפשרות אימון מותאם אישית (למתקדמים) כשיטת האימון ולוחצים על המשך.
- לוחצים על המשך.
בשלב הבא, מזינים mpg
(או כל שם אחר שרוצים לקרוא למודל) בשדה שם המודל. לאחר מכן בוחרים באפשרות מאגר מותאם אישית:
בתיבת הטקסט Container image, לוחצים על Browse ומוצאים את תמונת ה-Docker שהעליתם ל-Container Registry. משאירים את שאר השדות ריקים ולוחצים על המשך.
לא נשתמש בכוונון היפר-פרמטרים במדריך הזה, לכן משאירים את תיבת הכוונון 'הפעלת היפר-פרמטרים' לא מסומנת ולוחצים על המשך.
בקטע Compute and pricing, משאירים את האזור שנבחר כפי שהוא ובוחרים באפשרות n1-standard-4 כסוג המכונה:
משאירים את שדות המאיץ ריקים ובוחרים באפשרות המשך. המודל שבהדגמה הזאת מתאמן במהירות ולכן אנחנו משתמשים במכונה מסוג קטן יותר.
בשלב PredictionContainer (מאגר חיזוי) בוחרים באפשרות Pre-built-Container (מאגר מוגדר מראש) ואז בוחרים ב-TensorFlow 2.6.
משאירים את הגדרות ברירת המחדל של מאגר התגים המוכן מראש. בקטע Model Directory, מזינים את הקטגוריה של GCS עם ספריית המשנה mpg. זהו הנתיב בסקריפט לאימון המודל שאליו מייצאים את המודל האימון:
מערכת Vertex תחפש במיקום הזה במהלך פריסת המודל. עכשיו הכול מוכן לאימון. לוחצים על התחלת האימון כדי להתחיל את משימת האימון. בקטע Training במסוף יופיע משהו כזה:
6. פריסה של נקודת קצה (endpoint) של מודל
כשהגדרנו את משימה האימון, צינינו איפה מערכת Vertex AI תצטרך לחפש את נכסי המודל המיוצאים שלנו. כחלק מצינור ההכשרה שלנו, מערכת Vertex תיצור משאב למודל על סמך נתיב הנכס הזה. משאב המודל עצמו הוא לא מודל שנפרס, אבל ברגע שיש לכם מודל אתם מוכנים לפרוס אותו בנקודת קצה. מידע נוסף על מודלים ונקודות קצה ב-Vertex AI זמין במסמכי העזרה.
בשלב הזה ניצור נקודת קצה (endpoint) למודל המאומן. אנחנו יכולים להשתמש בהם כדי לקבל חיזויים במודל שלנו באמצעות Vertex AI API.
שלב 1: פריסה של נקודת הקצה
כשמשימת האימון תסתיים, אמור להופיע מודל בשם mpg (או כל מודל אחר שנתתם לו) בקטע Models (מודלים) במסוף:
כשמשימת האימון שלכם רצה, Vertex יצר בשבילכם משאב מודל. כדי להשתמש במודל הזה, צריך לפרוס נקודת קצה (endpoint). יכולות להיות לכם הרבה נקודות קצה לכל מודל. לוחצים על המודל ואז על Deploy to endpoint (פריסה לנקודת קצה).
בוחרים באפשרות יצירת נקודת קצה חדשה ונותנים לה שם, למשל v1. משאירים את האפשרות Standard (רגילה) מסומנת בקטע Access (גישה) ולוחצים על Continue (המשך).
משאירים את הערך של חלוקת התנועה כ-100, ומזינים 1 לצורך מספר מינימלי של צומתי מחשוב. בקטע Machine type, בוחרים באפשרות n1-standard-2 (או בכל סוג מכונה אחר שרוצים). משאירים את שאר ברירות המחדל מסומנות ולוחצים על המשך. לא נפעיל מעקב אחרי המודל הזה, לכן צריך ללחוץ על Deploy כדי להתחיל את הפריסה של נקודת הקצה.
פריסה של נקודת הקצה תימשך 10 עד 15 דקות. בסיום הפריסה תקבלו אימייל. בסיום הפריסה של נקודת הקצה, יוצג המסך הבא, שבו מוצגת נקודת קצה אחת שנפרסה במשאב ה-Model:
שלב 2: קבלת תחזיות על המודל שנפרס
אנחנו נקבל חיזויים לגבי המודל שעבר אימון מ-notebook ב-Python באמצעות Vertex Python API. חוזרים למכונת ה-notebook ויוצרים notebook של Python 3 ממרכז האפליקציות:
כדי להתקין את Vertex AI SDK, מריצים את הפקודה הבאה בתא ב-notebook:
!pip3 install google-cloud-aiplatform --upgrade --user
לאחר מכן מוסיפים תא ב-notebook כדי לייבא את ה-SDK וליצור הפניה לנקודת הקצה שפרסתם:
from google.cloud import aiplatform
endpoint = aiplatform.Endpoint(
endpoint_name="projects/YOUR-PROJECT-NUMBER/locations/us-central1/endpoints/YOUR-ENDPOINT-ID"
)
צריך להחליף שני ערכים במחרוזת endpoint_name
שלמעלה במספר הפרויקט ונקודת הקצה. כדי למצוא את מספר הפרויקט, עוברים למרכז הבקרה של הפרויקט ומחפשים את הערך של מספר הפרויקט.
המזהה של נקודת הקצה מופיע בקטע 'נקודות קצה' במסוף כאן:
בשלב האחרון, מבצעים חיזוי לנקודת הקצה (endpoint) על ידי העתקה והרצה של הקוד הבא בתא חדש:
test_mpg = [1.4838871833555929,
1.8659883497083019,
2.234620276849616,
1.0187816540094903,
-2.530890710602246,
-1.6046416850441676,
-0.4651483719733302,
-0.4952254087173721,
0.7746763768735953]
response = endpoint.predict([test_mpg])
print('API response: ', response)
print('Predicted MPG: ', response.predictions[0][0])
בדוגמה הזו כבר יש ערכים מנורמלים, הפורמט שהמודל שלנו מצפה לו.
הריצו את התא הזה, והפלט אמור להופיע כ-25 ק"מ לגלון.
🎉 כל הכבוד! 🎉
למדתם איך להשתמש ב-Vertex AI כדי:
- כדי לאמן מודל, מספקים את קוד האימון בקונטיינר בהתאמה אישית. השתמשתם במודל TensorFlow בדוגמה הזו, אבל אפשר לאמן מודל שנוצר עם כל מסגרת באמצעות קונטיינרים מותאמים אישית.
- פריסה של מודל TensorFlow באמצעות קונטיינר שפותח מראש כחלק מתהליך האימון שבו השתמשתם.
- יצירת נקודת קצה למודל ויצירה של חיזוי.
מידע נוסף על החלקים השונים של Vertex זמין במסמכי העזרה.
7. הסרת המשאבים
אם אתם רוצים להמשיך להשתמש ב-notebook שיצרתם בשיעור ה-Lab הזה, מומלץ להשבית אותו כשהוא לא בשימוש. בממשק המשתמש של Workbench במסוף Cloud, בוחרים את ה-notebook ואז לוחצים על Stop.
אם אתם רוצים למחוק לגמרי את ה-notebook, לחצו על הלחצן 'מחיקה' בפינה השמאלית העליונה.
כדי למחוק את נקודת הקצה שפרסתם, עוברים לקטע Endpoints במסוף Vertex AI, לוחצים על נקודת הקצה שיצרתם ובוחרים באפשרות UnDeploy model from endpoint (ביטול הפריסה של מודל מנקודת קצה).
כדי למחוק את קטגוריית האחסון, באמצעות תפריט הניווט במסוף Cloud, עוברים אל Storage (אחסון), בוחרים את הקטגוריה ולוחצים על סמל המחיקה: