Como analisar um modelo de ML financeiro implantado na AI Platform do Cloud com a Ferramenta What-If

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 e implantado na AI Platform 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 no AI Platform Notebooks
  • Implante o modelo XGBoost no AI Platform
  • Analisar o modelo com a Ferramenta What-If

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

2. 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:

308a0bfc70733abf.png

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.

3. 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 Cloud AI Platform Models

Acesse a seção Modelos do AI Platform do console do Cloud e clique em "Ativar", caso essa opção ainda não esteja ativada.

d0d38662851c6af3.png

Etapa 2: 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 3: criar uma instância de Notebooks no AI Platform

Acesse a seção de Notebooks do AI Platform do console do Cloud e clique em Nova instância. Em seguida, selecione o tipo de instância TF Enterprise 2.x mais recente sem GPUs:

7d16190440ab2e9c.png

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

772f8868d3841ba0.png

Etapa 4: instalar o XGBoost

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

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

28dcf2790ce77c96.png

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

pip3 install xgboost==0.90

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

4. 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 nosso DataFrame do Pandas, criaremos um dict do tipo de dados de cada coluna para que o Pandas leia nosso 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:

29106b71103235a6.png

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:

83aacfaad626e538.png

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,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.

5. 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')

6. implantar o modelo na AI Platform do Cloud

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 these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
MODEL_BUCKET = 'gs://storage_bucket_name'
VERSION_NAME = 'v1'
MODEL_NAME = 'xgb_mortgage'

Agora estamos prontos para criar um bucket de armazenamento para armazenar o arquivo de modelo XGBoost. Vamos indicar o AI Platform do Cloud nesse arquivo durante a implantação.

Execute este comando gsutil no seu notebook para criar um bucket:

!gsutil mb $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:

31e2567fa0117214.png

Etapa 3: criar e implantar o modelo

Estamos quase prontos para implantar o modelo. O seguinte comando ai-platform da gcloud vai criar um novo modelo no seu projeto. Ele será chamado de xgb_mortgage:

!gcloud ai-platform models create $MODEL_NAME --region='global'

Agora é hora de implantar o modelo. Podemos fazer isso com este comando gcloud:

!gcloud ai-platform versions create $VERSION_NAME \
--model=$MODEL_NAME \
--framework='XGBOOST' \
--runtime-version=2.1 \
--origin=$MODEL_BUCKET \
--python-version=3.7 \
--project=$GCP_PROJECT \
--region='global'

Enquanto ele estiver em execução, verifique a seção de modelos do console do AI Platform. Sua nova versão será implantada nesse local:

342875ba92becad1.png

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

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 o primeiro exemplo do nosso conjunto de teste:

%%writefile predictions.json
[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 código para testar o modelo:

prediction = !gcloud ai-platform predict --model=xgb_mortgage --region='global' --json-instances=predictions.json --version=$VERSION_NAME --verbosity=none

print(prediction)

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.

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 aos seus modelos do AI Platform, 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].values,y_test[:num_wit_examples].reshape(-1,1)))

Para instanciar a Ferramenta What-If, basta criar um objeto WitConfigBuilder e transmitir a ele o modelo do AI Platform que queremos analisar.

Usamos o parâmetro opcional adjust_prediction aqui porque a Ferramenta What-If espera uma lista de pontuações para cada classe no modelo (neste caso, 2). Como nosso modelo retorna somente um valor de 0 a 1, nós o transformamos para o formato correto nesta função:

def adjust_prediction(pred):
  return [1 - pred, pred]

config_builder = (WitConfigBuilder(test_examples.tolist(), data.columns.tolist() + ['mortgage_status'])
  .set_ai_platform_model(GCP_PROJECT, MODEL_NAME, VERSION_NAME, adjust_prediction=adjust_prediction)
  .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:

4c0b00e6afcdbe01.png

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

717620d6a1330479.png

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:

60ff20ae80ed5e27.png

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:

ae64fd7abefe5449.png

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:

72117b5ceb683841.png

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:

fe1384ee47699498.png

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 (cerca de 87%).

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:

f3f1858d627d57ab.png

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

318a8d5a8ffc6bea.png

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:

48ab3c4879793324.png

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

879147427150b6c7.png

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

Usando o menu de navegação do console do Cloud, acesse "Storage" e exclua os dois buckets que você criou para armazenar os recursos do modelo.