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

1. 概览

在本实验中,您将使用假设分析工具分析基于金融数据训练的 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 包含许多不同的产品,可支持端到端机器学习工作流。本实验将重点介绍下面突出显示的产品:Prediction 和 Notebook。

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 部分中,点击“笔记本”:

选择笔记本

然后,选择新建实例。然后,选择不带 GPU 的 TensorFlow 企业版 2.3 实例类型:

TFE 实例

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

第 4 步:安装 XGBoost

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

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

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

pip3 install xgboost==1.2

完成后,从启动器中打开 Python 3 笔记本实例。您可以开始在记事本中进行操作了!

第 5 步:导入 Python 软件包

在笔记本的第一个单元中,添加以下 import 并运行该单元。您可以按顶部菜单中的向右箭头按钮或按 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”和“red”,get_dummies 会将其转换为两个名为“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 工具连接到本地模型,您需要向其传递一部分测试样本以及这些样本的标准答案值。我们创建一个包含 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,模型的预测结果会发生什么变化:

如假设分析工具的左下角部分所示,更改此特征后,模型的 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 工具中的功能标签页。这会显示数据集中每个特征的值分布情况:

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

我们在本文中仅介绍了“假设分析”工具的几个探索思路。欢迎随意继续使用该工具,还有许多方面可以探索!

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”界面中,选择相应 Notebook,然后选择 Stop

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

如需删除您部署的端点,请前往 Vertex 控制台的“端点”部分,然后点击删除图标:

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