使用 Vertex AI 建構及部署模型

1. 總覽

在本研究室中,您將瞭解如何使用 Google Cloud 新宣布的代管機器學習平台 Vertex AI,建構端對端機器學習工作流程。您將瞭解如何從原始資料轉移至已部署的模型,還能在這個研討會中完成使用 Vertex AI,以便開發及推出自己的機器學習專案。在本研究室中,我們會使用 Cloud Shell 建立自訂 Docker 映像檔,示範透過 Vertex AI 進行訓練的自訂容器。

當這裡使用 TensorFlow 編寫模型程式碼時,你可以輕鬆將其替換為其他架構。

課程內容

學習重點:

  • 使用 Cloud Shell 建構及容器化模型訓練程式碼
  • 將自訂模型訓練工作提交至 Vertex AI
  • 將訓練過的模型部署至端點,並透過該端點取得預測結果

在 Google Cloud 中執行這個研究室的總費用約為 $2 美元。

2. Vertex AI 簡介

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

如下圖所示,Vertex 提供多種工具,可協助您完成機器學習工作流程的每個階段。下文將著重說明如何運用 Vertex 訓練預測

Vertex 服務

3. 設定環境

自修環境設定

登入 Cloud 控制台建立新專案,或是重複使用現有專案。(如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶)。

提醒您,專案 ID 是所有 Google Cloud 專案的專屬名稱 (已經有人使用上述名稱,很抱歉對您不符!)。

接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Google Cloud 資源。

執行這個程式碼研究室並不會產生任何費用,如果有的話。請務必依照「清除所用資源」一節指示本節將說明如何關閉資源,這樣您就不會產生本教學課程結束後產生的費用。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

步驟 1:啟動 Cloud Shell

在本研究室中,您將會透過 Cloud Shell 工作階段執行,也就是由在 Google 雲端環境中運作的虛擬機器託管的指令解譯器。您可以和在自己的電腦本機輕鬆執行這個部分,但只要使用 Cloud Shell,就能在一致的環境中提供可重現的體驗。完成研究室後,您可以使用自己的電腦再試一次。

授權 Cloud Shell

啟用 Cloud Shell

在 Cloud 控制台的右上方,按一下下列按鈕來「啟用 Cloud Shell」

啟用 Cloud Shell

如果您先前從未啟動 Cloud Shell,您會看見中繼畫面 (需捲動位置),說明螢幕內容。如果出現這種情況,請按一下「繼續」 (之後不會再顯示)。以下是單次畫面的外觀:

Cloud Shell 設定

佈建並連線至 Cloud Shell 只需幾分鐘的時間。

Cloud Shell 啟動

這個虛擬機器搭載您需要的所有開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。在本程式碼研究室中,您的大部分作業都可以透過瀏覽器或 Chromebook 完成。

連線至 Cloud Shell 後,您應會發現自己通過驗證,且專案已設為您的專案 ID。

在 Cloud Shell 中執行下列指令,確認您已通過驗證:

gcloud auth list

指令輸出

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

在 Cloud Shell 中執行下列指令,確認 gcloud 指令知道您的專案:

gcloud config list project

指令輸出

[core]
project = <PROJECT_ID>

如果尚未設定,請使用下列指令進行設定:

gcloud config set project <PROJECT_ID>

指令輸出

Updated property [core/project].

Cloud Shell 有數個環境變數,包括 GOOGLE_CLOUD_PROJECT,其中含有目前 Cloud 專案名稱。我們會在本研究室的各個不同地方使用這些內容。您可以執行以下指令來查看:

echo $GOOGLE_CLOUD_PROJECT

步驟 2:啟用 API

在後續步驟中,您會看到需要這些服務的位置和原因。目前請先執行下列指令,為專案授予 Compute Engine、Container Registry 和 Vertex AI 服務的存取權:

gcloud services enable compute.googleapis.com         \
                       containerregistry.googleapis.com  \
                       aiplatform.googleapis.com

這應該會產生類似下列內容的成功訊息:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

步驟 3:建立 Cloud Storage 值區

如要在 Vertex AI 執行訓練工作,我們需要一個儲存儲存的模型資產的儲存空間值區。在 Cloud Shell 終端機中執行下列指令來建立值區:

BUCKET_NAME=gs://$GOOGLE_CLOUD_PROJECT-bucket
gsutil mb -l us-central1 $BUCKET_NAME

步驟 4:別名 Python 3

本研究室的程式碼使用 Python 3。為確保執行將在本研究室中建立的指令碼時使用的是 Python 3,請在 Cloud Shell 中執行下列指令來建立別名:

alias python=python3

本研究室將訓練及提供的模型是依據 TensorFlow 說明文件的本教學課程建構而成。本教學課程使用 Kaggle 的 Auto MPG 資料集來預測車輛的燃油效率。

4. 將訓練程式碼容器化

我們會將這項訓練工作提交至 Vertex,方法是將訓練程式碼放入 Docker 容器,並推送至 Google Container Registry。透過這種做法,我們可以訓練以任何架構建構的模型。

步驟 1:設定檔案

首先,請在 Cloud Shell 中的終端機執行下列指令,建立 Docker 容器需要的檔案:

mkdir mpg
cd mpg
touch Dockerfile
mkdir trainer
touch trainer/train.py

您現在應該會擁有 mpg/ 目錄,如下所示:

+ Dockerfile
+ trainer/
    + train.py

如要查看及編輯這些檔案,請使用 Cloud Shell 內建的程式碼編輯器。只要按一下 Cloud Shell 右上方的選單列上的按鈕,即可在編輯器與終端機之間切換:

切換至 Cloud Shell 中的編輯器

步驟 2:建立 Dockerfile

為了將程式碼容器化,我們首先建立 Dockerfile。並在 Dockerfile 中加入執行映像檔所需的所有指令。此工具會安裝目前使用的所有程式庫,並設定訓練程式碼的進入點。

在 Cloud Shell 檔案編輯器中開啟 mpg/ 目錄,然後按兩下即可開啟 Dockerfile:

開啟 Dockerfile

接著將下列內容複製到這個檔案中:

FROM gcr.io/deeplearning-platform-release/tf2-cpu.2-3
WORKDIR /

# Copies the trainer code to the docker image.
COPY trainer /trainer

# Sets up the entry point to invoke the trainer.
ENTRYPOINT ["python", "-m", "trainer.train"]

這個 Dockerfile 使用深度學習容器 TensorFlow 企業版 2.3 Docker 映像檔。Google Cloud 中的深度學習容器已預先安裝許多常見的機器學習和數據資料學架構。我們使用的是 TF Enterprise 2.3、Pandas、Scikit-learn 等項目。下載該映像檔後,這個 Dockerfile 會設定訓練程式碼的進入點,我們將在下一個步驟中新增這個點。

步驟 3:新增模型訓練程式碼

接著在 Cloud Shell 編輯器中開啟 train.py 檔案,並複製下列程式碼 (改寫在 TensorFlow 文件中的教學課程)。

# This will be replaced with your bucket name after running the `sed` command in the tutorial
BUCKET = "BUCKET_NAME"

import numpy as np
import pandas as pd
import pathlib
import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers

print(tf.__version__)

"""## The Auto MPG dataset

The dataset is available from the [UCI Machine Learning Repository](https://archive.ics.uci.edu/ml/).

### Get the data
First download the dataset.
"""

"""Import it using pandas"""

dataset_path = "https://storage.googleapis.com/io-vertex-codelab/auto-mpg.csv"
dataset = pd.read_csv(dataset_path, na_values = "?")

dataset.tail()

"""### Clean the data

The dataset contains a few unknown values.
"""

dataset.isna().sum()

"""To keep this initial tutorial simple drop those rows."""

dataset = dataset.dropna()

"""The `"origin"` column is really categorical, not numeric. So convert that to a one-hot:"""

dataset['origin'] = dataset['origin'].map({1: 'USA', 2: 'Europe', 3: 'Japan'})

dataset = pd.get_dummies(dataset, prefix='', prefix_sep='')
dataset.tail()

"""### Split the data into train and test

Now split the dataset into a training set and a test set.

We will use the test set in the final evaluation of our model.
"""

train_dataset = dataset.sample(frac=0.8,random_state=0)
test_dataset = dataset.drop(train_dataset.index)

"""### Inspect the data

Have a quick look at the joint distribution of a few pairs of columns from the training set.

Also look at the overall statistics:
"""

train_stats = train_dataset.describe()
train_stats.pop("mpg")
train_stats = train_stats.transpose()
train_stats

"""### Split features from labels

Separate the target value, or "label", from the features. This label is the value that you will train the model to predict.
"""

train_labels = train_dataset.pop('mpg')
test_labels = test_dataset.pop('mpg')

"""### Normalize the data

Look again at the `train_stats` block above and note how different the ranges of each feature are.

It is good practice to normalize features that use different scales and ranges. Although the model *might* converge without feature normalization, it makes training more difficult, and it makes the resulting model dependent on the choice of units used in the input.

Note: Although we intentionally generate these statistics from only the training dataset, these statistics will also be used to normalize the test dataset. We need to do that to project the test dataset into the same distribution that the model has been trained on.
"""

def norm(x):
  return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset)
normed_test_data = norm(test_dataset)

"""This normalized data is what we will use to train the model.

Caution: The statistics used to normalize the inputs here (mean and standard deviation) need to be applied to any other data that is fed to the model, along with the one-hot encoding that we did earlier.  That includes the test set as well as live data when the model is used in production.

## The model

### Build the model

Let's build our model. Here, we'll use a `Sequential` model with two densely connected hidden layers, and an output layer that returns a single, continuous value. The model building steps are wrapped in a function, `build_model`, since we'll create a second model, later on.
"""

def build_model():
  model = keras.Sequential([
    layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),
    layers.Dense(64, activation='relu'),
    layers.Dense(1)
  ])

  optimizer = tf.keras.optimizers.RMSprop(0.001)

  model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])
  return model

model = build_model()

"""### Inspect the model

Use the `.summary` method to print a simple description of the model
"""

model.summary()

"""Now try out the model. Take a batch of `10` examples from the training data and call `model.predict` on it.

It seems to be working, and it produces a result of the expected shape and type.

### Train the model

Train the model for 1000 epochs, and record the training and validation accuracy in the `history` object.

Visualize the model's training progress using the stats stored in the `history` object.

This graph shows little improvement, or even degradation in the validation error after about 100 epochs. Let's update the `model.fit` call to automatically stop training when the validation score doesn't improve. We'll use an *EarlyStopping callback* that tests a training condition for  every epoch. If a set amount of epochs elapses without showing improvement, then automatically stop the training.

You can learn more about this callback [here](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/EarlyStopping).
"""

model = build_model()

EPOCHS = 1000

# The patience parameter is the amount of epochs to check for improvement
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)

early_history = model.fit(normed_train_data, train_labels, 
                    epochs=EPOCHS, validation_split = 0.2, 
                    callbacks=[early_stop])


# Export model and save to GCS
model.save(BUCKET + '/mpg/model')

將上述程式碼複製到 mpg/trainer/train.py 檔案後,請返回 Cloud Shell 中的終端機,然後執行下列指令,將自己的值區名稱新增至檔案:

sed -i "s|BUCKET_NAME|$BUCKET_NAME|g" trainer/train.py

步驟 4:在本機建構及測試容器

在終端機中執行下列指令,以便使用 Google Container Registry 中容器映像檔的 URI 定義變數:

IMAGE_URI="gcr.io/$GOOGLE_CLOUD_PROJECT/mpg:v1"

接著,從 mpg 目錄的根目錄執行下列指令,以建構容器:

docker build ./ -t $IMAGE_URI

容器建構完成後,請推送至 Google Container Registry:

docker push $IMAGE_URI

如要確認映像檔已推送至 Container Registry,當您前往控制台的 Container Registry 部分時,應會看見下列內容:

Container Registry 預先發布版

將容器推送至 Container Registry 後,我們現在可以開始執行自訂模型訓練工作。

5. 在 Vertex AI 中執行訓練工作

Vertex 提供兩種訓練模型的選項:

  • AutoML:只需要最基本的機器學習專業知識,就能輕鬆訓練出高品質模型。
  • 自訂訓練:使用 Google Cloud 其中一個預先建構的容器,或在雲端執行自訂訓練應用程式。

在本研究室中,我們會透過 Google Container Registry 上的自訂容器使用自訂訓練。首先,請前往 Cloud 控制台「Vertex」專區中的「訓練」部分:

Vertex 側欄選單 - 訓練

步驟 1:開始執行訓練工作

按一下「建立」,輸入訓練工作和已部署模型的參數:

  • 在「資料集」下方,選取「沒有代管資料集」
  • 接著選取「自訂訓練 (進階)」做為訓練方法,然後按一下「繼續」
  • 在「Model name」(模型名稱) 中輸入 mpg (或是您想要呼叫模型的任何字詞)
  • 按一下 [Continue] (繼續)

在「容器設定」步驟中,選取「自訂容器」

自訂容器選項

在第一個方塊中 (容器映像檔) 按一下「Browse」(瀏覽),找出您剛才推送至 Container Registry 的容器。如下所示:

尋找容器

將其餘欄位留白,並按一下「繼續」

本教學課程不會使用超參數調整,因此請將「啟用超參數調整」方塊保持未勾選的狀態,然後按一下 [繼續]

在「運算和定價」中,將所選區域保持不變,並選取「n1-standard-4」做為機器類型:

機器類型

這個範例中的模型訓練速度相當快,因此我們使用的是規模較小的機器類型。

在「Prediction container」(預測容器) 步驟下方,選取「No Prediction container」(沒有預測容器)

沒有任何預測容器

6. 部署模型端點

在這個步驟中,我們會為訓練過的模型建立端點。我們可以透過 Vertex AI API,透過模型取得模型預測結果。為了達成這個目標,我們已在公開 GCS 值區中提供匯出的訓練模型資產版本

一個機構通常會由一個團隊或個人負責建構模型,並由不同的團隊負責部署。在接下來的步驟,將說明如何從已訓練完成的模型中,部署模型以進行預測。

這裡會使用 Vertex AI SDK 建立模型、將模型部署至端點,以及取得預測結果。

步驟 1:安裝 Vertex SDK

在 Cloud Shell 終端機中執行下列指令,安裝 Vertex AI SDK:

pip3 install google-cloud-aiplatform --upgrade --user

我們可以使用這個 SDK 與 Vertex 的許多不同部分互動。

步驟 2:建立模型及部署端點

接下來,我們會建立 Python 檔案,並使用 SDK 建立模型資源,並部署至端點。在 Cloud Shell 的檔案編輯器中,依序選取「File」和「New File」

在 Cloud Shell 建立新檔案

命名檔案 deploy.py。請在編輯器中開啟此檔案,並複製下列程式碼:

from google.cloud import aiplatform

# Create a model resource from public model assets
model = aiplatform.Model.upload(
    display_name="mpg-imported",
    artifact_uri="gs://io-vertex-codelab/mpg-model/",
    serving_container_image_uri="gcr.io/cloud-aiplatform/prediction/tf2-cpu.2-3:latest"
)

# Deploy the above model to an endpoint
endpoint = model.deploy(
    machine_type="n1-standard-4"
)

接著,請返回 Cloud Shell 中的終端機,cd 返回根目錄,然後執行您剛建立的這個 Python 指令碼:

cd ..
python3 deploy.py | tee deploy-output.txt

建立資源時,終端機會將更新記錄下來。執行程式需要 10-15 分鐘。為確保運作一切正常,請在 Vertex AI 中前往控制台的「模型」部分

Vertex 控制台中的模型

點選 mgp-imported,畫面應會顯示建立該模型的端點:

待處理的端點

端點部署完成後,Cloud Shell 終端機會顯示類似下列記錄:

Endpoint model deployed. Resource name: projects/your-project-id/locations/us-central1/endpoints/your-endpoint-id

您將在下一個步驟中使用此項目,取得已部署端點的預測結果。

步驟 3:取得已部署端點的預測結果

在 Cloud Shell 編輯器中,建立名為 predict.py 的新檔案:

建立預測檔案

開啟 predict.py 並將下列程式碼貼入其中:

from google.cloud import aiplatform

endpoint = aiplatform.Endpoint(
    endpoint_name="ENDPOINT_STRING"
)

# A test example we'll send to our model for prediction
test_mpg = [1.4838871833555929,
 1.8659883497083019,
 2.234620276849616,
 1.0187816540094903,
 -2.530890710602246,
 -1.6046416850441676,
 -0.4651483719733302,
 -0.4952254087173721,
 0.7746763768735953]

response = endpoint.predict([test_mpg])

print('API response: ', response)

print('Predicted MPG: ', response.predictions[0][0])

接下來,請返回終端機並輸入以下指令,將預測檔案中的 ENDPOINT_STRING 替換成您自己的端點:

ENDPOINT=$(cat deploy-output.txt | sed -nre 's:.*Resource name\: (.*):\1:p' | tail -1)
sed -i "s|ENDPOINT_STRING|$ENDPOINT|g" predict.py

接著,您可以執行 predict.py 檔案,從我們部署的模型端點取得預測結果:

python3 predict.py

您應該會看到系統記錄的 API 回應,以及測試預測的燃油效率。

🎉 恭喜!🎉

您已瞭解如何使用 Vertex AI 執行下列作業:

  • 在自訂容器中提供訓練程式碼來訓練模型。在這個範例中,您使用了 TensorFlow 模型,但可以透過自訂容器,以任何架構建構的模型。
  • 使用預先建構的容器部署 TensorFlow 模型,做為您用於訓練的工作流程的一部分。
  • 建立模型端點及產生預測。

如要進一步瞭解 Vertex AI 的其他部分,請參閱說明文件。如要查看您在步驟 5 中開始的訓練工作結果,請前往 Vertex 控制台的「訓練」部分

7. 清除

如要刪除您部署的端點,請前往 Vertex 控制台的「端點」部分,然後按一下「刪除」圖示:

刪除端點

如要刪除 Storage 值區,請使用 Cloud 控制台中的導覽選單前往「Storage」(儲存空間)、選取值區,然後點選「Delete」(刪除):

刪除儲存空間