# Importação de bibliotecas
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import (
accuracy_score, confusion_matrix, classification_report,
precision_score, recall_score, f1_score,
average_precision_score, precision_recall_curve,
RocCurveDisplay, PrecisionRecallDisplay
)
# --- 1. Carregamento e exploração inicial dos dados ---
dados = pd.read_csv('/content/emp_automovel.csv')
# Separar features e target
X = dados.drop('inadimplente', axis=1)
y = dados['inadimplente']
print(f'X: {X.shape}, y: {y.shape}')
print("\nInformações do dataset:")
dados.info()
print("\nExemplo de dados:")
print(dados.head())
print("\nEstatísticas descritivas:")
print(dados.describe(include='all'))
assert len(X) == len(y), "X e y devem ter o mesmo número de amostras!"
# --- 2. Divisão treino/teste ---
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42
)
print(f'\nShape Treino: {X_train.shape}, {y_train.shape}')
print(f'Shape Teste: {X_test.shape}, {y_test.shape}')
# --- 3. Treinamento do modelo ---
modelo = DecisionTreeClassifier(max_depth=10, random_state=42)
modelo.fit(X_train, y_train)
# --- 4. Avaliação no conjunto teste ---
y_pred = modelo.predict(X_test)
y_proba = modelo.predict_proba(X_test)[:, 1] # Probabilidades da classe positiva
print(f'\nAcurácia no teste: {accuracy_score(y_test, y_pred):.2%}')
print(f'Average Precision Score: {average_precision_score(y_test, y_proba):.4f}')
# --- 5. Curva Precisão x Recall por limiar ---
precisions, recalls, thresholds = precision_recall_curve(y_test, y_proba)
# Ajustar thresholds para plot (precisions e recalls têm +1 elemento)
thresholds = np.append(thresholds, 1.0)
plt.figure(figsize=(10,6))
plt.plot(thresholds, precisions, label='Precisão', color='blue')
plt.plot(thresholds, recalls, label='Recall', color='green')
plt.xlabel('Limiar de Decisão')
plt.ylabel('Métrica')
plt.title('Precisão e Recall por Limiar de Decisão')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# --- 6. Encontrar melhor limiar com precisão >= 10% e maior recall ---
precisao_minima = 0.10
indices_validos = np.where(precisions[:-1] >= precisao_minima)[0]
if len(indices_validos) > 0:
melhor_indice = indices_validos[np.argmax(recalls[indices_validos])]
melhor_limiar = thresholds[melhor_indice]
print(f'\nMelhor limiar com precisão >= {precisao_minima*100:.0f}%: {melhor_limiar:.3f}')
print(f'Precisão: {precisions[melhor_indice]:.2%}')
print(f'Recall: {recalls[melhor_indice]:.2%}')
else:
print(f'\nNenhum limiar encontrado com precisão >= {precisao_minima*100:.0f}%')
# --- 7. Aplicar limiar personalizado e reavaliar ---
y_pred_custom = (y_proba >= melhor_limiar).astype(int)
conf_matrix = confusion_matrix(y_test, y_pred_custom)
print('\nMatriz de Confusão (limiar personalizado):')
print(conf_matrix)
plt.figure(figsize=(6,5))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
xticklabels=['Adimplente', 'Inadimplente'],
yticklabels=['Adimplente', 'Inadimplente'])
plt.xlabel('Previsto')
plt.ylabel('Real')
plt.title(f'Matriz de Confusão (limiar = {melhor_limiar:.3f})')
plt.tight_layout()
plt.show()
print('\nRelatório de Classificação (limiar personalizado):')
print(classification_report(y_test, y_pred_custom, target_names=['Adimplente', 'Inadimplente']))
# --- 8. Métricas detalhadas com limiar padrão (0.5) e personalizado ---
print(f'=== Métricas com limiar padrão (0.5) ===')
print(f'Precisão: {precision_score(y_test, y_pred):.2%}')
print(f'Recall: {recall_score(y_test, y_pred):.2%}')
print(f'F1-score: {f1_score(y_test, y_pred):.2%}')
print(f'\n=== Métricas com limiar personalizado ({melhor_limiar:.3f}) ===')
print(f'Precisão: {precision_score(y_test, y_pred_custom):.2%}')
print(f'Recall: {recall_score(y_test, y_pred_custom):.2%}')
print(f'F1-score: {f1_score(y_test, y_pred_custom):.2%}')
# --- 9. Curvas ROC e Precision-Recall com limiar padrão ---
plt.figure(figsize=(8,6))
RocCurveDisplay.from_predictions(y_test, y_proba, name='Decision Tree');
plt.title('Curva ROC - Árvore de Decisão')
plt.grid(True)
plt.show()
plt.figure(figsize=(8,6))
PrecisionRecallDisplay.from_predictions(y_test, y_proba, name='Decision Tree');
plt.title('Curva Precision-Recall - Árvore de Decisão')
plt.grid(True)
plt.show()