1
resposta

Minha Solução da aula de validação de modelos, métricas de avaliação

# 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()
1 resposta

E aí, Paulo! Tudo bem?

Parabéns! Mantenha o ritmo nos exercícios e continue compartilhando na nossa comunidade.

Percebi que você praticou o uso da árvore de decisão, aplicou muito bem o controle do limiar de decisão para ajustar o balanceamento (entre precisão e recall) e ainda entendeu a relevância de analisar as curvas Precision-Recall e ROC para avaliar classificadores.

Permaneça postando as suas soluções, com certeza isso ajudará outros estudantes e tem grande relevância para o fórum.

Ícone de sugestão Para saber mais:

Sugestão de conteúdo para você mergulhar ainda mais sobre o tema:

Fico à disposição! E se precisar, conte sempre com o apoio do fórum.

Abraço e bons estudos!

AluraConte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!