使用 What-If Tool 和 Vertex AI 建構金融機器學習模型

1. 總覽

在本研究室中,您將使用 What-if Tool 分析以財務資料訓練的 XGBoost 模型。分析模型後,您會將模型部署至 Cloud 的新 Vertex AI。

課程內容

學習重點:

  • 在託管筆記本中,根據公開的抵押貸款資料集訓練 XGBoost 模型
  • 使用 What-If Tool 分析模型
  • 將 XGBoost 模型部署至 Vertex AI

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

2. Vertex AI 簡介

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

Vertex AI 提供許多不同的產品,可支援端對端機器學習工作流程。本實驗室將著重於下列產品:預測和 Notebook。

Vertex 產品總覽

3. 快速 XGBoost 入門

XGBoost 是一種機器學習架構,會使用決策樹梯度提升建立預測模型。這項模型會根據與樹狀圖中不同葉節點相關聯的分數,將多個決策樹組合在一起。

下圖是簡單決策樹模型的可視化圖表,可根據天氣預報評估是否應進行運動賽事:

樹狀模型範例

為什麼我們會為這個模型使用 XGBoost?雖然傳統類神經網路在圖片和文字等非結構化資料上表現最佳,但決策樹經常在結構化資料上表現極佳,例如我們在本程式碼研究室中使用的抵押貸款資料集。

4. 設定環境

您需要已啟用計費功能的 Google Cloud Platform 專案,才能執行這個程式碼研究室。如要建立專案,請按照這篇文章中的操作說明進行。

步驟 1:啟用 Compute Engine API

前往「Compute Engine」,然後選取「啟用」 (如果尚未啟用)。您需要這項資訊才能建立 Notebook 執行個體。

步驟 2:啟用 Vertex AI API

前往 Cloud 控制台的「Vertex」專區,然後點選「啟用 Vertex AI API」

Vertex 資訊主頁

步驟 3:建立 Notebooks 執行個體

在 Cloud 控制台的 Vertex 專區中,按一下「筆記本」:

選取筆記本

接著選取「New Instance」。接著選取「TensorFlow 企業版 2.3」執行個體類型,但「不含 GPU」

TFE 執行個體

使用預設選項,然後按一下「建立」。執行個體建立完成後,請選取「Open JupyterLab」

步驟 4:安裝 XGBoost

開啟 JupyterLab 執行個體後,您需要新增 XGBoost 套件。

如要這麼做,請從啟動器選取「Terminal」(終端機):

接著執行下列指令,安裝 Vertex AI 支援的最新版 XGBoost:

pip3 install xgboost==1.2

完成後,請透過啟動器開啟 Python 3 Notebook 執行個體。現在可以開始使用筆記本了!

步驟 5:匯入 Python 套件

在筆記本的第一個儲存格中,新增下列匯入內容並執行儲存格。按下頂端選單中的向右箭頭按鈕,或按下 Command 鍵,即可開啟模式:

import pandas as pd
import xgboost as xgb
import numpy as np
import collections
import witwidget

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.utils import shuffle
from witwidget.notebook.visualization import WitWidget, WitConfigBuilder

5. 下載及處理資料

我們會使用 ffiec.gov 的抵押貸款資料集訓練 XGBoost 模型。我們已對原始資料集進行一些預先處理,並建立較小的版本供您訓練模型。模型會預測特定抵押貸款申請是否會獲得核准

步驟 1:下載預先處理的資料集

我們已在 Google Cloud Storage 中為您提供一個版本的資料集。您可以在 Jupyter 筆記本中執行下列 gsutil 指令來下載:

!gsutil cp 'gs://mortgage_dataset_files/mortgage-small.csv' .

步驟 2:使用 Pandas 讀取資料集

在建立 Pandas DataFrame 之前,我們會建立每個資料欄的資料類型 dict,讓 Pandas 正確讀取資料集:

COLUMN_NAMES = collections.OrderedDict({
 'as_of_year': np.int16,
 'agency_code': 'category',
 'loan_type': 'category',
 'property_type': 'category',
 'loan_purpose': 'category',
 'occupancy': np.int8,
 'loan_amt_thousands': np.float64,
 'preapproval': 'category',
 'county_code': np.float64,
 'applicant_income_thousands': np.float64,
 'purchaser_type': 'category',
 'hoepa_status': 'category',
 'lien_status': 'category',
 'population': np.float64,
 'ffiec_median_fam_income': np.float64,
 'tract_to_msa_income_pct': np.float64,
 'num_owner_occupied_units': np.float64,
 'num_1_to_4_family_units': np.float64,
 'approved': np.int8
})

接下來,我們將建立 DataFrame,並將上述指定的資料類型傳遞給 DataFrame。為避免原始資料集以特定方式排序,請務必將資料洗牌。我們使用名為 shufflesklearn 公用程式執行這項操作,該公用程式已在第一個儲存格中匯入:

data = pd.read_csv(
 'mortgage-small.csv',
 index_col=False,
 dtype=COLUMN_NAMES
)
data = data.dropna()
data = shuffle(data, random_state=2)
data.head()

data.head() 可讓我們在 Pandas 中預覽資料集的前五列。執行上述單元格後,畫面應會顯示類似下列的內容:

抵押貸款資料集預覽

這些是我們用來訓練模型的特徵。如果您捲動至末端,就會看到最後一欄 approved,也就是我們要預測的內容。如果值為 1,表示特定申請已獲核准;如果值為 0,則表示申請遭拒。

如要查看資料集中的核准 / 拒絕值分布情形,並建立標籤的 numpy 陣列,請執行以下操作:

# Class labels - 0: denied, 1: approved
print(data['approved'].value_counts())

labels = data['approved'].values
data = data.drop(columns=['approved'])

約有 66% 的資料集含有已核准的申請資料。

步驟 3:為分類值建立虛擬欄

這個資料集包含類別和數值值,但 XGBoost 要求所有特徵都必須是數值。對於 XGBoost 模型,我們會利用 Pandas get_dummies 函式,而非使用one-hot 編碼來表示分類值。

get_dummies 會將含有多個可能值的資料欄轉換為一系列資料欄,每個資料欄只包含 0 和 1。舉例來說,如果我們有一個「color」資料欄,其中可能的值為「blue」和「red」,get_dummies 會將這個欄轉換為 2 個資料欄,分別命名為「color_blue」和「color_red」,並將所有布林值轉換為 0 和 1。

如要為類別特徵建立虛設欄,請執行下列程式碼:

dummy_columns = list(data.dtypes[data.dtypes == 'category'].index)
data = pd.get_dummies(data, columns=dummy_columns)

data.head()

這次預覽資料時,您會看到單一地圖項目 (例如下圖中的 purchaser_type) 分割成多個資料欄:

Pandas 虛擬欄

步驟 4:將資料拆分為訓練集和測試集

機器學習中一個重要的概念是訓練 / 測試分割。我們會使用大部分的資料來訓練模型,並將其餘資料留作測試,以便在模型從未見過的資料上測試模型。

在筆記本中新增下列程式碼,使用 Scikit-learn 函式 train_test_split 分割資料:

x,y = data.values,labels
x_train,x_test,y_train,y_test = train_test_split(x,y)

您現在可以建構及訓練模型了!

6. 建構、訓練及評估 XGBoost 模型

步驟 1:定義及訓練 XGBoost 模型

在 XGBoost 中建立模型十分簡單。我們將使用 XGBClassifier 類別建立模型,只需為特定分類工作傳遞正確的 objective 參數即可。在本例中,我們使用 reg:logistic,因為我們遇到二元分類問題,希望模型輸出 (0,1) 範圍內的單一值:0 代表未核准,1 代表核准。

下列程式碼會建立 XGBoost 模型:

model = xgb.XGBClassifier(
    objective='reg:logistic'
)

您可以使用一行程式碼訓練模型,呼叫 fit() 方法並傳遞訓練資料和標籤。

model.fit(x_train, y_train)

步驟 2:評估模型準確度

我們現在可以使用已訓練的模型,透過 predict() 函式針對測試資料產生預測結果。

然後,我們會使用 Scikit-learn 的 accuracy_score() 函式,根據測試資料執行模型的方式計算模型的準確率。我們會為測試集中的每個範例,傳遞真值和模型的預測值:

y_pred = model.predict(x_test)
acc = accuracy_score(y_test, y_pred.round())
print(acc, '\n')

準確度應約為 87%,但由於機器學習總是存在隨機性,因此您的結果可能會有些許差異。

步驟 3:儲存模型

如要部署模型,請執行下列程式碼,將模型儲存至本機檔案:

model.save_model('model.bst')

7. 使用 What-if Tool 解讀模型

步驟 1:建立假設分析工具的示意圖

如要將 What-if Tool 連結至您的本機模型,您必須將一部分的測試範例,以及這些範例的真值值傳送給該模型。我們將建立一個 Numpy 陣列,其中包含 500 個測試範例和實際資料標籤:

num_wit_examples = 500
test_examples = np.hstack((x_test[:num_wit_examples],y_test[:num_wit_examples].reshape(-1,1)))

只要建立 WitConfigBuilder 物件,然後將要分析的模型傳遞給該物件,即可輕鬆將 What-if Tool 例項化。

由於 What-if Tool 預期模型中每個類別的分數清單 (本例中為 2),因此我們將搭配 What-If Tool 使用 XGBoost 的 predict_proba 方法:

config_builder = (WitConfigBuilder(test_examples.tolist(), data.columns.tolist() + ['mortgage_status'])
  .set_custom_predict_fn(model.predict_proba)
  .set_target_feature('mortgage_status')
  .set_label_vocab(['denied', 'approved']))
WitWidget(config_builder, height=800)

請注意,視覺化資訊需要一分鐘的時間才能載入。載入後,您應該會看到以下內容:

What-If Tool 的初始檢視畫面

y 軸顯示模型的預測結果,1 代表高可信度的 approved 預測,0 代表高可信度的 denied 預測。x 軸只是所有載入資料點的散布範圍。

步驟 2:探索個別資料點

What-if Tool 的預設檢視畫面為「Datapoint Editor」分頁。您可以在這裡點選任一資料點,查看該資料點的特徵、變更特徵值,以及查看變更如何影響模型對個別資料點的預測結果。

在下方範例中,我們選擇了接近 0.5 門檻的資料點。與這個特定資料點相關聯的抵押貸款申請來自消費者金融保護局 (CFPB)。我們已將特徵值變更為 0,並將 agency_code_Department of Housing and Urban Development (HUD) 的值變更為 1,以瞭解如果這筆貸款並非源自 HUD,模型的預測作業會受到什麼影響:

如同我們在假設分析工具的左下方看到的結果,變更這項功能後,模型的 approved 預測值大幅減少了 32%。這可能代表出借代理商的貸款已對模型的輸出結果有重大影響,但我們還需要進行更多分析才能確定。

在 UI 的左下方,我們也可以查看每個資料點的實際值,並與模型預測結果進行比較:

步驟 3:反事實分析

接著,按一下任一資料點,然後將「Show nearest counterfactual datapoint」滑桿向右移動:

選取這個選項後,系統會顯示與您選取的原始資料點最相似的資料值,但預測結果相反。接著您可以捲動特徵值,查看兩個資料點的差異 (差異會以綠色和粗體標示)。

步驟 4:查看部分依賴度圖表

如要瞭解各項特徵對模型整體預測結果的影響,請勾選「部分相依圖」方塊,並確認您已選取「全域部分相依圖」

從這裡可以看到,來自 HUD 的貸款遭拒的機率略高。代理商代碼是布林值功能,因此值只能是 0 或 1,因此圖表會呈現這個形狀。

applicant_income_thousands 是數值特徵,在部分相依圖中,我們可以發現,收入越高的申請機率就越高,但最多只有 $20 萬美元。超過 20 萬美元後,這項功能就不會影響模型的預測結果。

步驟 5:瞭解整體成效和公平性

接著,前往「成效與公平性」分頁。這項功能會顯示模型在提供的資料集上產生結果的整體成效統計資料,包括混淆矩陣、PR 曲線和 ROC 曲線。

選取 mortgage_status 做為實際資料地圖項目,即可查看混淆矩陣:

這個混淆矩陣會顯示模型的正確和錯誤預測結果,以百分比表示。如果您將「實際為是 / 預測為是」和「實際為否 / 預測為否」的方塊加總起來,應該會與模型的準確率相同 (在本例中約為 87%,但由於訓練機器學習模型時會出現隨機因素,因此您的模型可能會略有不同)。

您還可以使用門檻滑桿進行實驗,提高及降低模型在決定貸款預測的 approved 之前必須傳回的正分類分數,然後看看會如何改變準確率、偽陽性和偽陰性。在本例中,準確率為 .55 的門檻最高。

接著,在左側的「切片依據」下拉式選單中,選取 loan_purpose_Home_purchase

您現在會看到資料的兩個子集的成效:"0"切片代表貸款非購屋貸款,"1"切片代表貸款為購屋貸款。檢查兩個切片之間的準確率、偽陽性和偽陰性率,找出效能差異。

展開列表查看混淆矩陣,您會發現模型預測約 70% 的房貸申請為「核准」,且只有 46% 的貸款不是用於購屋 (實際百分比會因模型而異):

如果您從左側的圓形按鈕中選取「群體均等」,系統會調整兩個門檻,讓模型預測兩個區塊中百分比相近的申請人 approved。我們該如何改進每個片段的準確率、偽陽性和偽陰性結果?

步驟 6:探索功能分發

最後,前往 What-if Tool 中的「Features」分頁。這會顯示資料集中每個特徵的值分佈情形:

您可以使用這個分頁確認資料集是否平衡。舉例來說,資料集中來自農業服務局的貸款似乎很少。為提高模型準確度,我們可能會考慮加入該機構的更多貸款 (如果有資料的話)。

我們在此僅介紹了幾個 What-If Tool 探索的想法。歡迎繼續試用這項工具,還有許多值得探索的地方!

8. 將模型部署至 Vertex AI

我們已在本機上執行模型,但如果能從任何地方 (而非僅限於這個 Notebook) 進行預測,那就太好了!在這個步驟中,我們會將其部署至雲端。

步驟 1:為模型建立 Cloud Storage 值區

首先,我們先定義一些環境變數,這些變數會在本程式碼研究室的後續部分中使用。請填入下列值,包括 Google Cloud 專案名稱、要建立的 Cloud Storage 值區名稱 (必須是全域不重複的名稱),以及模型第一個版本的版本名稱:

# Update the variables below to your own Google Cloud project ID and GCS bucket name. You can leave the model name we've specified below:
GCP_PROJECT = 'your-gcp-project'
MODEL_BUCKET = 'gs://storage_bucket_name'
MODEL_NAME = 'xgb_mortgage'

我們現在可以建立儲存值區來儲存 XGBoost 模型檔案。我們會在部署時將 Vertex AI 指向這個檔案。

在 Notebook 中執行以下 gsutil 指令,建立地區性 Storage 值區:

!gsutil mb -l us-central1 $MODEL_BUCKET

步驟 2:將模型檔案複製到 Cloud Storage

接下來,我們會將 XGBoost 儲存的模型檔案複製到 Cloud Storage。執行下列 gsutil 指令:

!gsutil cp ./model.bst $MODEL_BUCKET

請前往 Cloud 控制台中的儲存空間瀏覽器,確認檔案已複製完成:

步驟 3:建立模型並部署至端點

我們幾乎準備好將模型部署至雲端了!在 Vertex AI 中,模型可以容納多個端點。首先來建立模型,然後在模型內建立端點並加以部署

首先,請使用 gcloud CLI 建立模型:

!gcloud beta ai models upload \
--display-name=$MODEL_NAME \
--artifact-uri=$MODEL_BUCKET \
--container-image-uri=us-docker.pkg.dev/cloud-aiplatform/prediction/xgboost-cpu.1-2:latest \
--region=us-central1

artifact-uri 參數會指向儲存 XGBoost 模型的儲存空間位置。container-image-uri 參數會告知 Vertex AI 要使用哪個預先建構的容器來處理。這項指令完成後,請前往 Vertex 主控台的模型專區,取得新模型的 ID。請參閱以下連結:

從控制台取得模型 ID

複製該 ID 並儲存至變數:

MODEL_ID = "your_model_id"

現在,您可以建立這個模型的端點。我們可以使用以下 gcloud 指令執行這項操作:

!gcloud beta ai endpoints create \
--display-name=xgb_mortgage_v1 \
--region=us-central1

完成後,筆記本輸出內容中就會顯示端點的登入位置。請找出指出端點是使用以下路徑建立的程式碼行:projects/project_ID/locations/us-central1/endpoints/endpoint_ID. 然後將下方值替換為您在上述步驟中建立的端點 ID:

ENDPOINT_ID = "your_endpoint_id"

如要部署端點,請執行下列 gcloud 指令:

!gcloud beta ai endpoints deploy-model $ENDPOINT_ID \
--region=us-central1 \
--model=$MODEL_ID \
--display-name=xgb_mortgage_v1 \
--machine-type=n1-standard-2 \
--traffic-split=0=100

端點部署作業大約需要 5 到 10 分鐘才能完成。端點部署期間,請前往控制台的「模型」部分。按一下模型,您應該會看到端點部署作業:

部署作業完成後,載入旋轉圖示會變成綠色勾號。

步驟 4:測試已部署的模型

如要確認已部署的模型是否正常運作,請使用 gcloud 進行預測測試。首先,請儲存含有測試集範例的 JSON 檔案:

%%writefile predictions.json
{
  "instances": [
    [2016.0, 1.0, 346.0, 27.0, 211.0, 4530.0, 86700.0, 132.13, 1289.0, 1408.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0]
  ]
}

執行下列 gcloud 指令來測試模型:

!gcloud beta ai endpoints predict $ENDPOINT_ID \
--json-request=predictions.json \
--region=us-central1

您應該會在輸出內容中看到模型的預測結果。這個特定範例已獲核准,因此值應該接近 1。

9. 清理

如果你想繼續使用這個筆記本,建議你在不用時關閉它。在 Cloud 控制台的 Notebook 使用者介面中,選取 Notebook,然後選取「Stop」

如果您想刪除在本實驗室中建立的所有資源,只要刪除筆記本執行個體即可,無須停止執行。

如要刪除已部署的端點,請前往 Vertex 控制台的「Endpoints」(端點) 部分,然後點選刪除圖示:

如要刪除儲存體值區,請使用 Cloud 控制台的「導覽」選單,前往「儲存體」頁面,選取所需值區,然後按一下「刪除」: