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 treinado em dados financeiros e implantado na IA Platform do Google Cloud.

Conteúdo do laboratório

Você vai aprender a:

  • Treinar um modelo XGBoost em um conjunto de dados público de hipotecas no AI Platform Notebooks
  • Implantar o modelo XGBoost na AI Platform
  • Analisar o modelo usando a Ferramenta What-If

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

2. Um guia rápido do XGBoost

O XGBoost é uma estrutura de machine learning que usa árvores de decisão e otimização de gradiente para criar modelos preditivos. Ele funciona combinando várias árvores de decisão com base na pontuação associada a diferentes nós folha em uma árvore.

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

308a0bfc70733abf.png

Por que estamos usando o XGBoost para esse modelo? Embora as redes neurais tradicionais tenham mostrado um desempenho melhor 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 hipoteca que vamos usar 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", se ainda não tiver feito isso.

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 do AI Platform Notebooks

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

7d16190440ab2e9c.png

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

772f8868d3841ba0.png

Etapa 4: instalar o XGBoost

Depois que 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 Google Cloud:

pip3 install xgboost==0.90

Depois que isso for concluído, abra uma instância do notebook Python 3 no iniciador. Tudo pronto para começar a usar o notebook.

Etapa 5: importar pacotes Python

Na primeira célula do notebook, adicione as importações a seguir 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

4. Fazer o download e processar dados

Vamos usar um conjunto de dados de hipotecas 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 vai prever se um determinado pedido 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. 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 criar o DataFrame do Pandas, vamos criar um dicionário com o 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, vamos criar um DataFrame, transmitindo os tipos de dados especificados acima. É importante embaralhar os dados caso o conjunto de dados original esteja ordenado de uma maneira específica. Usamos um utilitário sklearn chamado shuffle para fazer isso, 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 conjunto de dados no Pandas. Depois de executar a célula acima, você vai encontrar algo parecido com isto:

29106b71103235a6.png

Esses são os recursos que vamos usar para treinar nosso modelo. Se você rolar até o final, vai encontrar 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 dos 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 atributos sejam numéricos. Em vez de representar valores categóricos usando 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 tivermos uma coluna "cor" com os valores possíveis "azul" e "vermelho", o get_dummies vai transformar isso em duas colunas chamadas "cor_azul" e "cor_vermelho" 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 desta vez, você vai notar que recursos únicos (como purchaser_type, mostrado abaixo) foram divididos em várias colunas:

83aacfaad626e538.png

Etapa 4: dividir os dados em conjuntos de treinamento e teste

Um conceito importante no machine learning é a divisão entre treinamento e teste. Vamos usar a maioria dos dados para treinar nosso modelo e separar o restante para testá-lo com dados que ele nunca viu antes.

Adicione o código a seguir ao notebook, que usa a função train_test_split do Scikit Learn para dividir os dados:

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

Agora você está pronto para 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. Vamos usar a classe XGBClassifier para criar o modelo e só precisamos transmitir o parâmetro objective correto para nossa tarefa de classificação específica. Nesse caso, usamos reg:logistic porque 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 cria 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 acurácia do modelo com base na performance 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 nosso conjunto de teste:

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

A acurácia 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 seguinte código para salvá-lo em um arquivo local:

model.save_model('model.bst')

6. Implantar o modelo no AI Platform da IA do Google Cloud

Nosso modelo está funcionando localmente, mas seria bom se pudéssemos fazer previsões nele de qualquer lugar, não apenas deste notebook. Nesta etapa, vamos implantá-lo na nuvem.

Etapa 1: criar um bucket do Cloud Storage para nosso 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 na nuvem 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 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 modelo XGBoost. Vamos direcionar a AI Platform do Cloud para esse arquivo durante a implantação.

Execute este comando gsutil no notebook para criar um bucket:

!gsutil mb $MODEL_BUCKET

Etapa 2: copiar o arquivo modelo para o Cloud Storage

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

!gsutil cp ./model.bst $MODEL_BUCKET

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

31e2567fa0117214.png

Etapa 3: criar e implantar o modelo

Quase tudo pronto para implantar o modelo. O comando ai-platform gcloud a seguir vai criar um novo modelo no seu projeto. Vamos chamar esse 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 isso, verifique a seção de modelos do console da AI Platform. A nova versão vai aparecer sendo implantada:

342875ba92becad1.png

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

Etapa 4: testar o modelo implantado

Para garantir que o modelo implantado esteja funcionando, teste-o usando o gcloud para fazer uma previsão. Primeiro, salve um arquivo JSON com o primeiro exemplo do nosso conjunto de testes:

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

Teste o modelo executando este código:

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 vai aparecer na saída. Este exemplo específico foi aprovado, então você vai ver um valor próximo de 1.

7. Usar a Ferramenta What-If para interpretar seu modelo

Etapa 1: criar a visualização da ferramenta "E se?"

Para conectar a Ferramenta What-If aos seus modelos do AI Platform, transmita um subconjunto dos exemplos de teste com os valores de informações empíricas deles. 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].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 você quer analisar.

Usamos o parâmetro opcional adjust_prediction porque a Ferramenta What-If espera uma lista de pontuações para cada classe no nosso modelo (neste caso, 2). Como nosso modelo retorna apenas um valor de 0 a 1, transformamos ele no 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)

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

4c0b00e6afcdbe01.png

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

Etapa 2: analisar pontos de dados individuais

A visualização padrão na Ferramenta What-If é a guia Editor de pontos de dados. Clique em qualquer ponto de dados individual para conferir os recursos dele, mudar os valores 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. O pedido de hipoteca associado a esse ponto de dados específico foi originado do CFPB. Mudamos esse recurso para 0 e também alteramos o valor de agency_code_Department of Housing and Urban Development (HUD) para 1 para ver o que aconteceria com a previsão do modelo se esse empréstimo fosse originado do HUD:

717620d6a1330479.png

Como podemos ver na seção inferior esquerda da Ferramenta de simulação, mudar esse recurso diminuiu significativamente a previsão de approved do modelo em 32%. Isso pode indicar que a agência de origem de um empréstimo tem um grande impacto na saída do modelo, mas precisamos fazer mais análises para ter certeza.

Na parte inferior esquerda da interface, também é possível ver o valor de verdade fundamental 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 o ponto de dados contrafactual mais próximo para a direita:

ae64fd7abefe5449.png

Ao selecionar essa opção, você verá o ponto de dados com os valores de atributos mais semelhantes ao original selecionado, mas com a previsão oposta. Em seguida, role pelos valores de atributos para ver onde os dois pontos de dados diferem. As diferenças são destacadas em verde e negrito.

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

Para saber como cada atributo afeta as previsões do modelo no geral, marque a caixa Gráficos de dependência parcial e confira se Gráficos de dependência parcial globais está selecionado:

72117b5ceb683841.png

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

applicant_income_thousands é uma variável numérica. No gráfico de dependência parcial, podemos ver que uma renda mais alta aumenta um pouco a probabilidade de aprovação de um pedido, 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: analise a performance geral e a imparcialidade

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

Selecione mortgage_status como o atributo de informação empírica para ver uma matriz de confusão:

fe1384ee47699498.png

Essa matriz de confusão mostra as previsões corretas e incorretas do nosso modelo como uma porcentagem do total. Se você somar os quadrados Sim real / Sim previsto e Não real / Não previsto, o resultado será a mesma acurácia do seu modelo (cerca de 87%).

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 acurácia, os falsos positivos e os falsos negativos. Nesse caso, a acurácia é maior em torno de um limite de 0,55.

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

f3f1858d627d57ab.png

Agora você vai ver 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. Confira a acurácia, a taxa de falsos positivos e falsos negativos entre as duas partes para procurar diferenças na performance.

Se você expandir as linhas para analisar as matrizes de confusão, vai notar que o modelo prevê "aprovado" para cerca de 70% dos pedidos 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):

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 nas duas partes. O que isso faz com a acurácia, 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 recurso no conjunto de dados:

48ab3c4879793324.png

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

Descrevemos apenas algumas ideias de análise detalhada da Ferramenta What-If aqui. Continue testando a ferramenta. Há muitas outras áreas para explorar.

8. Limpeza

Se você quiser continuar usando esse notebook, recomendamos que o desative quando não estiver em uso. Na interface de Notebooks no console do Cloud, selecione o notebook e clique em Parar:

879147427150b6c7.png

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

No menu de navegação do console do Cloud, acesse "Storage" e exclua os dois buckets criados para armazenar os recursos do modelo.