1 – Aprendizado de Maquina
1.1.2 – Classificacao
1.1.2.1 – Binaria
LEGENDA
Principal
Ramo
Metodo
Problemas
Modelo
Arquitetura
Duas opções, uma decisão
Classificação binária é a forma mais simples de classificação, com apenas duas categorias possíveis. O modelo decide entre duas classes mutuamente exclusivas como “sim” ou “não”. Por exemplo, determinar se um e-mail é spam ou não spam. Primeiramente, essa simplicidade torna a classificação binária ideal para iniciantes. Além disso, muitos problemas complexos podem ser decompostos em múltiplos problemas binários. A saída geralmente representa a probabilidade de pertencer à classe positiva. É o ponto de partida fundamental para entender classificação supervisionada.Limiar de decisão e probabilidades
A maioria dos classificadores binários produz uma probabilidade entre 0 e 1 como saída. Primeiramente, o limiar padrão é 0,5: acima disso classe positiva, abaixo classe negativa. Além disso, podemos ajustar esse limiar para diferentes necessidades operacionais. Por exemplo, em diagnósticos médicos, preferimos um limiar mais baixo para não perder casos. Limiares mais altos produzem menos falsos positivos, mas podem perder casos verdadeiros. A curva ROC mostra o desempenho do modelo em todos os limiares possíveis. A escolha do limiar reflete o equilíbrio entre diferentes tipos de erro.Métricas essenciais para problemas binários
Avaliar classificadores binários exige métricas que capturam os diferentes tipos de erro possíveis. A matriz de confusão organiza resultados em quatro categorias: VP, VN, FP, FN. Primeiramente, verdadeiros positivos (VP) são acertos na classe positiva. Verdadeiros negativos (VN) são acertos na classe negativa. Além disso, falsos positivos (FP) são erros do tipo alarme falso. Falsos negativos (FN) são erros onde o modelo perdeu casos positivos. Precisão e recall derivam dessas quantidades para avaliação detalhada. F1-score combina precisão e recall em uma única métrica balanceada.Desbalanceamento de classes
Problemas binários frequentemente sofrem com desbalanceamento entre as duas classes. Por exemplo, fraudes representam menos de 1% das transações bancárias. Primeiramente, um modelo que sempre prevê “não fraude” tem acurácia de 99%. Além disso, métricas como acurácia se tornam enganosas em dados desbalanceados. Técnicas como sobreamostragem (oversampling) criam cópias da classe minoritária. Subamostragem (undersampling) reduz exemplos da classe majoritária para equilíbrio. Algoritmos sensíveis a custo atribuem pesos diferentes para cada classe. O desbalanceamento exige cuidado especial na avaliação e treinamento do modelo.Aplicações práticas da classificação binária
Classificação binária está presente em sistemas críticos que exigem decisões rápidas. Primeiramente, detecção de fraudes analisa transações bancárias em tempo real. Além disso, diagnóstico médico classifica exames como normais ou alterados. Sistemas de segurança usam classificação binária para reconhecimento facial autorizado. Filtros de conteúdo identificam comentários ofensivos ou apropriados para publicação. Na indústria, sistemas inspecionam produtos como “defeituoso” ou “sem defeitos”. Para iniciantes, classificação binária oferece aplicações práticas imediatas e compreensíveis. É a base sobre a qual muitos sistemas inteligentes realizam decisões críticas.Descrição do Problema
Este é um problema clássico de Aprendizado de Máquina Supervisionado onde o objetivo é classificar tumores de mama como Malignos (cancerígenos) ou Benignos (não cancerígenos) com base em características extraídas de imagens de exames.🎯 Objetivo: Construir um modelo preditivo que possa auxiliar médicos no diagnóstico precoce de câncer de mama, identificando automaticamente se um tumor é maligno ou benigno com alta precisão.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# -*- coding: utf-8 -*- """Classificação Binária - Câncer de Mama Este é um exemplo clássico de aprendizado de máquina supervisionado para classificação binária (tumor maligno vs benigno) """ # 1. IMPORTAÇÕES NECESSÁRIAS import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import (accuracy_score, classification_report, confusion_matrix, roc_curve, auc, roc_auc_score) import warnings warnings.filterwarnings('ignore') # Configurações de visualização plt.style.use('seaborn-v0_8-darkgrid') sns.set_palette("husl") print("="*60) print("CLASSIFICAÇÃO BINÁRIA - DIAGNÓSTICO DE CÂNCER DE MAMA") print("="*60) # 2. CARREGAR E EXPLORAR OS DADOS print("\n📊 Carregando dataset...") data = load_breast_cancer() X = pd.DataFrame(data.data, columns=data.feature_names) y = pd.Series(data.target, name='target') print(f"\n✅ Dataset carregado com sucesso!") print(f" - Total de amostras: {X.shape[0]}") print(f" - Total de features: {X.shape[1]}") print(f" - Classes: {data.target_names}") print(f" - Distribuição das classes:") print(f" • Maligno (0): {sum(y==0)} amostras") print(f" • Benigno (1): {sum(y==1)} amostras") # 3. ANÁLISE EXPLORATÓRIA BÁSICA print("\n📈 Análise Exploratória...") # Verificando valores missing print(f"\n Valores missing: {X.isnull().sum().sum()}") # Estatísticas descritivas print("\n Estatísticas descritivas das primeiras 5 features:") print(X.iloc[:, :5].describe().round(2)) # 4. PRÉ-PROCESSAMENTO print("\n🔧 Pré-processamento dos dados...") # Separar features (X) e target (y) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) print(f" Dados de treino: {X_train.shape[0]} amostras") print(f" Dados de teste: {X_test.shape[0]} amostras") # Padronizar os dados (Standardization) scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) print(" ✅ Dados padronizados (média=0, desvio=1)") # 5. TREINAMENTO DO MODELO print("\n🤖 Treinando modelo Random Forest...") # Criar e treinar o modelo rf_model = RandomForestClassifier( n_estimators=100, max_depth=10, random_state=42, n_jobs=-1 ) rf_model.fit(X_train_scaled, y_train) print(" ✅ Modelo treinado com sucesso!") # 6. AVALIAÇÃO DO MODELO print("\n📊 Avaliação do modelo...") # Predições y_pred = rf_model.predict(X_test_scaled) y_pred_proba = rf_model.predict_proba(X_test_scaled)[:, 1] # Métricas accuracy = accuracy_score(y_test, y_pred) roc_auc = roc_auc_score(y_test, y_pred_proba) print(f"\n 📈 Métricas no conjunto de teste:") print(f" • Acurácia: {accuracy:.4f}") print(f" • ROC-AUC: {roc_auc:.4f}") # Validação cruzada cv_scores = cross_val_score(rf_model, X_train_scaled, y_train, cv=5) print(f" • Validação cruzada (5-fold): {cv_scores.mean():.4f} (±{cv_scores.std():.4f})") # Relatório de classificação detalhado print("\n 📋 Relatório de Classificação:") print(classification_report(y_test, y_pred, target_names=data.target_names)) # 7. VISUALIZAÇÕES print("\n🎨 Gerando visualizações...") fig, axes = plt.subplots(2, 2, figsize=(14, 10)) # Matriz de Confusão cm = confusion_matrix(y_test, y_pred) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[0, 0], xticklabels=data.target_names, yticklabels=data.target_names) axes[0, 0].set_title('Matriz de Confusão', fontsize=14, fontweight='bold') axes[0, 0].set_xlabel('Predito') axes[0, 0].set_ylabel('Real') # Curva ROC fpr, tpr, _ = roc_curve(y_test, y_pred_proba) roc_auc = auc(fpr, tpr) axes[0, 1].plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (AUC = {roc_auc:.3f})') axes[0, 1].plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') axes[0, 1].set_xlim([0.0, 1.0]) axes[0, 1].set_ylim([0.0, 1.05]) axes[0, 1].set_xlabel('False Positive Rate') axes[0, 1].set_ylabel('True Positive Rate') axes[0, 1].set_title('Curva ROC', fontsize=14, fontweight='bold') axes[0, 1].legend(loc="lower right") # Importância das Features feature_importance = pd.DataFrame({ 'feature': data.feature_names, 'importance': rf_model.feature_importances_ }).sort_values('importance', ascending=False).head(10) axes[1, 0].barh(feature_importance['feature'], feature_importance['importance']) axes[1, 0].set_xlabel('Importância') axes[1, 0].set_title('Top 10 Features Mais Importantes', fontsize=14, fontweight='bold') axes[1, 0].invert_yaxis() # Distribuição das probabilidades preditas axes[1, 1].hist(y_pred_proba[y_test==0], bins=20, alpha=0.7, label='Maligno (Real)', color='red') axes[1, 1].hist(y_pred_proba[y_test==1], bins=20, alpha=0.7, label='Benigno (Real)', color='green') axes[1, 1].set_xlabel('Probabilidade de Ser Benigno') axes[1, 1].set_ylabel('Frequência') axes[1, 1].set_title('Distribuição das Probabilidades', fontsize=14, fontweight='bold') axes[1, 1].legend() plt.tight_layout() plt.show() # 8. OTIMIZAÇÃO DE HIPERPARÂMETROS (Opcional) print("\n🔍 Otimizando hiperparâmetros...") param_grid = { 'n_estimators': [50, 100, 200], 'max_depth': [5, 10, 15, None], 'min_samples_split': [2, 5, 10] } grid_search = GridSearchCV( RandomForestClassifier(random_state=42), param_grid, cv=5, scoring='roc_auc', n_jobs=-1, verbose=0 ) grid_search.fit(X_train_scaled, y_train) print(f" ✅ Melhores parâmetros: {grid_search.best_params_}") print(f" ✅ Melhor score (validação cruzada): {grid_search.best_score_:.4f}") # Avaliar modelo otimizado best_model = grid_search.best_estimator_ y_pred_optimized = best_model.predict(X_test_scaled) accuracy_optimized = accuracy_score(y_test, y_pred_optimized) print(f"\n 📈 Comparação com modelo otimizado:") print(f" • Acurácia original: {accuracy:.4f}") print(f" • Acurácia otimizada: {accuracy_optimized:.4f}") # 9. EXEMPLO DE PREDIÇÃO PARA UM NOVO CASO print("\n💡 Exemplo de predição para um novo paciente:") # Usar a primeira amostra do teste como exemplo sample_index = 0 sample = X_test_scaled[sample_index].reshape(1, -1) sample_original = X_test.iloc[sample_index] true_label = y_test.iloc[sample_index] prediction = best_model.predict(sample)[0] probability = best_model.predict_proba(sample)[0] print(f"\n Características do paciente (parciais):") print(f" • Raio médio: {sample_original['mean radius']:.2f}") print(f" • Textura média: {sample_original['mean texture']:.2f}") print(f" • Perímetro médio: {sample_original['mean perimeter']:.2f}") print(f" • Área média: {sample_original['mean area']:.2f}") print(f"\n 🩺 Diagnóstico REAL: {data.target_names[true_label]}") print(f" 🤖 Diagnóstico PREDITO: {data.target_names[prediction]}") print(f" 📊 Confiança da predição:") print(f" • Probabilidade de ser maligno: {probability[0]:.2%}") print(f" • Probabilidade de ser benigno: {probability[1]:.2%}") # 10. CONCLUSÃO print("\n" + "="*60) print("✅ PROCESSO CONCLUÍDO COM SUCESSO!") print("="*60) print("\n📚 RESUMO DO PIPELINE:") print("1. ✅ Carregamento e exploração dos dados") print("2. ✅ Análise exploratória") print("3. ✅ Pré-processamento (padronização)") print("4. ✅ Treinamento (Random Forest)") print("5. ✅ Avaliação (acurácia, ROC-AUC, matriz de confusão)") print("6. ✅ Otimização de hiperparâmetros") print("7. ✅ Predição para novos casos") print("\n🎯 Este é um fluxo de trabalho completo para classificação binária!") |
Dataset – Breast Cancer Wisconsin
O dataset contém 569 amostras de tumores de mama, cada uma descrita por 30 características numéricas calculadas a partir de imagens digitalizadas.
Distribuição das Classes
🔴 Maligno (0): 212 amostras (37.3%) 🟢 Benigno (1): 357 amostras (62.7%)Tipos de Features
• Raio (radius) • Textura (texture) • Perímetro (perimeter) • Área (area) • Suavidade (smoothness) • Compacidade (compactness) • Concavidade (concavity) • Simetria (symmetry)Arquitetura do Modelo
Utilizamos o algoritmo Random Forest Classifier, um método ensemble que combina múltiplas árvores de decisão para obter predições mais robustas e precisas.RandomForestClassifier(
n_estimators=100, # Número de árvores na floresta
max_depth=10, # Profundidade máxima das árvores
random_state=42, # Seed para reprodutibilidade
n_jobs=-1 # Usa todos os processadores
)
Pipeline de Processamento
1️⃣ Pré-processamento
• Padronização dos dados (StandardScaler) • Média = 0, Desvio Padrão = 1 • Divisão treino/teste (80/20)2️⃣ Treinamento
• Random Forest com 100 árvores • Validação cruzada (5-fold) • GridSearch para otimização3️⃣ Avaliação
• Acurácia • ROC-AUC • Matriz de Confusão • Relatório de Classificação⚙️ Hiperparâmetros do Modelo
Hiperparâmetros Principais:
| Hiperparâmetro | Valor Padrão | Valor Otimizado | Descrição |
|---|---|---|---|
| n_estimators | 100 | 200 | Número de árvores de decisão na floresta |
| max_depth | 10 | 15 | Profundidade máxima de cada árvore |
| min_samples_split | 2 | 5 | Número mínimo de amostras para dividir um nó |
| min_samples_leaf | 1 | 2 | Número mínimo de amostras em um nó folha |
| max_features | ‘sqrt’ | ‘sqrt’ | Número de features para melhor divisão |
GridSearch – Espaço de Busca:
param_grid = {
‘n_estimators’: [50, 100, 200], # Número de árvores
‘max_depth’: [5, 10, 15, None], # Profundidade das árvores
‘min_samples_split’: [2, 5, 10] # Amostras para divisão
}
📈 Métricas de Avaliação
✅ Acurácia
Proporção de predições corretas:(VP + VN) / (VP + VN + FP + FN)
Resultado esperado: ~96-98%
📊 ROC-AUC
Capacidade de distinguir entre classes: Área sob a curva ROC Resultado esperado: ~0.99🎯 Precisão (Precision)
Taxa de verdadeiros positivos entre os preditos positivos:VP / (VP + FP)
📐 Recall (Sensibilidade)
Capacidade de encontrar todos os positivos:VP / (VP + FN)