Como criar um modelo de ML financeiro com a Ferramenta What-If e a Vertex AI

1. Visão geral

Neste laboratório, você vai usar a Ferramenta What-if para analisar um modelo XGBoost treinado com dados financeiros. Depois de analisar o modelo, você vai implantá-lo na nova Vertex AI do Cloud.

Conteúdo do laboratório

Você vai aprender a:

  • Treine um modelo da XGBoost em um conjunto de dados público de hipoteca em um notebook hospedado
  • Analisar o modelo com a Ferramenta What-If
  • Implantar o modelo XGBoost na Vertex AI

O custo total da execução deste laboratório no Google Cloud é de aproximadamente US$ 1.

2. Introdução à Vertex AI

Este laboratório usa a mais nova oferta de produtos de IA disponível no Google Cloud. A Vertex AI integra as ofertas de ML do Google Cloud em uma experiência de desenvolvimento intuitiva. Anteriormente, modelos treinados com o AutoML e modelos personalizados eram acessíveis por serviços separados. A nova oferta combina ambos em uma única API, com outros novos produtos. Você também pode migrar projetos existentes para a Vertex AI. Se você tiver algum feedback, consulte a página de suporte.

A Vertex AI inclui vários produtos diferentes para dar suporte a fluxos de trabalho integrais de ML. Os produtos destacados abaixo são o foco deste laboratório: o Prediction e os Notebooks.

Visão geral do produto Vertex

3. Um guia rápido sobre o XGBoost

O XGBoost é um framework de aprendizado de máquina que usa árvores de decisão e otimização por gradiente para criar modelos preditivos. Ele funciona agrupando várias árvores de decisão com base na pontuação associada a diferentes nós de folha em uma árvore.

O diagrama abaixo é uma visualização de um modelo de árvore de decisão simples que avalia se um jogo esportivo deve ser jogado com base na previsão do tempo:

Exemplo de modelo de árvore

Por que estamos usando o XGBoost para este modelo? Embora as redes neurais tradicionais tenham melhor desempenho em dados não estruturados, como imagens e texto, as árvores de decisão geralmente têm um desempenho muito bom em dados estruturados, como o conjunto de dados de hipotecas que vamos usar neste codelab.

4. Configurar o ambiente

Para executar este codelab, você vai precisar de um projeto do Google Cloud Platform com o faturamento ativado. Para criar um projeto, siga estas instruções.

Etapa 1: ativar a API Compute Engine

Acesse o Compute Engine e selecione Ativar, caso essa opção ainda não esteja ativada. Você vai precisar disso para criar sua instância de notebook.

Etapa 2: ativar a API Vertex AI

Acesse a seção "Vertex" do console do Cloud e clique em Ativar a API Vertex AI.

Painel da Vertex

Etapa 3: criar uma instância de Notebooks

Na seção Vertex do console do Cloud, clique em "Notebooks":

Selecionar notebooks

Em seguida, selecione Nova instância. Em seguida, selecione o tipo de instância TensorFlow Enterprise 2.3 sem GPUs:

Instância do TFE

Use as opções padrão e clique em Criar. Quando a instância for criada, selecione Abrir o JupyterLab.

Etapa 4: instalar o XGBoost

Depois que a instância do JupyterLab for aberta, você vai precisar adicionar o pacote XGBoost.

Para fazer isso, selecione Terminal no acesso rápido:

Em seguida, execute o seguinte comando para instalar a versão mais recente do XGBoost com suporte da Vertex AI:

pip3 install xgboost==1.2

Quando isso for concluído, abra uma instância do notebook Python 3 no menu inicial. Tudo pronto para começar a usar o bloco de notas.

Etapa 5: importar pacotes do Python

Na primeira célula do notebook, adicione as importações abaixo e execute a célula. Para executar, pressione o botão de seta para a direita no menu superior ou pressione 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. Fazer o download e processar dados

Vamos usar um conjunto de dados de hipoteca de ffiec.gov para treinar um modelo XGBoost. Fizemos um pré-processamento no conjunto de dados original e criamos uma versão menor para você treinar o modelo. O modelo vai prever se um pedido de hipoteca específico será aprovado ou não.

Etapa 1: fazer o download do conjunto de dados pré-processado

Disponibilizamos uma versão do conjunto de dados no Google Cloud Storage. Para fazer o download, execute o seguinte comando gsutil no notebook do Jupyter:

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

Etapa 2: ler o conjunto de dados com o Pandas

Antes de criarmos o DataFrame do Pandas, vamos criar um dict do tipo de dados de cada coluna para que o Pandas leia o conjunto de dados corretamente:

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
})

Em seguida, vamos criar um DataFrame, transmitindo os tipos de dados especificados acima. É importante embaralhar os dados caso o conjunto original esteja ordenado de uma maneira específica. Usamos um utilitário sklearn chamado shuffle para fazer isso, que foi importado na primeira célula:

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() permite visualizar as cinco primeiras linhas do nosso conjunto de dados no Pandas. Você vai encontrar algo como isso depois de executar a célula acima:

Prévia do conjunto de dados de hipoteca

Estes são os recursos que vamos usar para treinar o modelo. Se você rolar até o fim, verá a última coluna approved, que é o que estamos prevendo. Um valor de 1 indica que um aplicativo específico foi aprovado, e 0 indica que ele foi negado.

Para conferir a distribuição de valores aprovados / negados no conjunto de dados e criar uma matriz numpy dos rótulos, execute o seguinte:

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

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

Cerca de 66% do conjunto de dados contém aplicativos aprovados.

Etapa 3: criar uma coluna fictícia para valores categóricos

Esse conjunto de dados contém uma mistura de valores categóricos e numéricos, mas o XGBoost exige que todos os recursos sejam numéricos. Em vez de representar valores categóricos usando a codificação one-hot, para nosso modelo XGBoost, vamos aproveitar a função get_dummies do Pandas.

get_dummies usa uma coluna com vários valores possíveis e a converte em uma série de colunas, cada uma com apenas 0s e 1s. Por exemplo, se tivéssemos uma coluna "color" com os valores possíveis de "blue" e "red", get_dummies a transformaria em duas colunas chamadas "color_blue" e "color_red" com todos os valores booleanos 0 e 1.

Para criar colunas fictícias para nossos recursos categóricos, execute o seguinte código:

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

data.head()

Ao visualizar os dados dessa vez, você vai encontrar elementos únicos (como purchaser_type na imagem abaixo) divididos em várias colunas:

Colunas fictícias do Pandas

Etapa 4: dividir dados em conjuntos de treinamento e teste

Um conceito importante em machine learning é a divisão entre treinamento e teste. Vamos usar a maioria dos dados para treinar o modelo e deixar o restante de lado para testar o modelo com dados que ele nunca viu antes.

Adicione o código abaixo ao seu notebook, que usa a função train_test_split do Scikit-learn para dividir nossos dados:

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

Agora está tudo pronto para você criar e treinar seu modelo.

6. Criar, treinar e avaliar um modelo XGBoost

Etapa 1: definir e treinar o modelo XGBoost

Criar um modelo no XGBoost é simples. Vamos usar a classe XGBClassifier para criar o modelo e transmitir o parâmetro objective correto para nossa tarefa de classificação específica. Neste caso, usamos reg:logistic, já que temos um problema de classificação binária e queremos que o modelo gere um único valor no intervalo (0,1): 0 para "não aprovado" e 1 para "aprovado".

O código a seguir vai criar um modelo XGBoost:

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

É possível treinar o modelo com uma linha de código, chamando o método fit() e transmitindo os dados e rótulos de treinamento.

model.fit(x_train, y_train)

Etapa 2: avaliar a acurácia do modelo

Agora podemos usar o modelo treinado para gerar previsões nos dados de teste com a função predict().

Em seguida, vamos usar a função accuracy_score() do Scikit-learn para calcular a precisão do modelo com base no desempenho dele nos dados de teste. Vamos transmitir os valores de informações empíricas junto com os valores previstos do modelo para cada exemplo no conjunto de teste:

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

A precisão deve ser de cerca de 87%, mas a sua vai variar um pouco, já que sempre há um elemento de aleatoriedade no aprendizado de máquina.

Etapa 3: salvar o modelo

Para implantar o modelo, execute o código a seguir para salvá-lo em um arquivo local:

model.save_model('model.bst')

7. Usar a ferramenta What-if para interpretar seu modelo

Etapa 1: criar a visualização da Ferramenta What-If

Para conectar a Ferramenta de simulação ao modelo local, você precisa transmitir um subconjunto dos exemplos de teste com os valores de informações empíricas desses exemplos. Vamos criar uma matriz Numpy de 500 exemplos de teste com os rótulos de informações:

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

A instanciação da ferramenta What-if é tão simples quanto criar um objeto WitConfigBuilder e transmitir o modelo que queremos analisar.

Como a ferramenta "What-if" espera uma lista de pontuações para cada classe no modelo (neste caso, 2), vamos usar o método predict_proba do XGBoost com a ferramenta "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)

Pode levar um minuto para carregar a visualização. Quando ele carregar, você verá o seguinte:

Visualização inicial da Ferramenta What-If

O eixo y mostra a previsão do modelo, com 1 sendo uma previsão de approved de alta confiança e 0 sendo uma previsão de denied de alta confiança. O eixo x é apenas a distribuição de todos os pontos de dados carregados.

Etapa 2: analisar pontos de dados individuais

A visualização padrão da Ferramenta What-If é a guia Datapoint editor. Aqui, você pode clicar em qualquer ponto de dados individual para conferir os recursos, mudar os valores dos recursos e ver como essa mudança afeta a previsão do modelo em um ponto de dados individual.

No exemplo abaixo, escolhemos um ponto de dados próximo ao limite de 0,5. A solicitação de hipoteca associada a esse ponto de dados específico foi originada pelo CFPB. Mudamos esse recurso para 0 e também mudamos o valor de agency_code_Department of Housing and Urban Development (HUD) para 1 para saber o que aconteceria com a previsão do modelo se esse empréstimo tivesse origem no HUD:

Como podemos ver na seção inferior esquerda da ferramenta "E se", a alteração desse recurso reduziu significativamente a previsão de approved do modelo em 32%. Isso pode indicar que a agência que originou o empréstimo tem um grande impacto nos resultados do modelo, mas precisaremos fazer mais análises para ter certeza.

Na parte inferior esquerda da interface, também é possível conferir o valor real de cada ponto de dados e compará-lo com a previsão do modelo:

Etapa 3: análise contrafactual

Em seguida, clique em qualquer ponto de dados e mova o controle deslizante Mostrar ponto de dados contrafactual mais próximo para a direita:

Ao selecionar essa opção, você verá o ponto de dados que tem os valores de atributo mais semelhantes ao original que você selecionou, mas a previsão oposta. Em seguida, você pode rolar pelos valores dos elementos para conferir onde os dois pontos de dados são diferentes (as diferenças são destacadas em verde e negrito).

Etapa 4: analisar os gráficos de dependência parcial

Para ver como cada atributo afeta as previsões do modelo, marque a caixa Gráficos de dependência parcial e verifique se a opção Gráficos de dependência parcial global está selecionada:

Aqui podemos ver que os empréstimos provenientes do HUD têm uma probabilidade um pouco maior de serem negados. O gráfico tem esse formato porque o código da agência é um recurso booleano, de modo que os valores só podem ser exatamente 0 ou 1.

applicant_income_thousands é um recurso numérico, e no gráfico de dependência parcial, podemos ver que uma renda mais alta aumenta ligeiramente a probabilidade de um aplicativo ser aprovado, mas apenas até cerca de US $200 mil. Depois de US $200 mil, esse recurso não afeta a previsão do modelo.

Etapa 5: analisar o desempenho geral e a imparcialidade

Em seguida, acesse a guia Performance e imparcialidade. Isso mostra as estatísticas de desempenho geral dos resultados do modelo no conjunto de dados fornecido, incluindo matrizes de confusão, curvas de PR e ROC.

Selecione mortgage_status como o elemento de informações empíricas para ver uma matriz de confusão:

Esta matriz de confusão mostra as previsões corretas e incorretas do modelo como uma porcentagem do total. Se você somar os quadrados Real: sim / Previsto: sim e Real: não / Previsto: não, ele vai somar a mesma precisão do seu modelo (neste caso, cerca de 87%, embora seu modelo possa variar um pouco, já que há um elemento de aleatoriedade no treinamento de modelos de ML).

Você também pode testar o controle deslizante de limite, aumentando e diminuindo a pontuação de classificação positiva que o modelo precisa retornar antes de decidir prever approved para o empréstimo e ver como isso muda a precisão, os falsos positivos e os falsos negativos. Nesse caso, a precisão é maior em torno de um limite de 0,55.

Em seguida, no menu suspenso Dividir por à esquerda, selecione loan_purpose_Home_purchase:

Agora você vai conferir a performance nos dois subconjuntos de dados: a fatia "0" mostra quando o empréstimo não é para compra de uma casa, e a fatia "1" é para quando o empréstimo é para compra de uma casa. Verifique a precisão, a taxa de falso positivo e a taxa de falso negativo entre as duas fatias para procurar diferenças na performance.

Se você expandir as linhas para conferir as matrizes de confusão, vai notar que o modelo prevê "aprovado" para cerca de 70% das solicitações de empréstimo para compra de imóveis e apenas 46% dos empréstimos que não são para compra de imóveis (as porcentagens exatas variam de acordo com o modelo):

Se você selecionar Paridade demográfica nos botões de opção à esquerda, os dois limites serão ajustados para que o modelo preveja approved para uma porcentagem semelhante de candidatos nas duas fatias. O que isso faz com a precisão, os falsos positivos e os falsos negativos de cada fatia?

Etapa 6: analisar a distribuição de recursos

Por fim, acesse a guia Recursos na Ferramenta What-If. Isso mostra a distribuição de valores para cada atributo no conjunto de dados:

Use essa guia para garantir que seu conjunto de dados esteja equilibrado. Por exemplo, parece que poucos empréstimos no conjunto de dados foram originados pela Farm Service Agency. Para melhorar a precisão do modelo, podemos considerar adicionar mais empréstimos dessa agência se os dados estiverem disponíveis.

Descrevemos apenas algumas ideias de exploração da Ferramenta What-If. Continue testando a ferramenta. Há muitas outras áreas para explorar.

8. Implantar o modelo na Vertex AI

Nosso modelo está funcionando localmente, mas seria bom se pudéssemos fazer previsões sobre ele de qualquer lugar (não apenas deste notebook). Nesta etapa, vamos implantar na nuvem.

Etapa 1: criar um bucket do Cloud Storage para o modelo

Primeiro, vamos definir algumas variáveis de ambiente que vamos usar no restante do codelab. Preencha os valores abaixo com o nome do seu projeto do Google Cloud, o nome do bucket do Cloud Storage que você quer criar (precisa ser globalmente exclusivo) e o nome da primeira versão do modelo:

# 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'

Agora podemos criar um bucket de armazenamento para armazenar o arquivo de modelo XGBoost. Vamos indicar a Vertex AI para este arquivo quando implantarmos.

Execute este comando gsutil no notebook para criar um bucket de armazenamento regional:

!gsutil mb -l us-central1 $MODEL_BUCKET

Etapa 2: copiar o arquivo do modelo para o Cloud Storage

Em seguida, vamos copiar o arquivo de modelo salvo do XGBoost para o Cloud Storage. Execute o seguinte comando gsutil:

!gsutil cp ./model.bst $MODEL_BUCKET

Acesse o navegador de armazenamento no Cloud Console para confirmar se o arquivo foi copiado:

Etapa 3: criar o modelo e implantar em um endpoint

Já está quase tudo pronto para implantar o modelo na nuvem. Na Vertex AI, um modelo pode conter vários endpoints. Primeiro, vamos criar um modelo e, em seguida, um endpoint dentro dele e implantar.

Primeiro, use a CLI gcloud para criar o modelo:

!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

O parâmetro artifact-uri vai apontar para o local do armazenamento em que você salvou o modelo do XGBoost. O parâmetro container-image-uri informa à Vertex AI qual contêiner pré-criado usar para exibição. Depois que o comando for concluído, acesse a seção de modelos do console da Vertex para acessar o ID do novo modelo. Ele pode ser encontrado aqui:

Conseguir o ID do modelo no console

Copie esse ID e salve-o em uma variável:

MODEL_ID = "your_model_id"

Agora é hora de criar um endpoint nesse modelo. Podemos fazer isso com este comando do gcloud:

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

Quando isso for concluído, o local do endpoint será registrado na saída do notebook. Procure a linha que diz que o endpoint foi criado com um caminho semelhante ao seguinte: projects/project_ID/locations/us-central1/endpoints/endpoint_ID. Em seguida, substitua os valores abaixo pelos IDs do endpoint criado acima:

ENDPOINT_ID = "your_endpoint_id"

Para implantar o endpoint, execute o comando gcloud abaixo:

!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

A implantação do endpoint vai levar de 5 a 10 minutos. Enquanto o endpoint está sendo implantado, acesse a seção de modelos do console. Clique no seu modelo para ver a implantação final:

Quando a implantação for concluída, você vai notar uma marca de seleção verde onde o ícone de carregamento está.

Etapa 4: testar o modelo implantado

Para verificar se o modelo implantado está funcionando, teste-o usando a gcloud para fazer uma previsão. Primeiro, salve um arquivo JSON com um exemplo do nosso conjunto de testes:

%%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]
  ]
}

Para testar o modelo, execute este comando do gcloud:

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

A previsão do modelo vai aparecer na saída. Esse exemplo específico foi aprovado, então o valor será próximo de 1.

9. Limpeza

Se você quiser continuar usando este notebook, é recomendável que você o desligue quando não estiver usando. Na interface de Notebooks no console do Cloud, selecione o notebook e clique em Parar:

Se você quiser excluir todos os recursos criados neste laboratório, exclua a instância do notebook em vez de interromper.

Para excluir o endpoint implantado, acesse a seção "Endpoints" do console da Vertex e clique no ícone de exclusão:

Para excluir o bucket do Storage, use o menu de navegação do console do Cloud, acesse o Storage, selecione o bucket e clique em "Excluir":