Vertex AI: מודלים של מארחים נוספים באותה מכונה וירטואלית עבור חיזויים

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 הזה נתמקד במוצרים שמודגשים בהמשך: תחזיות וסביבת עבודה

סקירה כללית על מוצר Vertex

3. סקירה כללית של תרחישי שימוש

כשפורסים מודלים בשירות החיזוי של Vertex AI, כל מודל נפרס כברירת מחדל במכונה וירטואלית משלו. כדי להוזיל את עלויות האירוח, אפשר לארח כמה מודלים באותה מכונה וירטואלית, וכך לשפר את ניצול הזיכרון ומשאבי המחשוב. מספר המודלים שתבחרו לפרוס באותה מכונה וירטואלית יהיה תלוי בגדלים של המודלים ובדפוסי התנועה, אבל התכונה הזו שימושית במיוחד לתרחישים שבהם יש לכם הרבה מודלים פרוסים עם תנועה דלילה.

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

deployment_pool

4. הגדרת הסביבה

כדי להפעיל את ה-codelab הזה, צריך פרויקט ב-Google Cloud Platform שמופעל בו חיוב. כדי ליצור פרויקט, פועלים לפי ההוראות האלה.

שלב 1: הפעלת Compute Engine API

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

שלב 2: הפעלת Vertex AI API

עוברים אל הקטע Vertex AI במסוף Cloud ולוחצים על הפעלת Vertex AI API.

לוח הבקרה של Vertex AI

שלב 3: יצירת מכונה של Vertex AI Workbench

בקטע Vertex AI במסוף Cloud, לוחצים על Workbench:

תפריט Vertex AI

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

Notebook_api

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

Notebooks_UI

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

new_notebook

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

create_notebook

לוחצים על הגדרות מתקדמות.

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

enable_terminal

אפשר להשאיר את כל ההגדרות המתקדמות האחרות כמו שהן.

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

אחרי שיוצרים את המופע, בוחרים באפשרות OPEN JUPYTERLAB (פתיחת JupyterLab).

open_jupyterlab

5. דגם הרכבת

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

שלב 1: יצירת קטגוריה של Cloud Storage

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

launcher_terminal

במסוף, מריצים את הפקודה הבאה כדי להגדיר משתנה סביבה לפרויקט. חשוב להחליף את your-cloud-project במזהה הפרויקט:

PROJECT_ID='your-cloud-project'

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

BUCKET="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET

שלב 2: הרצת מחברת

ממרכז האפליקציות של מופע Workbench, פותחים מחברת חדשה של TensorFlow 2.

launcher_tf2

הקוד שבהמשך מאמן מסווג סנטימנטים בינארי (חיובי או שלילי) על מערך הנתונים של ביקורות על סרטים מ-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 (הפעלה).

execute_nb

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

execution_config

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

execution_status

6. פריסת מודל

שלב 1: העלאת מודל

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

tf_nb

קודם מייבאים את 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. סטטוס הפריסה ריק כי עדיין לא פרסנו את המודלים.

model_registry

שלב 2: יצירת נקודת קצה

יוצרים נקודת קצה. שימו לב: זה שונה מפריסת מודל בנקודת קצה.

endpoint = aiplatform.Endpoint.create('cohost-endpoint')

אחרי שנקודת הקצה נוצרת, היא מופיעה במסוף.

console_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_1_endpoint

לאחר מכן, אפשר לפרוס את 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}'

שוב, בדוגמה הזו שני המודלים נפרסו לאותה נקודת קצה, אבל אפשר גם לארח במשותף מודלים באותו מאגר משאבים שנפרסו לנקודות קצה שונות. במקרה כזה, לא צריך לדאוג לגבי פיצול התנועה.

אחרי הפריסה של המודל השני, שניהם יופיעו במסוף.

deployed_models

שלב 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. הסרת המשאבים

אם אתם לא מתכננים להשתמש במודלים, כדאי לבטל את הפריסה שלהם מנקודת הקצה. אפשר גם למחוק את נקודת הקצה לגמרי. תמיד אפשר לפרוס מחדש מודל לנקודת קצה אם צריך.

undeploy_model

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

עצירת מכונה

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

מחיקת האחסון