使用 What-If 工具和 Vertex AI 构建金融机器学习模型

1. 概览

在本实验中,您将使用 What-If 工具来分析使用财务数据训练的 XGBoost 模型。分析完模型后,您需要将其部署到 Cloud 的新 Vertex AI。

学习内容

您将了解如何:

  • 基于托管笔记本中的公共抵押贷款数据集训练 XGBoost 模型
  • 使用 What-If 工具分析模型
  • 将 XGBoost 模型部署到 Vertex AI

在 Google Cloud 上运行本实验的总费用约为 $1

2. Vertex AI 简介

本实验使用的是 Google Cloud 上提供的最新 AI 产品。Vertex AI 将整个 Google Cloud 的机器学习产品集成到无缝的开发体验中。以前,使用 AutoML 训练的模型和自定义模型是通过不同的服务访问的。现在,该新产品与其他新产品一起将这两种模型合并到一个 API 中。您还可以将现有项目迁移到 Vertex AI。如果您有任何反馈,请参阅支持页面

Vertex AI 包含许多不同的产品,可支持端到端机器学习工作流。本实验将重点介绍下面突出显示的产品:预测和笔记本。

Vertex 产品概览

3. XGBoost 入门指南

XGBoost 是一种机器学习框架,它使用决策树梯度提升来构建预测模型。其工作原理是,根据与树中不同叶节点相关联的得分将多个决策树集成在一起。

下图是一个简单的决策树模型的可视化图表,该模型根据天气预报评估是否应举行体育赛事:

树模型示例

为什么要为此模型使用 XGBoost?虽然传统神经网络已被证明在处理非结构化数据(如图片和文本)时表现最佳,但决策树通常在结构化数据(例如,我们将在此 Codelab 中使用的抵押贷款数据集)上表现非常好。

4. 设置您的环境

您需要一个启用了结算功能的 Google Cloud Platform 项目才能运行此 Codelab。如需创建项目,请按照此处的说明操作。

第 1 步:启用 Compute Engine API

前往 Compute Engine,然后选择启用(如果尚未启用)。您需要用它来创建笔记本实例。

第 2 步:启用 Vertex AI API

前往 Cloud 控制台的 Vertex 部分,然后点击启用 Vertex AI API

Vertex 信息中心

第 3 步:创建 Notebooks 实例

在 Cloud 控制台的 Vertex 部分中,点击“笔记本”:

选择笔记本

在此处,选择新建实例。然后选择不带 GPUTensorFlow 企业版 2.3 实例类型:

TFE 实例

使用默认选项,然后点击创建。创建实例后,选择打开 JupyterLab

第 4 步:安装 XGBoost

打开 JupyterLab 实例后,您需要添加 XGBoost 软件包。

为此,请从启动器中选择终端:

然后运行以下命令,安装 Vertex AI 支持的最新版 XGBoost:

pip3 install xgboost==1.2

完成后,从启动器中打开 Python 3 笔记本实例。现在可以在笔记本中开始使用了!

第 5 步:导入 Python 软件包

在笔记本的第一个单元中,添加以下导入并运行该单元。您可以按顶部菜单中的向右箭头按钮或按 Command+Enter 键来运行它:

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,向其传递上面指定的数据类型。如果原始数据集以特定方式排序,则重排数据非常重要。我们使用一个名为 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 函数,而不是使用独热编码表示分类值。

get_dummies 接受包含多个可能值的列,然后将其转换为一系列仅包含 0 和 1 的列。例如,如果我们有一个“color”列可能的值为“blue”和“红色”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 工具解读您的模型

第 1 步:创建 What-If 工具可视化图表

如需将 What-If 工具连接到本地模型,您需要向其传递一部分测试样本以及这些样本的标准答案值。我们来创建一个包含 500 个测试样本及其标准答案标签的 Numpy 数组:

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

What-If 工具的实例化过程非常简单,只需创建一个 WitConfigBuilder 对象并向其传递我们想要分析的模型即可。

由于 What-If 工具需要模型中每个类的得分列表(在本例中为 2),因此我们将结合使用 XGBoost 的 predict_proba 方法与 What-If 工具:

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 工具初始视图

y 轴表示模型的预测结果,1 表示高置信度 approved 预测,0 表示高置信度 denied 预测。x 轴表示所有已加载数据点的分布情况。

第 2 步:探索各个数据点

What-If 工具上的默认视图是 Datapoint editor 标签页。在这里,您可以点击任意数据点来查看其特征、更改特征值,以及了解该变化对模型对各个数据点的预测有何影响。

在下面的示例中,我们选择了一个接近 0.5 阈值的数据点。与此特定数据点关联的抵押贷款申请源自 CFPB。我们将该特征更改为 0,并将 agency_code_Department of Housing and Urban Development (HUD) 的值更改为 1,看看如果这笔贷款并非源自 HUD,模型的预测结果会发生什么变化:

如 What-If 工具的左下部分所示,更改此特征会使模型的 approved 预测显著降低 32%。这可能表明贷款机构对模型的输出有很大影响,但我们需要进行更多分析才能确定。

在界面的左下角,我们还可以看到每个数据点的标准答案值,并将其与模型的预测结果进行比较:

第 3 步:反事实分析

接下来,点击任意数据点并将显示最接近的计数器数据点滑块向右移动:

选择此选项后,您将看到数据点与您选择的原始数据点具有最相似特征值,但预测结果相反。然后,您可以滚动浏览特征值,查看两个数据点的差异(差异以绿色和粗体突出显示)。

第 4 步:查看部分依赖图

要了解每个特征对模型的整体预测结果有何影响,请选中部分依赖图复选框,并确保已选中全局部分依赖图

我们可以看到,源自平视显示 (HUD) 的贷款遭拒的可能性略高。图表之所以呈现这种形状,是因为代理机构代码是布尔值特征,因此值只能正好为 0 或 1。

applicant_income_thousands 是一个数值特征,在部分依赖图中,我们可以看到,收入较高会略微提高申请获得批准的可能性,但最高只能达到 20 万美元左右。$20 万之后,此功能不会影响模型的预测。

第 5 步:探索整体性能和公平性

然后,前往效果和公平性标签页。此图表显示了模型在所提供数据集上的结果的整体性能统计信息,包括混淆矩阵、PR 曲线和 ROC 曲线。

选择 mortgage_status 作为标准答案特征以查看混淆矩阵:

此混淆矩阵以总数百分比的形式显示模型的正确预测和错误预测。如果将“实际是 / 预测是”和实际否 / 预测否平方数相加,计算得出的准确率应该与您的模型相同(在本例中为 87% 左右,但由于训练机器学习模型中存在随机性元素,您的模型可能会略有不同)。

您还可以使用阈值滑块进行实验,提高和降低模型在决定贷款的预测 approved 之前需要返回的正分类得分,并了解这会对准确率、假正例和假负例有何影响。在这种情况下,准确率在阈值 0.55 左右达到最高。

接下来,在左侧的切片依据下拉菜单中,选择 loan_purpose_Home_purchase

现在,您可以查看两个数据子集的效果数据:“0”切片显示了当贷款并非用于买房时,“1”切片适用于购房贷款。查看两个切片之间的准确率、假正例率和假负例率,了解性能差异。

如果您展开这些行以查看混淆矩阵,可以看到该模型预测为“已批准”约 70% 的购房贷款申请,仅 46% 非购房贷款(具体比例因模型而异):

如果您从左侧的单选按钮中选择受众特征对等,系统会调整这两个阈值,以便模型针对两个切片中相似比例的申请者预测 approved。这对每个切片的准确率、假正例和假负例有何影响?

第 6 步:探索特征分布

最后,前往 What-If 工具中的 Features 标签页。这会显示数据集中每个特征的值的分布情况:

您可以使用此标签页来确保数据集平衡。例如,数据集中似乎很少有贷款来自农场服务机构。为提高模型准确性,如果有数据可用,我们可能会考虑添加更多来自该机构的贷款。

我们在这里仅介绍了一些 What-If 工具的探索思路。您可以随意使用该工具,还有很多其他领域有待探索!

8. 将模型部署到 Vertex AI

我们让模型在本地运行,但如果我们可以从任何位置(而不只是这个笔记本)对其执行预测,那就再好不过了。在此步骤中,我们会将其部署到云端。

第 1 步:为模型创建 Cloud Storage 存储分区

我们首先定义一些环境变量,我们将在 Codelab 的其余部分使用它们。在下面的值中填写您的 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 指向此文件。

在您的笔记本中运行以下 gsutil 命令以创建区域级存储分区:

!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 控制台的 Notebooks 界面中,选择相应笔记本,然后选择停止

如果您想删除在本实验中创建的所有资源,只需删除该笔记本实例,而无需停止该实例。

要删除您部署的端点,请导航至 Vertex 控制台的 Endpoints 部分,然后点击删除图标:

如需删除存储桶,请使用 Cloud Console 中的导航菜单,浏览到“存储空间”,选择您的存储桶,然后点击“删除”: