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 (em inglês) treinado com dados financeiros. Depois da análise, você vai implantar o modelo 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 da 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. Uma breve introdução à XGBoost

O XGBoost (em inglês) é um framework de machine learning que usa árvores de decisão e aumento de gradiente para criar modelos preditivos. Ela funciona unindo 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 XGBoost no modelo? Embora as redes neurais tradicionais tenham demonstrado um desempenho melhor em dados não estruturados, como imagens e texto, as árvores de decisão costumam ter um desempenho extremamente bom em dados estruturados, como o conjunto de dados de hipoteca que usaremos 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

Navegue até 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

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

Instância TFE

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

Etapa 4: instalar o XGBoost

Quando sua instância do JupyterLab for aberta, adicione o pacote XGBoost.

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

Em seguida, execute o comando a seguir para instalar a versão mais recente do XGBoost compatível com a Vertex AI:

pip3 install xgboost==1.2

Depois disso, abra uma instância de notebook do Python 3 no acesso rápido. Você já pode começar a usar seu notebook.

Etapa 5: importar pacotes do Python

Na primeira célula do notebook, adicione as importações abaixo e execute a célula. Para executá-lo, 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ê usar no treinamento do modelo. O modelo prevê se um determinado aplicativo de hipoteca será aprovado ou não.

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

Disponibilizamos uma versão do conjunto de dados para você no Google Cloud Storage. É possível fazer o download dele executando o seguinte comando gsutil no seu notebook do Jupyter:

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

Etapa 2: ler o conjunto de dados com o Pandas

Antes de criar o DataFrame do Pandas, criaremos 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, criaremos um DataFrame, transmitindo os tipos de dados especificados acima. É importante embaralhar os dados caso o conjunto original esteja ordenado de uma maneira específica. Para isso, usamos um utilitário sklearn chamado shuffle, que importamos 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ê verá algo parecido com isso depois de executar a célula acima:

Prévia do conjunto de dados de hipoteca

Esses são os atributos que vamos usar para treinar nosso modelo. Se você rolar até o fim, verá a última coluna approved, que é o que estamos prevendo. O valor 1 indica que uma inscrição específica foi aprovada e 0 indica que ela foi negada.

Para ver 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 combinação de valores categóricos e numéricos, mas o XGBoost exige que todos os atributos sejam numéricos. Em vez de representar valores categóricos usando a codificação one-hot, usaremos a função get_dummies do Pandas no modelo XGBoost.

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 “cor” com possíveis valores de "blue" (azul) e "vermelho", get_dummies transformaria isso em duas colunas chamadas "color_blue" e "color_red" com todos os valores booleanos 0 e 1.

Para criar colunas fictícias para os atributos 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 desta vez, você verá recursos únicos (como purchaser_type ilustrado 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 nossos dados para treinar o modelo e deixar o resto de lado para testar o modelo com dados que nunca foram vistos antes.

Adicione o seguinte código ao seu notebook, que usa a função Scikit-learn train_test_split 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. Usaremos a classe XGBClassifier para criar o modelo. Basta transmitir o parâmetro objective correto para nossa tarefa de classificação específica. Neste caso, usamos reg:logistic porque temos um problema de classificação binária e queremos que o modelo gere um único valor no intervalo de (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 nosso 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 acurácia do modelo com base no desempenho dele com os 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 será de cerca de 87%. No entanto, a sua varia um pouco, porque sempre há um elemento de aleatoriedade no machine learning.

Etapa 3: salvar o modelo

Para implantar o modelo, execute o seguinte código 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 What-If ao seu modelo local, transmita um subconjunto dos exemplos de teste e os valores de informações empíricas deles. Vamos criar uma matriz numpy de 500 exemplos de teste com os respectivos rótulos de informações empíricas:

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

Para instanciar a Ferramenta What-If, basta 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 essa ferramenta:

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)

O carregamento da visualização leva um minuto. Quando ele for carregado, você verá o seguinte:

Visualização inicial da Ferramenta What-If

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

Etapa 2: explorar pontos de dados individuais

A visualização padrão na Ferramenta What-If é a guia Editor do ponto de dados. Aqui é possível clicar em qualquer ponto de dados individual para ver os atributos, alterar os valores dos atributos e ver como essa mudança afeta a previsão do modelo sobre um ponto de dados individual.

No exemplo abaixo, escolhemos um ponto de dados próximo ao limite de 0,5. O aplicativo de hipoteca associado a este ponto de dados específico foi originado do CFPB. Mudamos esse atributo para 0 e também mudamos o valor de agency_code_Department of Housing and Urban Development (HUD) para 1. Assim, você vai descobrir o que aconteceria com a previsão do modelo se esse empréstimo se originasse do HUD:

Como podemos ver na seção do canto inferior esquerdo da Ferramenta What-If, mudar esse atributo diminuiu significativamente a previsão approved do modelo em 32%. Isso pode indicar que a agência que originou o empréstimo tem um forte impacto nos resultados do modelo, mas precisaremos fazer mais análises para ter certeza.

Na parte inferior esquerda da interface, também é possível ver o valor de informações empíricas 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 contrafatual 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, role pelos valores dos atributos para ver onde os dois pontos de dados diferem (as diferenças são destacadas em verde e em 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 esta forma porque o código da agência é um recurso boleano, de modo que os valores só podem ser exatamente 0 ou 1.

applicant_income_thousands é um atributo numérico e, no gráfico de dependência parcial, podemos ver que uma renda maior aumenta ligeiramente a probabilidade de uma inscrição ser aprovada, mas até cerca de US $200 mil. Após US $200 mil, esse atributo não afeta a previsão do modelo.

Etapa 5: analisar o desempenho geral e a imparcialidade

Em seguida, acesse a página Relatórios de desempenho Imparcialidade. Isso mostra as estatísticas gerais de desempenho dos resultados do modelo no conjunto de dados fornecido, incluindo matrizes de confusão, curvas PR e curvas ROC.

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

Essa 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 / Sim previsto e Não real / Não previsto, ele terá a mesma acurácia do modelo (nesse caso, cerca de 87%, embora seu modelo possa variar um pouco porque há um elemento de aleatoriedade no treinamento de modelos de ML).

Também é possível testar o controle deslizante de limite, aumentar ou diminuir a pontuação de classificação positiva que o modelo precisa retornar antes de decidir prever o approved para o empréstimo e ver como isso muda a acurácia, os falsos positivos e os falsos negativos. Nesse caso, a acurácia é mais alta em torno de um limite de 0,55.

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

Agora você vai notar o desempenho dos dois subconjuntos de dados: o "0" fração mostra quando o empréstimo não se destina à compra de uma casa, e "1" uma fração para o empréstimo para a compra de uma casa. Verifique a taxa de precisão, falso positivo e taxa de falso negativo entre as duas fatias para procurar diferenças no desempenho.

Se você expandir as linhas para analisar as matrizes de confusão, vai notar que o modelo prevê "aprovadas" para cerca de 70% das solicitações de empréstimo para compra de casas e apenas 46% dos empréstimos que não são para compra de casas (as porcentagens exatas variam em cada 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 em ambos os setores. O que isso faz com a precisão, falsos positivos e falsos negativos de cada fatia?

Etapa 6: analisar a distribuição de atributos

Por fim, navegue até 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 o equilíbrio do conjunto de dados. Por exemplo, parece que pouquíssimos empréstimos no conjunto de dados foram originados da Agência de Serviços Farmacêuticos. 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. Fique à vontade para continuar testando a ferramenta, há muito mais á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 implantá-lo na nuvem.

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

Primeiro, defina algumas variáveis de ambiente que serão usadas 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 versão da primeira versão do seu 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 estamos prontos para 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 de modelo para o Cloud Storage

Em seguida, você vai copiar o arquivo de modelo salvo do XGBoost no Cloud Storage. Execute o seguinte comando gsutil:

!gsutil cp ./model.bst $MODEL_BUCKET

Acesse o navegador do Storage no console do Cloud para confirmar se o arquivo foi copiado:

Etapa 3: criar o modelo e implantar em um endpoint

Estamos quase prontos para implantar o modelo na nuvem. Na Vertex AI, um modelo pode conter vários endpoints. Primeiro, vamos criar um modelo, depois vamos criar um endpoint nesse modelo e implantá-lo.

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 apontará para o local de 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 encontrar o ID do novo modelo. Ele pode ser encontrado aqui:

Extrair o ID do modelo no console

Copie esse ID e salve em uma variável:

MODEL_ID = "your_model_id"

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

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

Ao concluir, você verá a localização do endpoint registrada na saída do nosso notebook. Procure a linha que informa que o endpoint foi criado com um caminho semelhante a este: projects/project_ID/locations/us-central1/endpoints/endpoint_ID.. Em seguida, substitua os valores abaixo pelos IDs do endpoint criados 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 seu endpoint estiver sendo implantado, acesse a seção de modelos do console. Clique no modelo para ver a implantação final:

Quando a implantação for concluída, uma marca de seleção verde vai aparecer no local do ícone de carregamento.

Etapa 4: testar o modelo implantado

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

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

Execute este comando gcloud para testar o modelo:

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

A previsão do modelo será exibida 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, é recomendado que você o desative quando não estiver em uso. A partir da IU de Notebooks no Console do Cloud, selecione o notebook e depois clique em Parar:

Se quiser excluir todos os recursos criados neste laboratório, basta excluir a instância do notebook em vez de interrompê-la.

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":