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

3. סקירה כללית של תרחישי שימוש
כשפורסים מודלים בשירות החיזוי של Vertex AI, כל מודל נפרס כברירת מחדל במכונה וירטואלית משלו. כדי להוזיל את עלויות האירוח, אפשר לארח כמה מודלים באותה מכונה וירטואלית, וכך לשפר את ניצול הזיכרון ומשאבי המחשוב. מספר המודלים שתבחרו לפרוס באותה מכונה וירטואלית יהיה תלוי בגדלים של המודלים ובדפוסי התנועה, אבל התכונה הזו שימושית במיוחד לתרחישים שבהם יש לכם הרבה מודלים פרוסים עם תנועה דלילה.
התמיכה במודל של אירוח משותף מציגה את הרעיון של מאגר משאבי פריסה, שמקבץ מודלים כדי לשתף משאבים במכונה וירטואלית. מודלים יכולים לשתף מכונה וירטואלית אם הם חולקים נקודת קצה, וגם אם הם נפרסים בנקודות קצה שונות. נכון לעכשיו, למודלים באותו מאגר משאבים צריך להיות אותו קובץ אימג' של קונטיינר, כולל גרסת המסגרת של קונטיינרים מוכנים מראש של Vertex חיזוי (Prediction). בנוסף, בגרסה הזו יש תמיכה רק בקונטיינרים מוכנים מראש של Vertex Prediction עם מסגרת מודל Tensorflow. מסגרות מודל אחרות וקונטיינרים בהתאמה אישית עדיין לא נתמכים.

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

שלב 3: יצירת מכונה של Vertex AI Workbench
בקטע Vertex AI במסוף Cloud, לוחצים על Workbench:

מפעילים את Notebooks API אם הוא עדיין לא מופעל.

אחרי ההפעלה, לוחצים על מחברות מנוהלות:

לאחר מכן בוחרים באפשרות מחברת חדשה.

נותנים שם למחברת, ובקטע הרשאה בוחרים באפשרות חשבון שירות.

לוחצים על הגדרות מתקדמות.
בקטע אבטחה, בוחרים באפשרות 'הפעלת מסוף' אם היא עדיין לא מופעלת.

אפשר להשאיר את כל ההגדרות המתקדמות האחרות כמו שהן.
אחרי כן, לוחצים על יצירה. ייקח כמה דקות עד שהמופע יוקצה.
אחרי שיוצרים את המופע, בוחרים באפשרות OPEN JUPYTERLAB (פתיחת JupyterLab).

5. דגם הרכבת
כדי להתנסות בתכונת האירוח המשותף, קודם צריך לאמן מודל ולאחסן את הארטיפקטים של המודל השמור בקטגוריה של Cloud Storage. נשתמש במפעיל ה-notebook של Workbench כדי להפעיל את משימת האימון.
שלב 1: יצירת קטגוריה של Cloud Storage
אם יש לכם קטגוריה קיימת בפרויקט שבה אתם רוצים להשתמש, אתם יכולים לדלג על השלב הזה. אחרת, פותחים סשן טרמינל חדש ממרכז האפליקציות.

במסוף, מריצים את הפקודה הבאה כדי להגדיר משתנה סביבה לפרויקט. חשוב להחליף את your-cloud-project במזהה הפרויקט:
PROJECT_ID='your-cloud-project'
לאחר מכן, מריצים את הפקודה הבאה כדי ליצור קטגוריה חדשה בפרויקט.
BUCKET="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET
שלב 2: הרצת מחברת
ממרכז האפליקציות של מופע Workbench, פותחים מחברת חדשה של TensorFlow 2.

הקוד שבהמשך מאמן מסווג סנטימנטים בינארי (חיובי או שלילי) על מערך הנתונים של ביקורות על סרטים מ-IMDB. מדביקים את הקוד ב-Notebook.
חשוב להחליף את {YOUR_BUCKET} בקטגוריה שיצרתם בשלב הקודם (או בקטגוריה אחרת בפרויקט). כאן נאחסן את הארטיפקטים של המודל השמור, שנצטרך בהמשך כשנעלה את המודל למרשם המודלים של Vertex AI.
import numpy as np
import tensorflow_datasets as tfds
import tensorflow as tf
# REPLACE WITH YOUR BUCKET!
OUTPUT_PATH='gs://{YOUR_BUCKET}/model_output'
BUFFER_SIZE = 10000
BATCH_SIZE = 64
VOCAB_SIZE = 1000
# Load data
dataset, info = tfds.load('imdb_reviews', with_info=True,
as_supervised=True)
train_dataset, test_dataset = dataset['train'], dataset['test']
train_dataset = train_dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)
test_dataset = test_dataset.batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)
# Create text encoder
encoder = tf.keras.layers.TextVectorization(
max_tokens=VOCAB_SIZE)
encoder.adapt(train_dataset.map(lambda text, label: text))
# Create model
model = tf.keras.Sequential([
encoder,
tf.keras.layers.Embedding(
input_dim=len(encoder.get_vocabulary()),
output_dim=64,
# Use masking to handle the variable sequence lengths
mask_zero=True),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1)
])
# Compile model
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
optimizer=tf.keras.optimizers.Adam(1e-4),
metrics=['accuracy'])
# Fit model
history = model.fit(train_dataset, epochs=10,
validation_data=test_dataset,
validation_steps=30)
# Save model
model.save(OUTPUT_PATH)
לאחר מכן לוחצים על הלחצן Execute (הפעלה).

לאחר מכן מגדירים את ההפעלה באופן הבא ולוחצים על שליחה.

בכרטיסייה 'הפעלות' במסוף, אפשר לעקוב אחרי הסטטוס של משימת האימון.

6. פריסת מודל
שלב 1: העלאת מודל
כשההפעלה מסתיימת, חוזרים למחברת של Workbench כדי להעלות את המודל. יוצרים מחברת TensorFlow חדשה.

קודם מייבאים את Vertex AI Python SDK
from google.cloud import aiplatform
לאחר מכן מעלים את המודל, ומחליפים את {YOUR_BUCKET} בדלי שצוין בקוד האימון.
# replace {YOUR_BUCKET}
model_1 = aiplatform.Model.upload(display_name='text-model-1',
artifact_uri='gs://{YOUR_BUCKET}/model_output',
serving_container_image_uri='us-docker.pkg.dev/vertex-ai/prediction/tf2-cpu.2-8:latest')
לצורך הדגמה, נעלה את המודל הזה פעמיים, וניצור שני משאבי מודל שונים ב-Vertex AI. אנחנו עושים את זה כדי לבדוק פריסה של כמה מודלים לנקודת קצה אחת במאגר משאבי פריסה. בתרחיש אמיתי, היו לכם שני מודלים שונים במקום ליצור מודלים מאותם ארטיפקטים שמורים, אבל זה קיצור דרך כדי שלא נצטרך להפעיל עוד הרצה. בנוסף, אפשר גם לבחור לפרוס את שני המודלים לנקודות קצה שונות באותו מאגר משאבי פריסה.
# replace {YOUR_BUCKET}
model_2 = aiplatform.Model.upload(display_name='text-model-2',
artifact_uri='gs://{YOUR_BUCKET}/model_output',
serving_container_image_uri='us-docker.pkg.dev/vertex-ai/prediction/tf2-cpu.2-8:latest')
עכשיו אמורים לראות את שני המודלים במרשם המודלים של Vertex AI. סטטוס הפריסה ריק כי עדיין לא פרסנו את המודלים.

שלב 2: יצירת נקודת קצה
יוצרים נקודת קצה. שימו לב: זה שונה מפריסת מודל בנקודת קצה.
endpoint = aiplatform.Endpoint.create('cohost-endpoint')
אחרי שנקודת הקצה נוצרת, היא מופיעה במסוף.

שלב 3: יצירת DeploymentResourcePool
אפשר ליצור את DeploymentResourcePool באמצעות הפקודה הבאה. חשוב להחליף את {YOUR_PROJECT} במזהה הפרויקט.
# replace {YOUR_PROJECT}
PROJECT_ID={YOUR_PROJECT}
REGION="us-central1"
VERTEX_API_URL=REGION + "-aiplatform.googleapis.com"
VERTEX_PREDICTION_API_URL=REGION + "-prediction-aiplatform.googleapis.com"
MULTI_MODEL_API_VERSION="v1beta1"
# Give the pool a name
DEPLOYMENT_RESOURCE_POOL_ID="my-resource-pool"
import json
import pprint
pp = pprint.PrettyPrinter(indent=4)
CREATE_RP_PAYLOAD = {
"deployment_resource_pool":{
"dedicated_resources":{
"machine_spec":{
"machine_type":"n1-standard-4"
},
"min_replica_count":1,
"max_replica_count":2
}
},
"deployment_resource_pool_id":DEPLOYMENT_RESOURCE_POOL_ID
}
CREATE_RP_REQUEST=json.dumps(CREATE_RP_PAYLOAD)
pp.pprint("CREATE_RP_REQUEST: " + CREATE_RP_REQUEST)
!curl \
-X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools \
-d '{CREATE_RP_REQUEST}'
אפשר לראות את המאגר על ידי הרצת הפקודה
!curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools/{DEPLOYMENT_RESOURCE_POOL_ID}
שלב 4: פורסים את המודלים בנקודת הקצה
אחרי שיצרנו את מאגר המשאבים, אנחנו יכולים לפרוס את המודלים בתוך מאגר המשאבים.
קודם נבצע פריסה של model_1. חשוב להחליף את MODEL_1_ID ו-ENDPOINT_ID במזהים המתאימים.
MODEL_1_ID="{MODEL_1_ID}"
ENDPOINT_ID="{ENDPOINT_ID}"
הפקודה הבאה תפרוס את model_1 לנקודת הקצה במאגר המשאבים.
MODEL_NAME = "projects/{project_id}/locations/{region}/models/{model_id}".format(project_id=PROJECT_ID, region=REGION, model_id=MODEL_1_ID)
SHARED_RESOURCE = "projects/{project_id}/locations/{region}/deploymentResourcePools/{deployment_resource_pool_id}".format(project_id=PROJECT_ID, region=REGION, deployment_resource_pool_id=DEPLOYMENT_RESOURCE_POOL_ID)
DEPLOY_MODEL_PAYLOAD = {
"deployedModel": {
"model": MODEL_NAME,
"shared_resources": SHARED_RESOURCE
},
"trafficSplit": {
"0": 100
}
}
DEPLOY_MODEL_REQUEST=json.dumps(DEPLOY_MODEL_PAYLOAD)
pp.pprint("DEPLOY_MODEL_REQUEST: " + DEPLOY_MODEL_REQUEST)
!curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/endpoints/{ENDPOINT_ID}:deployModel \
-d '{DEPLOY_MODEL_REQUEST}'
הפעולה הזו תימשך כמה דקות, וכשהיא תסתיים תראו שהמודל נפרס לנקודת הקצה במסוף.

לאחר מכן, אפשר לפרוס את model_2 באותו מאגר פריסה. אנחנו נפיץ אותו לאותה נקודת קצה כמו model_1. עם זאת, אפשר גם לבחור לפרוס אתmodel_2 לנקודת קצה אחרת באותו מאגר משאבים.
מעדכנים את MODEL_ID עם המזהה של model_2. שוב, אפשר לקבל את המזהה הזה על ידי הרצת model_2.name
MODEL_2_ID="{MODEL_2_ID}"
אחר כך פורסים את model_2. מכיוון שכבר פרסנו את model_1 בנקודת הקצה, נצטרך לעדכן את trafficSplit כך שהתנועה תפוצל בין שני המודלים. לא נצטרך לעדכן את trafficSplit אם נבחר לפרוס את model_2 לנקודת קצה אחרת באותו מאגר משאבים.
כדי לעדכן את חלוקת התנועה, צריך להגדיר את מזהה ה-DeployedModel של model_1. שימו לב, זה לא מזהה המודל.
DEPLOYED_MODEL_1_ID = {DEPLOYED_MODEL_1_ID}
לאחר מכן מריצים את הפקודה הבאה כדי לפרוס את המודל השני.
MODEL_NAME = "projects/{project_id}/locations/{region}/models/{model_id}".format(project_id=PROJECT_ID, region=REGION, model_id=MODEL_2_ID)
SHARED_RESOURCE = "projects/{project_id}/locations/{region}/deploymentResourcePools/{deployment_resource_pool_id}".format(project_id=PROJECT_ID, region=REGION, deployment_resource_pool_id=DEPLOYMENT_RESOURCE_POOL_ID)
#`trafficSplit` is a map from a DeployedModel's ID to the percentage of this Endpoint's traffic that should be forwarded to that DeployedModel.
# The traffic percentage values for an endpoint must add up to 100.
# The key for the model being deployed is "0".
DEPLOY_MODEL_PAYLOAD = {
"deployedModel": {
"model": MODEL_NAME,
"shared_resources": SHARED_RESOURCE
},
"trafficSplit": {
"0": 50,
DEPLOYED_MODEL_1_ID: 50
}
}
DEPLOY_MODEL_REQUEST=json.dumps(DEPLOY_MODEL_PAYLOAD)
pp.pprint("DEPLOY_MODEL_REQUEST: " + DEPLOY_MODEL_REQUEST)
!curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://{VERTEX_API_URL}/{MULTI_MODEL_API_VERSION}/projects/{PROJECT_ID}/locations/{REGION}/endpoints/{ENDPOINT_ID}:deployModel \
-d '{DEPLOY_MODEL_REQUEST}'
שוב, בדוגמה הזו שני המודלים נפרסו לאותה נקודת קצה, אבל אפשר גם לארח במשותף מודלים באותו מאגר משאבים שנפרסו לנקודות קצה שונות. במקרה כזה, לא צריך לדאוג לגבי פיצול התנועה.
אחרי הפריסה של המודל השני, שניהם יופיעו במסוף.

שלב 5: קבלת תחזיות
השלב האחרון הוא לבדוק את נקודת הקצה ולקבל תחזיות.
קודם כול, מגדירים את משפט הבדיקה.
x_test=['The movie was cool. The animation and the graphics were out of this world. I would recommend this movie.']
לאחר מכן, מפעילים את הפונקציה predict בנקודת הקצה, והיא תחזיר חיזוי מאחד מהמודלים שנפרסו בנקודת הקצה.
endpoint.predict(instances=x_test)
🎉 איזה כיף! 🎉
למדתם איך להשתמש ב-Vertex AI כדי:
- אירוח משותף של מודלים באותה מכונה וירטואלית לחיזויים אונליין
מידע נוסף על חלקים שונים ב-Vertex זמין בתיעוד.
7. הסרת המשאבים
אם אתם לא מתכננים להשתמש במודלים, כדאי לבטל את הפריסה שלהם מנקודת הקצה. אפשר גם למחוק את נקודת הקצה לגמרי. תמיד אפשר לפרוס מחדש מודל לנקודת קצה אם צריך.

מחברות מנוהלות ב-Workbench מקבלות פסק זמן אוטומטי אחרי 180 דקות של חוסר פעילות, כך שלא צריך לדאוג לכיבוי המופע. אם רוצים להשבית את המופע באופן ידני, לוחצים על הלחצן Stop (הפסקה) בקטע Vertex AI Workbench במסוף. כדי למחוק את ה-Notebook לגמרי, לוחצים על לחצן המחיקה.

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