Vertex AI: używanie niestandardowych procedur prognozowania ze Sklearn do wstępnego i końcowego przetwarzania danych na potrzeby prognoz

1. Omówienie

W tym module dowiesz się, jak używać niestandardowych rutyn prognozowania w Vertex AI do pisania niestandardowej logiki wstępnego i końcowego przetwarzania danych. Ten przykład wykorzystuje Scikit-learn, ale niestandardowe rutyny prognozowania mogą działać z innymi platformami ML w języku Python, takimi jak XGBoost, PyTorch i TensorFlow.

Czego się nauczysz

Poznasz takie zagadnienia jak:

  • Tworzenie niestandardowej logiki prognozowania za pomocą niestandardowych procedur prognozowania
  • Testowanie lokalnie kontenera i modela do obsługi niestandardowej
  • Testowanie niestandardowego kontenera obsługi w Vertex AI Predictions

Łączny koszt przeprowadzenia tego laboratorium w Google Cloud wynosi około 1 USD.

2. Wprowadzenie do Vertex AI

Ten moduł wykorzystuje najnowszą ofertę usług AI dostępną w Google Cloud. Vertex AI integruje rozwiązania ML w Google Cloud, zapewniając bezproblemowe środowisko programistyczne. Wcześniej modele wytrenowane za pomocą AutoML i modele niestandardowe były dostępne za pomocą oddzielnych usług. Nowa oferta łączy oba te interfejsy API z innymi nowymi usługami. Możesz też przenieść istniejące projekty do Vertex AI.

Vertex AI zawiera wiele różnych usług, które obsługują kompleksowe przepływy pracy związane z systemami uczącymi się. Tematem tego modułu są Prognozy i Workbench.

Omówienie usługi Vertex

3. Omówienie zastosowania

Przypadek użycia

W tym module utworzysz model regresji lasu losowego, aby przewidzieć cenę diamentu na podstawie atrybutów takich jak szlif, czystość i rozmiar.

Napiszesz niestandardową logikę wstępnego przetwarzania, aby sprawdzić, czy dane w momencie wyświetlania mają format oczekiwany przez model. Napiszesz też niestandardową logikę przetwarzania wstępnego, aby zaokrąglić prognozy i przekształcić je w ciągi znaków. Aby napisać tę logikę, użyjesz niestandardowych procedur prognozowania.

Wprowadzenie do niestandardowych procedur prognozowania

Gotowe kontenery Vertex AI obsługują żądania prognozy, wykonując operację prognozowania w ramach frameworku uczenia maszynowego. Jeśli przed wprowadzeniem niestandardowych procedur prognozowania chcesz przetworzyć dane wejściowe przed wykonaniem prognozy lub przetworzyć prognozę modelu przed zwróceniem wyniku, musisz utworzyć niestandardowy kontener.

Utworzenie niestandardowego kontenera do obsługi wymaga napisania serwera HTTP, który otacza wytrenowany model, przekształca żądania HTTP w dane wejściowe modelu i przekształca dane wyjściowe modelu w odpowiedzi.

Dzięki niestandardowym rutynom prognozowania Vertex AI udostępnia komponenty związane z usługami, dzięki czemu możesz skupić się na modelu i transformacjach danych.

4. Konfigurowanie środowiska

Aby uruchomić to ćwiczenie, musisz mieć projekt Google Cloud Platform z włączonym rozliczeniem. Aby utworzyć projekt, postępuj zgodnie z tymi instrukcjami.

Krok 1. Włącz interfejs Compute Engine API

Przejdź do Compute Engine i wybierz opcję Włącz, jeśli nie jest jeszcze włączona. Potrzebujesz go do utworzenia instancji notatnika.

Krok 2. Włącz interfejs Artifact Registry API

Otwórz Artifact Registry i kliknij Włącz, jeśli nie zostało to jeszcze zrobione. Użyjesz go do utworzenia niestandardowego kontenera do obsługi.

Krok 3. Włącz interfejs Vertex AI API

Przejdź do sekcji Vertex AI w konsoli Cloud i kliknij Włącz interfejs Vertex AI API.

Panel Vertex AI

Krok 4. Utwórz instancję Vertex AI Workbench

W konsoli Cloud w sekcji Vertex AI kliknij Workbench:

Menu Vertex AI

Włącz interfejs Notebooks API, jeśli nie jest jeszcze włączony.

Notebook_api

Po włączeniu kliknij INSTANCJE, a następnie UTWÓRZ NOWĄ.

Zaakceptuj domyślne opcje i kliknij Utwórz.

Gdy instancja będzie gotowa, kliknij OTWÓRZ JUPYTERLAB, aby ją otworzyć.

5. Pisanie kodu trenowania

Krok 1. Utwórz zasobnik w Cloud Storage

Model i artefakty wstępnego przetwarzania będą przechowywane w zasośniku Cloud Storage. Jeśli w projekcie masz już zasobnik, którego chcesz użyć, możesz pominąć ten krok.

W uruchomionym programie uruchomiania otwórz nową sesję terminala.

Open_terminal

W terminalu uruchom to polecenie, aby zdefiniować zmienną środowiskową dla projektu. Pamiętaj, aby zastąpić your-cloud-project identyfikatorem projektu:

PROJECT_ID='your-cloud-project'

Następnie uruchom w terminalu to polecenie, aby utworzyć nowy zasobnik w projekcie.

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

Krok 2. Wytrenuj model

W terminalu utwórz nowy katalog o nazwie cpr-codelab i umieść w nim dysk cd.

mkdir cpr-codelab
cd cpr-codelab

W przeglądarce plików przejdź do nowego katalogu cpr-codelab, a następnie za pomocą programu uruchamiającego utwórz nowy notatnik Pythona 3 o nazwie task.ipynb.

file_browser

Katalog cpr-codelab powinien teraz wyglądać tak:

+ cpr-codelab/
    + task.ipynb

W notatniku wklej ten kod.

Najpierw utwórz plik 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

Wdrożony model będzie mieć inny zestaw wstępnie zainstalowanych zależności niż środowisko notebooka. Dlatego w pliku requirements.txt podaj wszystkie zależności modelu, a potem użyj pip, aby zainstalować te same zależności w notebooku. Następnie, przed wdrożeniem modelu w Vertex AI, przetestujesz go lokalnie, aby sprawdzić, czy środowiska są zgodne.

Za pomocą narzędzia Pip zainstaluj zależności w notatniku.

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

Pamiętaj, że po zakończeniu instalacji pip musisz ponownie uruchomić jądro.

restart_kernel

Następnie utwórz katalogi, w których będziesz przechowywać artefakty modelu i artefaktów wstępnego przetwarzania.

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

Twój katalog cpr-codelab powinien teraz wyglądać tak:

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

Teraz, gdy struktura katalogów jest już skonfigurowana, możesz wytrenować model.

Najpierw zaimportuj biblioteki.

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)

Następnie zdefiniuj poniższe zmienne. Pamiętaj, aby zastąpić PROJECT_ID identyfikatorem projektu, a BUCKET_NAME zasobnikiem utworzonym w poprzednim kroku.

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}"

Wczytaj dane z biblioteki seaborn, a potem utwórz 2 ramki danych: jedną z cechami, a drugą z oznaczeniem.

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

label = 'price'

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

Spójrzmy na dane treningowe. Jak widać, każdy wiersz odpowiada jednemu diamentowi.

x_train.head()

I etykiety, które są odpowiednimi cenami.

y_train.head()

Teraz zdefiniuj w sklearn transformację kolumny, aby zastosować kodowanie 1-hot do cech kategorialnych i przekształcić cechy liczbowe.

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

Zdefiniuj losowy model lasu

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

Następnie utwórz potok sklearn. Oznacza to, że dane przesyłane do tego potoku zostaną najpierw zakodowane/skalowane, a następnie przekazane do modelu.

my_pipeline = make_pipeline(column_transform, regr)

Dopasuj potok do danych treningowych

my_pipeline.fit(x_train, y_train)

Wypróbujmy model, aby się upewnić, że działa zgodnie z oczekiwaniami. Wywołaj metodę predict w modelu, przekazując próbkę testową.

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

Teraz możemy zapisać potok w katalogu model_artifacts i skopiować go do zasobnika Cloud Storage.

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

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

Krok 3. Zapisz artefakt wstępnej obróbki

Następnie utwórz artefakt wstępnej obróbki. Ten artefakt zostanie załadowany do kontenera niestandardowego po uruchomieniu serwera modelu. Artefakt wstępnego przetwarzania może mieć niemal dowolną postać (np. plik z piklem), ale w takim przypadku musisz zapisać słownik do pliku JSON.

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

W danych treningowych funkcja clarity była zawsze w skrócie (np. „FL” zamiast „Flawless”). W momencie wyświetlania chcemy sprawdzić, czy dane dotyczące tej funkcji są również skrócone. Wynika to z faktu, że nasz model wie, jak zakodować jeden kod „FL”, ale nie „Flawless”. Później napiszesz ten niestandardowy mechanizm wstępnego przetwarzania danych. Na razie zapisz tabelę wyszukiwania w pliku json, a potem zapisz go w zasobniku 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}/

Twój lokalny katalog cpr-codelab powinien teraz wyglądać tak:

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

6. Tworzenie niestandardowego kontenera do obsługi za pomocą serwera modelu CPR

Po wytrenowaniu modelu i zapisaniu artefaktu wstępnego przetwarzania możesz utworzyć niestandardowy kontener do obsługi. Zwykle tworzenie kontenera do obsługi wymaga napisania kodu serwera modelu. Jednak w przypadku niestandardowych rutyn prognozowania Vertex AI Predictions generuje serwer modelu i tworzy dla Ciebie niestandardowy obraz kontenera.

Kontener do obsługi niestandardowej zawiera 3 elementy kodu:

  1. Serwer modelu (zostanie wygenerowany automatycznie przez pakiet SDK i przechowywany w: scr_dir/)
    • serwer HTTP, który hostuje model;
    • Odpowiada za konfigurowanie tras, portów itp.
  2. Obsługa żądania
    • Odpowiedzialny za aspekty obsługi żądania związane z serwerem WWW, takie jak deserializacja treści żądania i serializacja odpowiedzi, ustawianie nagłówków odpowiedzi itp.
    • W tym przykładzie użyjesz domyślnego modułu obsługi google.cloud.aiplatform.prediction.handler.PredictionHandler, który jest dostępny w SDK.
  3. Prognozowanie
    • Odpowiedzialny za logikę ML do przetwarzania żądania prognozy.

Każdy z tych komponentów można dostosować do wymagań związanych z przypadkiem użycia. W tym przykładzie wdrożysz tylko prognozowanie.

Model prognozowania odpowiada za logikę ML służącą do przetwarzania żądania prognozy, np. niestandardowe wstępne i postępne przetwarzanie. Aby napisać niestandardową logikę prognozowania, podklasyfikujesz interfejs Vertex AI Predictor.

Ta wersja niestandardowych procedur prognozowania zawiera predykatory wielokrotnego użytku XGBoost i Sklearn, ale jeśli chcesz użyć innej platformy, możesz utworzyć własną, podklasyfikując podstawowe prognozowanie.

Poniżej znajdziesz przykład przewidywacza Sklearn. Oto cały kod, który musisz napisać, aby utworzyć niestandardowy serwer modeli.

sklearn_predictor

W notatniku wklej podany niżej kod, aby utworzyć podklasę SklearnPredictor i zapisz ją w pliku Pythona w folderze src_dir/. Pamiętaj, że w tym przykładzie dostosowujemy tylko metody load, preprocesspostprocess, a nie metodę 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)]}

Przyjrzyjmy się bliżej każdej z tych metod.

  • Metoda load wczytuje artefakt wstępnego przetwarzania, który w tym przypadku jest słownikiem mapującym wartości szlifowania diamentów na ich skróty.
  • metoda preprocess używa tego artefaktu, aby zapewnić, że w momencie wyświetlania funkcja Clarity będzie w skróconym formacie. W przeciwnym razie przekształca cały ciąg na jego skrót.
  • metoda postprocess zwraca przewidywaną wartość w postaci ciągu znaków ze znakiem $ i zaokrągla wartość.

Następnie utwórz obraz za pomocą pakietu SDK Vertex AI Python. Za pomocą niestandardowych rutyn prognostycznych zostanie wygenerowany plik Dockerfile i utworzony obraz.

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"),
)

Napisz plik testowy z 2 przykładami do wykorzystania w prognozie. Jedno z wystąpienia ma skróconą nazwę, a drugie musi zostać najpierw przekonwertowane.

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)

przetestować kontener lokalnie, wdrażając lokalny model;

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()

Wyniki prognozy możesz sprawdzić:

predict_response.content

7. Wdrażanie modelu w Vertex AI

Po lokalnym przetestowaniu kontenera musisz przenieść obraz do Artifact Registry i przesłać model do Vertex AI Model Registry.

Najpierw skonfiguruj Dockera, aby uzyskać dostęp do 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

Następnie przeciągnij obraz.

local_model.push_image()

Prześlij model.

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

Po przesłaniu modelu powinien być widoczny w konsoli:

model_registry

Następnie wdróż model, aby móc go używać do prognoz online. Niestandardowe procedury prognozowania działają też w przypadku prognozowania zbiorczego, więc jeśli Twoje zastosowanie nie wymaga prognozowania online, nie musisz wdrażać modelu.

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

Na koniec przetestuj wdrożony model, uzyskując prognozę.

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

🎉 Gratulacje! 🎉

Poznałeś/poznałaś już te sposoby korzystania z Vertex AI:

  • Napisz niestandardową logikę wstępnego i potwierdzenia za pomocą niestandardowych procedur prognozowania

Więcej informacji o różnych elementach Vertex AI znajdziesz w dokumentacji.

8. Czyszczenie

Jeśli chcesz nadal korzystać z notatnika utworzonego w tym laboratorium, zalecamy jego wyłączenie, gdy go nie używasz. W interfejsie Workbench w konsoli Google Cloud wybierz notebook, a następnie Zatrzymaj.

Aby całkowicie usunąć notatnik, kliknij przycisk Usuń w prawym górnym rogu.

Stop_nb

Aby usunąć wdrożony punkt końcowy, otwórz w konsoli sekcję Punkty końcowe, kliknij utworzony punkt końcowy, a potem wybierz Wycofaj wdrożenie modelu z punktu końcowego:

delete_endpoint

Aby usunąć obraz kontenera, otwórz Artifact Registry, wybierz utworzone repozytorium i kliknij Usuń.

delete_image

Aby usunąć zasobnik Cloud Storage, w menu nawigacyjnym konsoli Cloud wybierz Storage, a następnie zasobnik i kliknij Usuń:

Usuwanie miejsca na dane