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

1. סקירה כללית

בשיעור ה-Lab הזה תלמדו איך להשתמש בתרחישי חיזוי מותאמים אישית ב-Vertex AI כדי לכתוב לוגיקה מותאמת אישית של עיבוד מקדים ועיבוד לאחרי. אומנם הדוגמה הזו מתבססת על Scikit-learn, אבל תרחישים של חיזוי בהתאמה אישית יכולים לפעול עם frameworks אחרות של למידת מכונה ב-Python כמו XGBoost, PyTorch ו-TensorFlow.

מה תלמדו

נסביר לכם איך:

  • כתיבת לוגיקה של חיזוי בהתאמה אישית באמצעות תוכניות חיזוי בהתאמה אישית
  • בדיקה מקומית של הקונטיינר והמודל להצגה בהתאמה אישית
  • בדיקת קונטיינר ההרצה בהתאמה אישית ב-Vertex AI Predictions

העלות הכוללת של הפעלת שיעור ה-Lab הזה ב-Google Cloud היא כ-1$.

2. מבוא ל-Vertex AI

במעבדה הזו נעשה שימוש במוצרי ה-AI החדשים ביותר שזמינים ב-Google Cloud. Vertex AI משלבת את חבילות ה-ML ב-Google Cloud לחוויית פיתוח חלקה. בעבר, היה אפשר לגשת למודלים שהותאמו אישית ולמודלים שהותאמו באמצעות AutoML דרך שירותים נפרדים. המוצר החדש משלב את שניהם ב-API אחד, יחד עם מוצרים חדשים אחרים. אפשר גם להעביר פרויקטים קיימים ל-Vertex AI.

Vertex AI כולל מוצרים רבים ושונים לתמיכה בתהליכי עבודה של למידת מכונה מקצה לקצה. בשיעור ה-Lab הזה נתמקד ב-Predictions וב-Workbench.

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

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

תרחיש לדוגמה

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

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

מבוא לתרחישי חיזוי מותאמים אישית

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

כדי ליצור קונטיינר מותאם אישית להצגת מודעות, צריך לכתוב שרת HTTP שעוטף את המודל שעבר אימון, מתרגם בקשות HTTP לקלט של מודל ומתרגם את הפלט של המודל לתגובות.

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

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

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

שלב 1: מפעילים את Compute Engine API

עוברים אל Compute Engine ובוחרים באפשרות Enable (הפעלה) אם היא עדיין לא מופעלת. תצטרכו את זה כדי ליצור את מכונה של המחברות.

שלב 2: מפעילים את ה-Artifact Registry API

עוברים אל Artifact Registry ובוחרים באפשרות Enable (הפעלה) אם היא עדיין לא מסומנת. הקוד הזה ישמש ליצירת קונטיינר להצגה בהתאמה אישית.

שלב 3: מפעילים את Vertex AI API

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

מרכז הבקרה של Vertex AI

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

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

התפריט של Vertex AI

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

Notebook_api

אחרי ההפעלה, לוחצים על INSTANCES ובוחרים באפשרות CREATE NEW.

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

כשהמכונה מוכנה, לוחצים על פתיחת JupyterLab כדי לפתוח אותה.

5. כתיבה של קוד אימון

שלב 1: יוצרים קטגוריה של אחסון בענן

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

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

Open_terminal

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

PROJECT_ID='your-cloud-project'

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

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

שלב 2: אימון המודל

מהטרמינל, יוצרים ספרייה חדשה בשם cpr-codelab ומוסיפים אליה cd.

mkdir cpr-codelab
cd cpr-codelab

בדפדפן הקבצים, עוברים לספרייה החדשה cpr-codelab ומשתמשים במרכז האפליקציות כדי ליצור מסמך חדש של Python 3 בשם task.ipynb.

file_browser

הספרייה cpr-codelab אמורה להיראות כך:

+ cpr-codelab/
    + task.ipynb

מדביקים את הקוד הבא במחברת.

קודם כל, כותבים קובץ requirements.txt.

%%writefile requirements.txt
fastapi
uvicorn==0.17.6
joblib~=1.0
numpy~=1.20
scikit-learn>=1.2.2
pandas
google-cloud-storage>=1.26.0,<2.0.0dev
google-cloud-aiplatform[prediction]>=1.16.0

במודל שתפרסו תהיה קבוצה שונה של יחסי תלות מותקנים מראש, בהשוואה לסביבת היומן. לכן, כדאי לרשום את כל יחסי התלות של המודל ב-requirements.txt ואז להשתמש ב-pip כדי להתקין את אותם יחסי התלות במדויק ב-notebook. בהמשך, תבדקו את המודל באופן מקומי לפני הפריסה ב-Vertex AI כדי לוודא שהסביבות תואמות.

מתקינים את יחסי התלות ב-notebook.

!pip install -U --user -r requirements.txt

הערה: תצטרכו להפעיל מחדש את הליבה אחרי שההתקנה באמצעות pip תסתיים.

restart_kernel

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

USER_SRC_DIR = "src_dir"
!mkdir $USER_SRC_DIR
!mkdir model_artifacts

# copy the requirements to the source dir
!cp requirements.txt $USER_SRC_DIR/requirements.txt

הספרייה cpr-codelab אמורה להיראות כך:

+ cpr-codelab/
    + model_artifacts/
    + scr_dir/
        + requirements.txt
    + task.ipynb
    + requirements.txt

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

קודם כול, מייבאים את הספריות.

import seaborn as sns
import numpy as np
import pandas as pd

from sklearn import preprocessing
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import make_pipeline
from sklearn.compose import make_column_transformer

import joblib
import logging

# set logging to see the docker container logs
logging.basicConfig(level=logging.INFO)

לאחר מכן מגדירים את המשתנים הבאים. חשוב להחליף את PROJECT_ID במזהה הפרויקט ואת BUCKET_NAME בקטגוריה שיצרתם בשלב הקודם.

REGION = "us-central1"
MODEL_ARTIFACT_DIR = "sklearn-model-artifacts"
REPOSITORY = "diamonds"
IMAGE = "sklearn-image"
MODEL_DISPLAY_NAME = "diamonds-cpr"

# Replace with your project
PROJECT_ID = "{PROJECT_ID}"

# Replace with your bucket
BUCKET_NAME = "gs://{BUCKET_NAME}"

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

data = sns.load_dataset('diamonds', cache=True, data_home=None)

label = 'price'

y_train = data['price']
x_train = data.drop(columns=['price'])

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

x_train.head()

והתוויות, שהן המחירים המתאימים.

y_train.head()

עכשיו מגדירים טרנספורמציה של עמודה ב-sklearn כדי לבצע קידוד חם אחד של התכונות הקטגוריות ומתאימים את קנה המידה של התכונות המספריות

column_transform = make_column_transformer(
    (preprocessing.OneHotEncoder(), [1,2,3]),
    (preprocessing.StandardScaler(), [0,4,5,6,7,8]))

מגדירים את מודל היער האקראי

regr = RandomForestRegressor(max_depth=10, random_state=0)

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

my_pipeline = make_pipeline(column_transform, regr)

התאמת צינור עיבוד הנתונים לנתוני האימון

my_pipeline.fit(x_train, y_train)

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

my_pipeline.predict([[0.23, 'Ideal', 'E', 'SI2', 61.5, 55.0, 3.95, 3.98, 2.43]])

עכשיו אפשר לשמור את צינור עיבוד הנתונים בספרייה model_artifacts ולהעתיק אותו לקטגוריה של Cloud Storage.

joblib.dump(my_pipeline, 'model_artifacts/model.joblib')

!gsutil cp model_artifacts/model.joblib {BUCKET_NAME}/{MODEL_ARTIFACT_DIR}/

שלב 3: שמירת ארטיפקט של עיבוד מקדים

בשלב הבא תיצורו פריט מידע שנוצר בתהליך פיתוח (artifact) לעיבוד מקדים. הארטיפקט הזה יוטמע בקונטיינר המותאם אישית כששרת המודלים יופעל. הארטיפקט של העיבוד המקדים יכול להיות כמעט בכל צורה (למשל קובץ pickle), אבל במקרה הזה תכתבו מילון לקובץ JSON.

clarity_dict={"Flawless": "FL",
              "Internally Flawless": "IF",
              "Very Very Slightly Included": "VVS1",
              "Very Slightly Included": "VS2",
              "Slightly Included": "S12",
              "Included": "I3"}

המאפיין clarity בנתוני האימון שלנו תמיד הופיע בקיצור (למשל 'FL' במקום 'ללא שגיאות'). בזמן ההצגה, אנחנו רוצים לוודא שהנתונים של התכונה הזו מקוצרים גם כן. הסיבה לכך היא שהמודל שלנו יודע לבצע קידוד חד-מצב (one hot) של 'FL', אבל לא של 'Flawless'. נכתוב את הלוגיקה המותאמת אישית של העיבוד המקדים בהמשך. אבל בינתיים, פשוט שומרים את טבלת החיפוש הזו בקובץ JSON ולאחר מכן כותבים אותה לקטגוריה של Cloud Storage.

import json
with open("model_artifacts/preprocessor.json", "w") as f:
    json.dump(clarity_dict, f)

!gsutil cp model_artifacts/preprocessor.json {BUCKET_NAME}/{MODEL_ARTIFACT_DIR}/

ספריית cpr-codelab המקומית אמורה להיראות עכשיו כך:

+ cpr-codelab/
    + model_artifacts/
        + model.joblib
        + preprocessor.json
    + scr_dir/
        + requirements.txt
    + task.ipynb
    + requirements.txt

6. פיתוח קונטיינר מותאם אישית להצגת מודלים באמצעות שרת המודלים של CPR

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

מאגר תגים בהתאמה אישית מכיל את 3 קטעי הקוד הבאים:

  1. שרת מודל (ה-SDK ייצור אותו באופן אוטומטי ויאחסן אותו ב-scr_dir/)
    • שרת HTTP שמארח את המודל
    • אחראי על הגדרת מסלולים/יציאות וכו'.
  2. Request Handler
    • אחראי על היבטים של שרת האינטרנט בטיפול בבקשה, כמו ביצוע פעולת הסרת הסריאליזציה (deserialization) של גוף הבקשה, ביצוע פעולת הסריאליזציה (serialization) של התגובה, הגדרת כותרות התגובה וכו'.
    • בדוגמה הזו נשתמש ב-Handler שמוגדר כברירת מחדל, google.cloud.aiplatform.prediction.handler.PredictionHandler, שסופק ב-SDK.
  3. Predictor
    • אחראי ללוגיקת למידת המכונה בעיבוד בקשת חיזוי.

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

הכלי לחיזוי אחראי על הלוגיקה של למידת המכונה לעיבוד בקשת חיזוי, כמו עיבוד מקדים מותאם אישית ועיבוד לאחר העיבוד המקדים. כדי לכתוב לוגיקה של חיזוי בהתאמה אישית, צריך ליצור תת-מחלקה לממשק Vertex AI Predictor.

במהדורה הזו של שגרות חיזוי בהתאמה אישית יש מודלים חזויים של XGBoost ו-Sklearn לשימוש חוזר, אבל אם אתם צריכים להשתמש במסגרת אחרת, תוכלו ליצור מודלים משלכם על ידי יצירת צאצא של מודל החיזוי הבסיסי.

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

sklearn_predictor

מדביקים את הקוד הבא ביומן כדי ליצור תת-סוג של SklearnPredictor ולכתוב אותו בקובץ Python ב-src_dir/. לתשומת ליבך: בדוגמה הזו אנחנו מבצעים התאמה אישית רק של השיטות load, preprocess ו-postprocess, ולא של השיטה predict.

%%writefile $USER_SRC_DIR/predictor.py

import joblib
import numpy as np
import json

from google.cloud import storage
from google.cloud.aiplatform.prediction.sklearn.predictor import SklearnPredictor


class CprPredictor(SklearnPredictor):

    def __init__(self):
        return

    def load(self, artifacts_uri: str) -> None:
        """Loads the sklearn pipeline and preprocessing artifact."""

        super().load(artifacts_uri)

        # open preprocessing artifact
        with open("preprocessor.json", "rb") as f:
            self._preprocessor = json.load(f)


    def preprocess(self, prediction_input: np.ndarray) -> np.ndarray:
        """Performs preprocessing by checking if clarity feature is in abbreviated form."""

        inputs = super().preprocess(prediction_input)

        for sample in inputs:
            if sample[3] not in self._preprocessor.values():
                sample[3] = self._preprocessor[sample[3]]
        return inputs

    def postprocess(self, prediction_results: np.ndarray) -> dict:
        """Performs postprocessing by rounding predictions and converting to str."""

        return {"predictions": [f"${value}" for value in np.round(prediction_results)]}

בואו נבחן לעומק כל אחת מהשיטות האלה.

  • ה-method load נטענת בארטיפקט של עיבוד מראש, שבמקרה הזה הוא מילון שממפה את ערכי הבהירות של היהלום לקיצורים שלהם.
  • השיטה preprocess משתמשת באובייקט הזה כדי לוודא שבזמן ההצגה, תכונת הבהירות תהיה בפורמט המקוצר שלה. אם לא, הוא ממיר את המחרוזת המלאה לקיצורה.
  • השיטה postprocess מחזירה את הערך החזוי כמחרוזת עם הסימן $, ומעגלת את הערך.

בשלב הבא משתמשים ב-Vertex AI Python SDK כדי ליצור את התמונה. באמצעות תוכניות חיזוי בהתאמה אישית, המערכת תיצור את קובץ ה-Dockerfile ותבנה את קובץ האימג' בשבילכם.

from google.cloud import aiplatform

aiplatform.init(project=PROJECT_ID, location=REGION)

import os

from google.cloud.aiplatform.prediction import LocalModel

from src_dir.predictor import CprPredictor  # Should be path of variable $USER_SRC_DIR

local_model = LocalModel.build_cpr_model(
    USER_SRC_DIR,
    f"{REGION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}",
    predictor=CprPredictor,
    requirements_path=os.path.join(USER_SRC_DIR, "requirements.txt"),
)

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

import json

sample = {"instances": [
  [0.23, 'Ideal', 'E', 'VS2', 61.5, 55.0, 3.95, 3.98, 2.43],
  [0.29, 'Premium', 'J', 'Internally Flawless', 52.5, 49.0, 4.00, 2.13, 3.11]]}

with open('instances.json', 'w') as fp:
    json.dump(sample, fp)

בודקים את הקונטיינר באופן מקומי על ידי פריסת מודל מקומי.

with local_model.deploy_to_local_endpoint(
    artifact_uri = 'model_artifacts/', # local path to artifacts
) as local_endpoint:
    predict_response = local_endpoint.predict(
        request_file='instances.json',
        headers={"Content-Type": "application/json"},
    )

    health_check_response = local_endpoint.run_health_check()

אפשר לראות את תוצאות התחזית באמצעות:

predict_response.content

7. פריסה של מודל ב-Vertex AI

אחרי שבדקתם את הקונטיינר באופן מקומי, הגיע הזמן לדחוף את התמונה ל-Artifact Registry ולהעלות את המודל ל-Vertex AI Model Registry.

קודם צריך להגדיר את Docker כדי לגשת ל-Artifact Registry.

!gcloud artifacts repositories create {REPOSITORY} --repository-format=docker \
--location=us-central1 --description="Docker repository"


!gcloud auth configure-docker {REGION}-docker.pkg.dev --quiet

לאחר מכן, דוחפים את התמונה.

local_model.push_image()

מעלים את המודל.

model = aiplatform.Model.upload(local_model = local_model,
                                display_name=MODEL_DISPLAY_NAME,
                                artifact_uri=f"{BUCKET_NAME}/{MODEL_ARTIFACT_DIR}",)

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

model_registry

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

endpoint = model.deploy(machine_type="n1-standard-2")

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

endpoint.predict(instances=[[0.23, 'Ideal', 'E', 'VS2', 61.5, 55.0, 3.95, 3.98, 2.43]])

🎉 מזל טוב! 🎉

למדתם איך להשתמש ב-Vertex AI כדי:

  • כתיבת לוגיקה מותאמת אישית של עיבוד מקדים ועיבוד לאחרי עיבוד באמצעות תוכניות חיזוי בהתאמה אישית

מידע נוסף על החלקים השונים של Vertex AI זמין במסמכי התיעוד.

8. הסרת המשאבים

אם אתם רוצים להמשיך להשתמש במחברת שיצרתם במעבדה הזו, מומלץ לכבות אותה כשהיא לא בשימוש. בממשק המשתמש של Workbench במסוף Google Cloud, בוחרים את ה-notebook ואז לוחצים על Stop.

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

Stop_nb

כדי למחוק את נקודת הקצה שפרסמתם, עוברים לקטע Endpoints במסוף, לוחצים על נקודת הקצה שיצרתם ובוחרים באפשרות Undeploy model from endpoint:

delete_endpoint

כדי למחוק את קובץ האימג' בקונטיינר, עוברים אל Artifact Registry, בוחרים את המאגר שיצרתם ולוחצים על Delete.

delete_image

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

מחיקת אחסון