Este guia demonstra um fluxo de trabalho completo para a análise de explicabilidade de um modelo de classificação usando a biblioteca SHAP, focando na previsão de inadimplência de crédito.
1. Pré-processamento de Dados
Os dados são carregados e transformados. Variáveis categóricas são codificadas usando mapeamento de rótulos e one-hot encoding, e valores ausentes em características contínuas são preenchidos com a moda.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")
# Configurar fonte para suporte a caracteres acentuados
plt.rcParams['font.sans-serif'] = ['DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
# Carregar o conjunto de dados
credit_data = pd.read_csv('credit_data.csv')
# Codificação de rótulos para características ordinais
posse_mapeamento = {'Própria Casa': 1, 'Aluguel': 2, 'Hipoteca': 3, 'Empréstimo Casa': 4}
credit_data['Posse Moradia'] = credit_data['Posse Moradia'].map(posse_mapeamento)
tempo_emprego_mapeamento = {
'Menos de 1 ano': 1, '1 ano': 2, '2 anos': 3, '3 anos': 4,
'4 anos': 5, '5 anos': 6, '6 anos': 7, '7 anos': 8,
'8 anos': 9, '9 anos': 10, '10+ anos': 11
}
credit_data['Anos no Emprego'] = credit_data['Anos no Emprego'].map(tempo_emprego_mapeamento)
# One-Hot Encoding para a característica 'Finalidade'
credit_data_encoded = pd.get_dummies(credit_data, columns=['Finalidade'])
# Converter colunas booleanas do one-hot encoding para inteiro
colunas_originais = credit_data.columns.tolist()
novas_colunas_onehot = [col for col in credit_data_encoded.columns if col not in colunas_originais]
for col in novas_colunas_onehot:
credit_data_encoded[col] = credit_data_encoded[col].astype(int)
# Mapeamento binário para 'Prazo'
prazo_mapeamento = {'Curto Prazo': 0, 'Longo Prazo': 1}
credit_data_encoded['Prazo'] = credit_data_encoded['Prazo'].map(prazo_mapeamento)
credit_data_encoded = credit_data_encoded.rename(columns={'Prazo': 'Longo Prazo'})
# Identificar e preencher características numéricas
colunas_numericas = credit_data_encoded.select_dtypes(include=['int64', 'float64']).columns.tolist()
for caracteristica in colunas_numericas:
valor_mais_frequente = credit_data_encoded[caracteristica].mode()[0]
credit_data_encoded[caracteristica].fillna(valor_mais_frequente, inplace=True)
2. Treinamento do Modelo
Os dados são divididos em conjuntos de treino e teste. Um modelo de floresta aleatória é treinado e avaliado usando métricas de classificação padrão.
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
import time
# Separar características (X) e rótulo (y)
X = credit_data_encoded.drop(['Inadimplencia'], axis=1)
y = credit_data_encoded['Inadimplencia']
# Dividir os dados (80% treino, 20% teste)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.20, random_state=2024
)
# Treinar e avaliar o modelo com parâmetros padrão
print("--- Avaliando Modelo de Floresta Aleatória Padrão ---")
inicio = time.time()
modelo_rf = RandomForestClassifier(random_state=2024)
modelo_rf.fit(X_train, y_train)
previsoes = modelo_rf.predict(X_test)
fim = time.time()
print(f"Tempo de treinamento e predição: {fim - inicio:.2f} segundos")
print("\nRelatório de Classificação no Conjunto de Teste:")
print(classification_report(y_test, previsoes))
print("Matriz de Confusão:")
print(confusion_matrix(y_test, previsoes))
3. Análise de Explicabilidade com SHAP
A biblioteca SHAP é usada para calcular os valores SHAP, que quantificam a contribuição de cada característica para as previsões do modelo.
import shap
# Inicializar o explicador SHAP para modelos baseados em árvores
explicador_shap = shap.TreeExplainer(modelo_rf)
# Calcular os valores SHAP para o conjunto de teste
# O resultado é uma lista de arrays, um para cada classe no problema de classificação
valores_shap = explicador_shap.shap_values(X_test)
print(f"Formato dos valores SHAP para a classe 0: {valores_shap[0].shape}")
print(f"Formato das características de teste: {X_test.shape}")
4. Visualização dos Resultados SHAP
Diferentes tipos de gráficos fornecem insights sobre a importância e o impacto das características.
# 1. Gráfico de Barras: Importância global das características
shap.summary_plot(valores_shap[0], X_test, plot_type="bar", show=False)
plt.title("Importância das Características (Gráfico de Barras SHAP)")
plt.tight_layout()
plt.show()
# 2. Gráfico de Violino (Beeswarm): Distribuição e impacto dos valores SHAP
shap.summary_plot(valores_shap[0], X_test, plot_type="violin", max_display=10, show=False)
plt.title("Distribuição do Impacto das Características (Gráfico Violino SHAP)")
plt.tight_layout()
plt.show()
# 3. Gráfico de Dependência: Relação entre uma característica e seu impacto SHAP
shap.dependence_plot('Anos no Emprego', valores_shap[0], X_test, show=False)
plt.title("Relação de Dependência para 'Anos no Emprego'")
plt.tight_layout()
plt.show()