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。
3. 用途總覽
在本研究室中,您將建構隨機森林迴歸模型,根據切割、清晰度和尺寸等屬性預測鑽石的價格。
您將編寫自訂的預先處理邏輯,檢查提供時的資料是否採用模型預期的格式。您也會編寫自訂後處理邏輯,將預測結果四捨五入並轉換為字串。如要編寫這個邏輯,您將使用自訂預測處理常式。
自訂預測處理常式簡介
Vertex AI 預先建構的容器會執行機器學習架構的預測作業,以處理預測要求。在自訂預測處理常式之前,如果想在執行預測之前預先處理輸入內容,或是將模型的預測結果後置再傳回結果,就必須建構自訂容器。
如要建立自訂服務容器,您必須編寫 HTTP 伺服器來納入經過訓練的模型,並將 HTTP 要求轉譯為模型輸入內容,並將模型輸出內容轉譯為回應。
透過自訂預測處理常式,Vertex AI 會提供服務相關元件,讓您專心處理模型和資料轉換。
建構項目
您要設定一個名為 Thl-vpc 的虛擬私有雲網路,其中包含用於部署使用者代管筆記本的工作台子網路,以及存取部署於 us-central1 中的線上預測和模型端點,如圖 1 所示。
Figure1
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 執行個體
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 值區。如果專案中已有要使用的值區,您可以略過這個步驟。
從啟動器開啟新的終端機工作階段。
在終端機執行下列指令,定義專案的環境變數,請務必以專案的 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。
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 段程式碼:
- 模型伺服器 (由 SDK 自動產生,並儲存在 scr_dir/)
- 託管模型的 HTTP 伺服器
- 負責設定路線/通訊埠等
- 負責處理要求的網路伺服器層面,例如將要求主體還原序列化,以及將存放區序列化、設定回應標頭等。
- 在這個範例中,您將使用 SDK 提供的預設 Handler google.cloud.aiplatform.Predict.handler.PredictionHandler。
- 負責處理預測要求的機器學習邏輯。
每個元件都可以根據用途需求自訂。本例中,您只需要實作預測器。
預測者負責處理預測要求 (例如自訂預先處理和後續處理) 的機器學習邏輯。如要編寫自訂預測邏輯,您必須將 Vertex AI 預測者介面設為子類別。
這個版本的自訂預測處理常式隨附可重複使用的 XGBoost 和 Sklearn 預測工具,但如果需要使用其他架構,則可將基礎預測工具分類,以建立自己的架構。
您可以在下方查看 Sklearn 預測工具的範例。這是您為建構此自訂模型伺服器所需要撰寫的所有程式碼。
在筆記本中,貼上下列程式碼,將 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 認為程式碼研究室真的很棒!