1. 總覽
在本實驗室中,您將瞭解如何在 Vertex AI 上使用自訂預測處理常式,編寫自訂預先處理和後續處理邏輯。雖然本範例使用 Scikit-learn,但自訂預測處理常式可搭配其他 Python ML 架構使用,例如 XGBoost、PyTorch 和 TensorFlow。
課程內容
學習重點:
- 使用自訂預測處理常式編寫自訂預測邏輯
- 在本機測試自訂供應容器和模型
- 在 Vertex AI 預測上測試自訂服務容器
在 Google Cloud 上執行本實驗室的總費用約為 $1 美元。
2. Vertex AI 簡介
這個實驗室使用 Google Cloud 最新推出的 AI 產品服務。Vertex AI 整合了 Google Cloud 中的機器學習產品,提供流暢的開發體驗。先前使用 AutoML 訓練的模型和自訂模型,都能透過不同的服務存取。新產品將這兩項功能與其他新產品整合至單一 API。您也可以將現有專案遷移至 Vertex AI。
Vertex AI 包含許多不同產品,可支援端對端機器學習工作流程。本實驗室將著重於預測和工作台。
3. 用途簡介
用途
在本研究室中,您將建構隨機森林迴歸模型,根據切割、清晰度和尺寸等屬性預測鑽石的價格。
您將編寫自訂的預先處理邏輯,檢查提供時的資料是否採用模型預期的格式。此外,您也需要編寫自訂後處理邏輯,將預測結果四捨五入並轉換為字串。如要編寫這項邏輯,您將使用自訂預測處理常式。
自訂預測處理常式簡介
Vertex AI 預先建構的容器會執行機器學習架構的預測作業,以處理預測要求。在自訂預測處理常式之前,如果您想在執行預測前預先處理輸入內容,或是在傳回結果前對模型的預測結果進行後處理,就必須建構自訂容器。
如要建構自訂服務容器,您必須編寫 HTTP 伺服器,用於包裝已訓練的模型、將 HTTP 要求轉換為模型輸入內容,以及將模型輸出內容轉換為回應。
Vertex AI 會透過自訂預測例行程序提供服務相關元件,讓您專注於模型和資料轉換作業。
4. 設定環境
您必須擁有啟用計費功能的 Google Cloud Platform 專案,才能執行這個程式碼研究室。如要建立專案,請按照這篇文章中的操作說明進行。
步驟 1:啟用 Compute Engine API
前往「Compute Engine」,然後選取「啟用」 (如果尚未啟用)。您需要這項資訊才能建立 Notebook 執行個體。
步驟 2:啟用 Artifact Registry API
前往「Artifact Registry」,然後選取「Enable」(如果尚未啟用)。您將使用這組憑證建立自訂供應容器。
步驟 3:啟用 Vertex AI API
前往 Cloud 控制台的 Vertex AI 專區,然後按一下「啟用 Vertex AI API」。
步驟 4:建立 Vertex AI Workbench 執行個體
在 Cloud 控制台的 Vertex AI 專區中,按一下「Workbench」:
如果尚未啟用 Notebooks API,請先啟用。
啟用後,請按一下「執行個體」,然後選取「建立新執行個體」。
接受預設選項,然後點選「建立」。
執行個體準備就緒後,按一下「OPEN JUPYTERLAB」開啟執行個體。
5. 編寫訓練程式碼
步驟 1:建立 Cloud Storage 值區
您可以將模型和預先處理構件儲存至 Cloud Storage 值區。如果專案中已有要使用的桶,您可以略過這個步驟。
在啟動器中開啟新的終端機工作階段。
在終端機中執行以下指令,為專案定義 env 變數,請務必將 your-cloud-project
替換為專案的 ID:
PROJECT_ID='your-cloud-project'
接著,請在終端機中執行下列指令,在專案中建立新的值區。
BUCKET="gs://${PROJECT_ID}-cpr-bucket"
gsutil mb -l us-central1 $BUCKET
步驟 2:訓練模型
在終端機中建立名為 cpr-codelab
的新目錄,然後切換至該目錄。
mkdir cpr-codelab
cd cpr-codelab
在檔案瀏覽器中前往新的 cpr-codelab
目錄,然後使用啟動器建立名為 task.ipynb
的新 Python 3 筆記本。
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 在筆記本中安裝完全相同的依附元件。稍後,您會在本機測試模型,再部署至 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}"
從 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:儲存預先處理構件
接下來,您將建立預先處理構件。模型伺服器啟動時,系統會在自訂容器中載入這個構件。預先處理構件幾乎可以是任何形式 (例如 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」而非「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
6. 使用 CPR 模型伺服器建立自訂供應容器
現在模型已完成訓練,並儲存了預先處理構件,接著要建構自訂提供容器。一般來說,建構服務容器需要撰寫模型伺服器程式碼。不過,透過自訂預測處理常式,Vertex AI 預測會產生模型伺服器,並為您建構自訂容器映像檔。
自訂放送容器包含下列 3 個程式碼:
- 模型伺服器 (SDK 會自動產生並儲存在
scr_dir/
中)- 託管模型的 HTTP 伺服器
- 負責設定路徑/連接埠等。
- 要求處理常式
- 負責處理要求的網路伺服器層面,例如將要求主體還原序列化,以及將存放區序列化、設定回應標頭等。
- 在本例中,您將使用 SDK 提供的預設 Handler
google.cloud.aiplatform.prediction.handler.PredictionHandler
。
- 預測器
- 負責處理預測要求的機器學習邏輯。
您可以根據用途需求自訂每個元件。在這個範例中,您只會實作預測器。
預測器負責處理預測要求的機器學習邏輯,例如自訂預先處理和後續處理。如要編寫自訂預測邏輯,您必須將 Vertex AI 預測者介面設為子類別。
這個版本的自訂預測處理常式隨附可重複使用的 XGBoost 和 Sklearn 預測工具,但如果需要使用其他架構,則可將基礎預測工具分類,以建立自己的架構。
您可以在下方查看 Sklearn 預測工具的範例。這是您為了建構這個自訂模型伺服器而需要編寫的所有程式碼。
在筆記本中貼上下列程式碼,以便將 SklearnPredictor
設為子類別,並將其寫入 src_dir/
中的 Python 檔案。請注意,本例只是自訂 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)]}
讓我們進一步瞭解這些方法。
load
方法會載入預處理構件,在本例中為字典,用於將鑽石清晰度值對應至其縮寫。preprocess
方法會使用該構件,確保在放送時,clarity 功能會以簡略格式顯示。如果不是,則會將完整字串轉換為縮寫。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}",)
模型上傳完畢後,應該會在控制台中顯示:
接下來,您可以部署模型,以便進行線上預測。自訂預測處理常式也適用於批次預測,因此如果用途不需要線上預測,您就不需要部署模型。
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. 清除
如果想繼續使用您在這個研究室中建立的筆記本,建議在不使用時將其關閉。在 Google Cloud 控制台的 Workbench UI 中,選取 Notebook,然後選取「Stop」。
如要刪除整個筆記本,請按一下右上方的「刪除」按鈕。
如要刪除已部署的端點,請前往控制台的「端點」部分,按一下您建立的端點,然後選取「從端點取消部署模型」:
如要刪除容器映像檔,請前往 Artifact Registry,選取您建立的存放區,然後選取「Delete」
如要刪除儲存體值區,請使用 Cloud 控制台的「導覽」選單,前往「儲存體」並選取所需值區,然後按一下「刪除」: