Vertex AI:搭配 Sklearn 使用自訂預測處理常式,預先處理及後續處理資料以執行預測

1. 簡介

在本研究室中,您將瞭解如何在 Vertex AI 中使用自訂預測處理常式,編寫自訂預先處理和後續處理邏輯。雖然這個範例使用 Scikit-learn,但自訂預測處理常式也能與其他 Python 機器學習架構 (例如 XGBoost、PyTorch 和 TensorFlow) 搭配使用。

課程內容

  • 使用自訂預測處理常式編寫自訂預測邏輯
  • 在本機測試自訂供應容器和模型
  • 在 Vertex AI 預測中測試自訂供應容器

2. Vertex AI 簡介

這個研究室使用 Google Cloud 最新的 AI 產品服務。Vertex AI 將 Google Cloud 中的機器學習產品整合到流暢的開發體驗中。先前使用 AutoML 訓練的模型和自訂模型,都能透過不同的服務存取。這項新產品會與其他新產品一起合併為一個 API。您也可以將現有專案遷移至 Vertex AI。

Vertex AI 提供許多不同的產品,可支援端對端機器學習工作流程。本研究室將著重介紹預測和 Workbench。

440e66b5fde4cee7.png

3. 用途總覽

在本研究室中,您將建構隨機森林迴歸模型,根據切割、清晰度和尺寸等屬性預測鑽石的價格。

您將編寫自訂的預先處理邏輯,檢查提供時的資料是否採用模型預期的格式。您也會編寫自訂後處理邏輯,將預測結果四捨五入並轉換為字串。如要編寫這個邏輯,您將使用自訂預測處理常式。

自訂預測處理常式簡介

Vertex AI 預先建構的容器會執行機器學習架構的預測作業,以處理預測要求。在自訂預測處理常式之前,如果想在執行預測之前預先處理輸入內容,或是將模型的預測結果後置再傳回結果,就必須建構自訂容器。

如要建立自訂服務容器,您必須編寫 HTTP 伺服器來納入經過訓練的模型,並將 HTTP 要求轉譯為模型輸入內容,並將模型輸出內容轉譯為回應。

透過自訂預測處理常式,Vertex AI 會提供服務相關元件,讓您專心處理模型和資料轉換。

建構項目

您要設定一個名為 Thl-vpc 的虛擬私有雲網路,其中包含用於部署使用者代管筆記本的工作台子網路,以及存取部署於 us-central1 中的線上預測和模型端點,如圖 1 所示。

                                                                            Figure1

6ce21c7fdae12b4f.png

4. 啟用教學課程 API

步驟 1:啟用 Compute Engine API

前往「Compute Engine」,並選取「啟用」(如果尚未啟用)。建立筆記本執行個體時會用到。

步驟 2:啟用 Artifact Registry API

前往「Artifact Registry」並選取「啟用」(如果尚未啟用)。您將使用這組憑證建立自訂供應容器。

步驟 3:啟用 Vertex AI API

前往 Cloud 控制台的 Vertex AI 專區,然後按一下「啟用 Vertex AI API」。

步驟 4:建立 Vertex AI Workbench 執行個體

啟用「Notebooks API」(如果尚未啟用)。

5. 建立 Targetl-vpc

本教學課程將使用 $variables,協助在 Cloud Shell 中實作 gcloud 設定。

在 Cloud Shell 中執行以下操作:

gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectid=YOUR-PROJECT-NAME
echo $projectid

建立 preparel-vpc

在 Cloud Shell 中執行以下操作:

gcloud compute networks create aiml-vpc --project=$projectid --subnet-mode=custom

建立使用者自行管理的筆記本子網路

在 Cloud Shell 中建立 Workbench-subnet。

gcloud compute networks subnets create workbench-subnet --project=$projectid --range=172.16.10.0/28 --network=aiml-vpc --region=us-central1 --enable-private-ip-google-access

Cloud Router 和 NAT 設定

使用者管理的筆記本沒有外部 IP 位址,因此本教學課程會使用 Cloud NAT 下載軟體套件。Cloud NAT 提供輸出 NAT 功能,因此網際網路主機無法與使用者自行管理的筆記本展開通訊,因此更加安全。

在 Cloud Shell 中,建立區域性 Cloud Router us-central1,

gcloud compute routers create cloud-router-us-central1-aiml-nat --network aiml-vpc --region us-central1

在 Cloud Shell 中建立區域雲端 Nat 閘道 us-central1。

gcloud compute routers nats create cloud-nat-us-central1 --router=cloud-router-us-central1-aiml-nat --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges --region us-central1

6. 建立由使用者自行管理的筆記本

建立使用者自行管理的服務帳戶 (筆記本)

在下一節中,您將建立使用者代管服務帳戶,並與教學課程中使用的 Vertex Workbench (筆記本) 建立關聯。

在本教學課程中,服務帳戶會套用下列規則:

在 Cloud Shell 中建立服務帳戶。

gcloud iam service-accounts create user-managed-notebook-sa \
    --display-name="user-managed-notebook-sa"

在 Cloud Shell 中,將服務帳戶更新為「Storage 管理員」角色。

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/storage.admin"

在 Cloud Shell 中,將服務帳戶更新為「Vertex AI 使用者」角色。

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/aiplatform.user"

在 Cloud Shell 中,將服務帳戶更新為 Artifact Registry 管理員角色。

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/artifactregistry.admin"

在 Cloud Shell 中列出服務帳戶,並記下建立使用者自行管理筆記本時要使用的電子郵件地址。

gcloud iam service-accounts list

建立使用者自行管理的筆記本

在下一節中,建立由使用者自行管理的筆記本,並在其中加入先前建立的服務帳戶,也就是使用者自行管理的 notebook-sa。

在 Cloud Shell 中建立一個私人用戶端執行個體。

gcloud notebooks instances create workbench-tutorial \
      --vm-image-project=deeplearning-platform-release \
      --vm-image-family=common-cpu-notebooks \
      --machine-type=n1-standard-4 \
      --location=us-central1-a \
      --shielded-secure-boot \
      --subnet-region=us-central1 \
      --subnet=workbench-subnet \
      --no-public-ip    --service-account=user-managed-notebook-sa@$projectid.iam.gserviceaccount.com

7. 編寫訓練程式碼

步驟 1:建立 Cloud Storage 值區

您可以將模型和預先處理構件儲存至 Cloud Storage 值區。如果專案中已有要使用的值區,您可以略過這個步驟。

從啟動器開啟新的終端機工作階段。

84a53a5b528f2507.png

在終端機執行下列指令,定義專案的環境變數,請務必以專案的 ID 取代 your-cloud-project:

PROJECT_ID='your-cloud-project'

接著,在終端機中執行下列指令,在專案中建立新值區。

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。

f230930e0b79650c.png

cpr-codelab 目錄現在應如下所示:

+ cpr-codelab/
    + task.ipynb

在筆記本中,貼上下列程式碼。

首先,編寫 requirements.txt 檔案。

%%writefile requirements.txt
fastapi
uvicorn==0.17.6
joblib~=1.1.1
numpy>=1.17.3, <1.24.0
scikit-learn~=1.0.0
pandas
google-cloud-storage>=2.2.1,<3.0.0dev
google-cloud-aiplatform[prediction]>=1.18.2

您部署的模型已預先安裝與筆記本環境不同的依附元件組合。因此,建議您在 requirements.txt 中列出模型的所有依附元件,然後使用 pip 在筆記本中安裝完全相同的依附元件。之後,您會在部署至 Vertex AI 之前先在本機測試模型,確認環境是否相符。

Pip 會在筆記本中安裝依附元件。

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

請注意,在 pip 安裝完成後,您需要重新啟動核心。

接著,建立用於儲存模型和預先處理構件的目錄。

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 替換為您的專案 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}"

從海洋生物程式庫載入資料,然後建立兩個資料框架,一個具有特徵,另一個則加上標籤。

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(sparse=False), [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)

讓我們試用模型,確保模型正常運作。對模型呼叫預測方法,傳入測試範例。

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:儲存預先處理構件

接下來,您需要建立預先處理構件。模型伺服器啟動時,這個構件會在自訂容器中載入。預先處理構件可以是任何形式 (例如 Pickle 檔案),但在這種情況下,您必須將字典寫成 JSON 檔案。

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

訓練資料中的清晰特徵一律採用縮寫形式 (即「FL」而非「Flawless」)。提供服務時,我們想要檢查這項功能的資料是否也縮寫。這是因為我們的模型知道如何將熱編碼為「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

8. 使用 CPR 模型伺服器建立自訂供應容器

現在模型已完成訓練,並儲存了預先處理構件,接著要建構自訂提供容器。一般而言,建構供應容器需要編寫模型伺服器程式碼。不過,透過自訂預測處理常式,Vertex AI 預測會產生模型伺服器,並為您建構自訂容器映像檔。

自訂供應容器包含下列 3 段程式碼:

  1. 模型伺服器 (由 SDK 自動產生,並儲存在 scr_dir/)
  • 託管模型的 HTTP 伺服器
  • 負責設定路線/通訊埠等
  1. 要求處理常式
  • 負責處理要求的網路伺服器層面,例如將要求主體還原序列化,以及將存放區序列化、設定回應標頭等。
  • 在這個範例中,您將使用 SDK 提供的預設 Handler google.cloud.aiplatform.Predict.handler.PredictionHandler。
  1. 預測者
  • 負責處理預測要求的機器學習邏輯。

每個元件都可以根據用途需求自訂。本例中,您只需要實作預測器。

預測者負責處理預測要求 (例如自訂預先處理和後續處理) 的機器學習邏輯。如要編寫自訂預測邏輯,您必須將 Vertex AI 預測者介面設為子類別

這個版本的自訂預測處理常式隨附可重複使用的 XGBoost 和 Sklearn 預測工具,但如果需要使用其他架構,則可將基礎預測工具分類,以建立自己的架構。

您可以在下方查看 Sklearn 預測工具的範例。這是您為建構此自訂模型伺服器所需要撰寫的所有程式碼。

262df1246b28657e.png

在筆記本中,貼上下列程式碼,將 SklearnPredictor 設為子類別,並寫入 src_dir/ 中的 Python 檔案。請注意,本例只是自訂載入、預先處理和後置程序方法,而非預測方法。

%%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)]}

讓我們進一步瞭解這些方法。

  • 載入方法會在預先處理成果中載入,在本例中是將鑽石清晰值對應至縮寫的字典。
  • 預先處理方法會使用該構件,確保明確功能可在提供時採用縮寫格式。如果沒有,則會將整個字串轉換為縮寫。
  • 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

9. 將模型部署至 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}",)

模型上傳完畢後,應該會在控制台中顯示:

接下來,請部署模型,以便用於線上預測。自訂預測處理常式也適用於批次預測,因此如果用途不需要線上預測,就不必部署模型。

然後推送映像檔。

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 執行下列作業:

  • 使用自訂預測處理常式編寫自訂預先處理和後續處理邏輯

Cosmopup 認為程式碼研究室真的很棒!

e6d3675ca7c6911f.jpeg

後續步驟

其他資訊與影片

參考文件