1. סקירה כללית
בשיעור ה-Lab הזה תשתמשו ב-Vertex AI כדי לאמן מודל TensorFlow ולהכניס אותו לשימוש בסביבת הייצור באמצעות קוד בקונטיינר בהתאמה אישית.
אמנם אנחנו משתמשים ב-TensorFlow לקוד המודל כאן, אבל אפשר להחליף אותו בקלות ב-framework אחר.
מה לומדים
במאמר הזה נסביר איך:
- יצירה של קוד לאימון מודלים והעברה שלו לקונטיינר ב-Vertex Workbench
- שליחת משימת אימון של מודל בהתאמה אישית אל Vertex AI
- פריסת המודל שאומן לנקודת קצה, ושימוש בנקודת הקצה הזו כדי לקבל חיזויים
העלות הכוללת להרצת שיעור ה-Lab הזה ב-Google Cloud היא בערך 1$.
2. מבוא ל-Vertex AI
בשיעור ה-Lab הזה נעשה שימוש במוצר ה-AI החדש ביותר שזמין ב-Google Cloud. Vertex AI משלב את מוצרי ה-ML ב-Google Cloud לחוויית פיתוח חלקה. בעבר, היה אפשר לגשת למודלים שאומנו באמצעות AutoML ולמודלים בהתאמה אישית דרך שירותים נפרדים. המוצר החדש משלב את שניהם ב-API אחד, יחד עם מוצרים חדשים אחרים. אפשר גם להעביר פרויקטים קיימים אל Vertex AI. אם יש לך משוב, אפשר לעיין בדף התמיכה.
Vertex AI כולל מוצרים רבים ושונים לתמיכה בתהליכי עבודה של למידת מכונה מקצה לקצה. בשיעור ה-Lab הזה נתמקד במוצרים שמודגשים בהמשך: אימון, חיזוי ו-Workbench.

3. הגדרת הסביבה
כדי להפעיל את ה-codelab הזה, צריך פרויקט ב-Google Cloud Platform שמופעל בו חיוב. כדי ליצור פרויקט, פועלים לפי ההוראות האלה.
שלב 1: הפעלת Compute Engine API
עוברים אל Compute Engine ובוחרים באפשרות הפעלה אם הוא עדיין לא מופעל. תצטרכו את זה כדי ליצור את מופע המחברת.
שלב 2: הפעלת Vertex AI API
עוברים אל הקטע Vertex AI במסוף Cloud ולוחצים על הפעלת Vertex AI API.

שלב 3: הפעלת Container Registry API
עוברים אל Container Registry ובוחרים באפשרות Enable (הפעלה) אם היא עדיין לא מסומנת. תשתמשו בזה כדי ליצור קונטיינר למשימת האימון המותאמת אישית.
שלב 4: יצירת מכונה של Vertex AI Workbench
בקטע Vertex AI במסוף Cloud, לוחצים על Workbench:

משם, בקטע Notebooks בניהול המשתמשים, לוחצים על New Notebook:

לאחר מכן בוחרים את הגרסה האחרונה של סוג האינסטנס TensorFlow Enterprise (with LTS) without GPUs:

משתמשים באפשרויות ברירת המחדל ולוחצים על יצירה.
המודל שנאמן ונשתמש בו בשיעור ה-Lab הזה מבוסס על המדריך הזה ממסמכי TensorFlow. במדריך הזה נעשה שימוש במערך הנתונים Auto MPG מ-Kaggle כדי לחזות את יעילות צריכת הדלק של כלי רכב.
4. יצירת קונטיינר לקוד האימון
נשלח את משימת האימון הזו ל-Vertex על ידי הכנסת קוד האימון שלנו לקונטיינר Docker והעברת הקונטיינר הזה אל Google Container Registry. באמצעות הגישה הזו, אנחנו יכולים לאמן מודל שנבנה עם כל מסגרת.
כדי להתחיל, בתפריט מרכז האפליקציות, פותחים חלון הטרמינל במופע של מחברת:

יוצרים ספרייה חדשה בשם mpg ועוברים אליה באמצעות הפקודה cd:
mkdir mpg
cd mpg
שלב 1: יצירת Dockerfile
השלב הראשון שלנו ביצירת קונטיינר לקוד הוא ליצור קובץ Dockerfile. בקובץ Dockerfile נכלול את כל הפקודות שנדרשות להרצת התמונה. הסקריפט יתקין את כל הספריות שבהן אנחנו משתמשים ויגדיר את נקודת הכניסה לקוד ההדרכה. ב-Terminal, יוצרים קובץ Dockerfile ריק:
touch Dockerfile
פותחים את Dockerfile ומעתיקים לתוכו את הקוד הבא:
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"]
קובץ ה-Dockerfile הזה משתמש בקובץ האימג' של Docker TensorFlow Enterprise 2.3 של Deep Learning Container. הקונטיינרים של Deep Learning ב-Google Cloud מגיעים עם הרבה frameworks נפוצים של ML ומדעי נתונים שהותקנו מראש. הסביבה שבה אנחנו משתמשים כוללת את TF Enterprise 2.3, Pandas, Scikit-learn ועוד. אחרי שמורידים את התמונה הזו, קובץ ה-Docker הזה מגדיר את נקודת הכניסה לקוד האימון שלנו. עדיין לא יצרנו את הקבצים האלה – בשלב הבא נוסיף את הקוד לאימון ולייצוא של המודל.
שלב 2: יצירת קטגוריה של Cloud Storage
במשימת האימון שלנו, נייצא את מודל TensorFlow שאומן לקטגוריה של Cloud Storage. Vertex ישתמש בזה כדי לקרוא את נכסי המודל המיוצאים ולפרוס את המודל. במסוף, מריצים את הפקודה הבאה כדי להגדיר משתנה סביבה לפרויקט. חשוב להחליף את 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: פיתוח ובדיקה של הקונטיינר באופן מקומי
בטרמינל, מגדירים משתנה עם ה-URI של קובץ אימג' של קונטיינר ב-Google Container Registry:
IMAGE_URI="gcr.io/$PROJECT_ID/mpg:v1"
לאחר מכן, בונים את הקונטיינר על ידי הרצת הפקודה הבאה מתיקיית השורש של mpg:
docker build ./ -t $IMAGE_URI
מריצים את הקונטיינר במופע של notebook כדי לוודא שהוא פועל בצורה תקינה:
docker run $IMAGE_URI
האימון של המודל אמור להסתיים תוך דקה או שתיים, עם דיוק אימות של כ-72% (הדיוק המדויק עשוי להשתנות). כשמסיימים להריץ את הקונטיינר באופן מקומי, מעלים אותו אל Google Container Registry:
docker push $IMAGE_URI
אחרי שדחפנו את מאגר התגים ל-Container Registry, אפשר להתחיל להריץ משימת אימון של מודל בהתאמה אישית.
5. הרצת משימת אימון ב-Vertex AI
ב-Vertex AI יש שתי אפשרויות לאימון מודלים:
- AutoML: אימון מודלים באיכות גבוהה עם מאמץ מינימלי ומומחיות ב-ML.
- אימון מותאם אישית: הפעלת אפליקציות אימון מותאמות אישית בענן באמצעות אחד מהקונטיינרים המובנים מראש של Google Cloud, או שימוש בקונטיינר משלכם.
במעבדה הזו אנחנו משתמשים באימון מותאם אישית באמצעות קונטיינר מותאם אישית משלנו ב-Google Container Registry. כדי להתחיל, עוברים לקטע Models בקטע Vertex במסוף Cloud:

שלב 1: הפעלת משימת האימון
לוחצים על יצירה כדי להזין את הפרמטרים של משימת האימון והמודל שנפרס:
- בקטע מערך נתונים, בוחרים באפשרות אין מערך נתונים מנוהל.
- לאחר מכן בוחרים באפשרות Custom training (advanced) (אימון בהתאמה אישית (מתקדם)) בתור שיטת האימון ולוחצים על Continue (המשך).
- לוחצים על המשך.
בשלב הבא, מזינים mpg (או כל שם אחר שרוצים לתת למודל) בשדה שם המודל. לאחר מכן בוחרים באפשרות מאגר תגים בהתאמה אישית:

בתיבת הטקסט Container image (קובץ אימג' של קונטיינר), לוחצים על Browse (עיון) ומחפשים את קובץ האימג' של Docker שהעליתם ל-Container Registry. משאירים את שאר השדות ריקים ולוחצים על המשך.
במדריך הזה לא נשתמש בכוונון היפרפרמטרים, לכן משאירים את התיבה 'הפעלת כוונון היפרפרמטרים' לא מסומנת ולוחצים על המשך.
בקטע Compute and pricing, משאירים את האזור שנבחר כמו שהוא ובוחרים באפשרות n1-standard-4 כסוג המכונה:

משאירים את השדות של המאיץ ריקים ולוחצים על המשך. בגלל שהמודל בהדגמה הזו מתאמן במהירות, אנחנו משתמשים בסוג מכונה קטן יותר.
בשלב Prediction container (מאגר התחזיות), בוחרים באפשרות Pre-built container (מאגר מוכן מראש) ואז בוחרים באפשרות TensorFlow 2.6.
משאירים את הגדרות ברירת המחדל של הקונטיינר שנוצר מראש כמו שהן. בשדה Model directory (ספריית המודל), מזינים את מאגר ה-GCS עם ספריית המשנה mpg. זו הנתיב בסקריפט לאימון המודל שבו מייצאים את המודל שאומן:

Vertex יחפש במיקום הזה כשהוא יפרוס את המודל. עכשיו אפשר להתחיל להתאמן. כדי להפעיל את משימת האימון, לוחצים על Start training (התחלת האימון). בקטע 'הדרכה' במסוף, תראו משהו כזה:

6. פריסת נקודת קצה של מודל
כשמגדירים את משימת האימון, מציינים איפה ב-Vertex AI צריך לחפש את נכסי המודל המיוצאים. כחלק מצינור העיבוד לאימון, Vertex יוצר משאב מודל על סמך נתיב הנכס הזה. משאב המודל עצמו הוא לא מודל שנפרס, אבל אחרי שיש לכם מודל, אתם יכולים לפרוס אותו לנקודת קצה. מידע נוסף על מודלים ונקודות קצה ב-Vertex AI זמין במסמכי העזרה.
בשלב הזה ניצור נקודת קצה (endpoint) למודל שאומן. אנחנו יכולים להשתמש בזה כדי לקבל חיזויים לגבי המודל שלנו באמצעות Vertex AI API.
שלב 1: פריסת נקודת הקצה
אחרי שהאימון יסתיים, מודל בשם mpg (או השם שנתתם לו) יופיע בקטע Models במסוף:

כשמשימת האימון שלכם רצה, Vertex יוצר בשבילכם משאב מודל. כדי להשתמש במודל הזה, צריך לפרוס נקודת קצה. יכולות להיות הרבה נקודות קצה לכל מודל. לוחצים על המודל ואז על Deploy to endpoint (פריסה לנקודת קצה).
בוחרים באפשרות יצירת נקודת קצה חדשה ונותנים לה שם, כמו v1. משאירים את האפשרות רגיל מסומנת בקטע 'גישה' ולוחצים על המשך.
משאירים את הערך 100 בשדה חלוקת התנועה ומזינים 1 בשדה מספר מינימלי של צמתי מחשוב. בקטע Machine type (סוג המכונה), בוחרים באפשרות n1-standard-2 (או בכל סוג מכונה אחר שרוצים). משאירים את שאר ברירות המחדל מסומנות ולוחצים על המשך. לא נפעיל מעקב אחרי המודל הזה, לכן צריך ללחוץ על Deploy כדי להתחיל את הפריסה של נקודת הקצה.
פריסת נקודת הקצה תימשך 10-15 דקות, ותקבלו אימייל כשהפריסה תסתיים. כשהפריסה של נקודת הקצה תסתיים, תופיע התוצאה הבאה, שמראה שנקודת קצה אחת נפרסה מתחת למשאב Model:

שלב 2: קבלת תחזיות לגבי המודל שנפרס
נקבל תחזיות לגבי המודל שאומן מתוך מחברת Python, באמצעות Vertex API בשפת Python. חוזרים למופע של מחברת, ויוצרים מחברת Python 3 ממרכז האפליקציות:

במחברת, מריצים את הפקודה הבאה בתא כדי להתקין את Vertex AI SDK:
!pip3 install google-cloud-aiplatform --upgrade --user
אחר כך מוסיפים תא למחברת כדי לייבא את ה-SDK וליצור הפניה לנקודת הקצה שזה עתה פרסתם:
from google.cloud import aiplatform
endpoint = aiplatform.Endpoint(
endpoint_name="projects/YOUR-PROJECT-NUMBER/locations/us-central1/endpoints/YOUR-ENDPOINT-ID"
)
צריך להחליף שני ערכים במחרוזת endpoint_name שלמעלה במספר הפרויקט ובנקודת הקצה שלכם. כדי למצוא את מספר הפרויקט, עוברים אל מרכז הבקרה של הפרויקט ומעתיקים את הערך של 'מספר הפרויקט'.
אפשר למצוא את מזהה נקודת הקצה בקטע 'נקודות קצה' במסוף:

לבסוף, כדי ליצור תחזית לנקודת הקצה, מעתיקים את הקוד הבא ומריצים אותו בתא חדש:
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])
בדוגמה הזו כבר יש ערכים מנורמלים, שזה הפורמט שהמודל שלנו מצפה לו.
מריצים את התא הזה, וצריכה להתקבל תחזית של כ-6.8 ק"מ לליטר.
🎉 איזה כיף! 🎉
למדתם איך להשתמש ב-Vertex AI כדי:
- לאמן מודל על ידי ציון קוד האימון בקונטיינר בהתאמה אישית. בדוגמה הזו השתמשנו במודל TensorFlow, אבל אפשר לאמן מודל שנבנה עם כל מסגרת באמצעות קונטיינרים בהתאמה אישית.
- פריסת מודל TensorFlow באמצעות קונטיינר מוכן מראש כחלק מאותו תהליך עבודה שבו השתמשתם לאימון.
- יוצרים נקודת קצה של מודל ומפיקים חיזוי.
מידע נוסף על החלקים השונים של Vertex זמין בתיעוד.
7. הסרת המשאבים
אם אתם רוצים להמשיך להשתמש ב-notebook שיצרתם בשיעור Lab הזה, מומלץ לכבות אותו כשאתם לא משתמשים בו. בממשק המשתמש של Workbench במסוף Cloud, בוחרים את מחברת ה-notebook ואז בוחרים באפשרות Stop (הפסקה).
כדי למחוק את המחברת כולה, לוחצים על לחצן המחיקה בפינה השמאלית העליונה.
כדי למחוק את נקודת הקצה שפרסתם, עוברים לקטע Endpoints (נקודות קצה) במסוף Vertex AI, לוחצים על נקודת הקצה שיצרתם ואז בוחרים באפשרות Undeploy model from endpoint (ביטול פריסת המודל מנקודת הקצה):

כדי למחוק את קטגוריית האחסון, בתפריט הניווט ב-Cloud Console, עוברים אל Storage, בוחרים את הקטגוריה ולוחצים על Delete:
