Anteriormente introduzimos os conceitos fundamentais dos Support Vector Machines. Analogamente, agora exploraremos sua aplicação específica para problemas de classificação, que é uma das utilizações mais comuns e bem-sucedidas desses algoritmos.
Fundamentos da Classificação com SVM
Primordialmente, o SVC (Support Vector Classification) é a implementação do scikit-learn para problemas de classificação. Decerto, seu objetivo é encontrar o hiperplano ótimo que separa as classes com a maior margem possível.
Conforme a documentação, o SVC suporta tanto classificação binária quanto multiclasse através da abordagem “one-vs-one”. Similarmente, para problemas linearmente separáveis, o algoritmo busca maximizar a margem entre as classes.
Formulação Matemática
Para dados linearmente separáveis, o problema de otimização é formulado como:
\(\min_{w,b} \frac{1}{2}||w||^2\)Sujeito a:
\(y_i(w \cdot x_i + b) \geq 1, \quad \forall i\)Para dados não linearmente separáveis, introduzimos variáveis de folga:
\(\min_{w,b,\xi} \frac{1}{2}||w||^2 + C\sum_{i=1}^n \xi_i\)Sujeito a:
\(y_i(w \cdot x_i + b) \geq 1 – \xi_i, \quad \xi_i \geq 0\)Implementações Disponíveis
Atualmente, o scikit-learn oferece três implementações principais para classificação:
- SVC: Implementação versátil baseada no libsvm
- NuSVC: Similar ao SVC mas com parâmetro ν controlando o número de vetores de suporte
- LinearSVC: Implementação otimizada para classificação linear
Diferenças entre SVC e LinearSVC
Inegavelmente, compreender as diferenças entre essas implementações é crucial:
- SVC: Suporta kernels não-lineares, usa one-vs-one para multiclasse
- LinearSVC: Mais escalável, usa one-vs-rest para multiclasse
- NuSVC: Controla diretamente o número de vetores de suporte
Parâmetros Principais
Conquanto existam muitos parâmetros, alguns são particularmente importantes:
- C: Parâmetro de regularização que controla o trade-off entre margem e erro
- kernel: Tipo de função do kernel (linear, rbf, poly, sigmoid)
- gamma: Coeficiente para kernels rbf, poly e sigmoid
- degree: Grau do kernel polinomial
Exemplo Prático: Classificação com Diferentes Kernels
Ademais, vejamos um exemplo completo de classificação utilizando diferentes abordagens:
|
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 |
''' Classificação com Support Vector Machines Este exemplo demonstra o uso do SVC para problemas de classificação binária e multiclasse ''' import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.svm import SVC, LinearSVC from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.preprocessing import StandardScaler from sklearn.metrics import classification_report, confusion_matrix, accuracy_score # Carregar dataset Iris para classificação multiclasse iris = datasets.load_iris() X = iris.data y = iris.target target_names = iris.target_names print("Dataset Iris - Informações:") print(f"Número de amostras: {X.shape[0]}") print(f"Número de features: {X.shape[1]}") print(f"Classes: {target_names}") print(f"Distribuição das classes: {np.bincount(y)}") # Dividir em treino e teste X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y) # Normalizar os dados scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) print(f"\nDimensões: Treino {X_train.shape}, Teste {X_test.shape}") ''' Comparação de diferentes kernels para classificação Cada kernel tem características distintas que podem ser mais adequadas para diferentes tipos de dados ''' kernels = ['linear', 'rbf', 'poly'] results = {} for kernel in kernels: print(f"\n--- Treinando SVC com kernel {kernel} ---") if kernel == 'poly': svc = SVC(kernel=kernel, degree=3, random_state=42) else: svc = SVC(kernel=kernel, random_state=42) # Treinar modelo svc.fit(X_train_scaled, y_train) # Fazer previsões y_pred = svc.predict(X_test_scaled) # Calcular acurácia accuracy = accuracy_score(y_test, y_pred) # Armazenar resultados results[kernel] = { 'model': svc, 'accuracy': accuracy, 'n_support_vectors': len(svc.support_vectors_) } print(f"Acurácia: {accuracy:.3f}") print(f"Vetores de suporte: {len(svc.support_vectors_)}") print(f"Distribuição por classe: {np.bincount(svc.n_support_)}") # Comparação com LinearSVC print("\n--- Comparação com LinearSVC ---") linear_svc = LinearSVC(random_state=42, max_iter=10000) linear_svc.fit(X_train_scaled, y_train) y_pred_linear = linear_svc.predict(X_test_scaled) accuracy_linear = accuracy_score(y_test, y_pred_linear) print(f"LinearSVC Acurácia: {accuracy_linear:.3f}") # Otimização de hiperparâmetros com GridSearchCV print("\n--- Otimização de Hiperparâmetros com GridSearchCV ---") param_grid = { 'C': [0.1, 1, 10, 100], 'gamma': ['scale', 'auto', 0.1, 0.01], 'kernel': ['rbf', 'linear'] } grid_search = GridSearchCV(SVC(random_state=42), param_grid, cv=5, scoring='accuracy', n_jobs=-1) grid_search.fit(X_train_scaled, y_train) print(f"Melhores parâmetros: {grid_search.best_params_}") print(f"Melhor score na validação: {grid_search.best_score_:.3f}") # Modelo final com melhores parâmetros best_svc = grid_search.best_estimator_ y_pred_best = best_svc.predict(X_test_scaled) final_accuracy = accuracy_score(y_test, y_pred_best) print(f"Acurácia final no teste: {final_accuracy:.3f}") # Relatório de classificação detalhado print("\n--- Relatório de Classificação Detalhado ---") print(classification_report(y_test, y_pred_best, target_names=target_names)) # Matriz de confusão cm = confusion_matrix(y_test, y_pred_best) print("\nMatriz de Confusão:") print(cm) # Visualização dos resultados (para duas primeiras features) plt.figure(figsize=(15, 5)) # Plot dos dados originais plt.subplot(1, 3, 1) for i, target_name in enumerate(target_names): plt.scatter(X[y == i, 0], X[y == i, 1], label=target_name, alpha=0.7) plt.xlabel('Comprimento da Sépala') plt.ylabel('Largura da Sépala') plt.title('Dados Originais - Iris Dataset') plt.legend() # Plot das previsões plt.subplot(1, 3, 2) for i, target_name in enumerate(target_names): mask = (y_pred_best == i) plt.scatter(X_test[mask, 0], X_test[mask, 1], label=target_name, alpha=0.7) plt.xlabel('Comprimento da Sépala') plt.ylabel('Largura da Sépala') plt.title('Previsões do Modelo') plt.legend() # Plot de comparação de acurácias plt.subplot(1, 3, 3) methods = list(results.keys()) + ['LinearSVC', 'Otimizado'] accuracies = [results[k]['accuracy'] for k in kernels] + [accuracy_linear, final_accuracy] plt.bar(methods, accuracies, color=['skyblue', 'lightcoral', 'lightgreen', 'gold', 'violet']) plt.xticks(rotation=45) plt.ylabel('Acurácia') plt.title('Comparação de Acurácias por Método') plt.ylim(0, 1) plt.tight_layout() plt.show() # Análise final print(f"\n--- Resumo Final ---") print(f"Melhor método: {grid_search.best_params_['kernel']} kernel") print(f"Acurácia final: {final_accuracy:.3f}") print(f"Total de vetores de suporte: {len(best_svc.support_vectors_)}") print(f"Percentual de vetores de suporte: {len(best_svc.support_vectors_)/len(X_train)*100:.1f}%") |
Casos de Uso e Recomendações
Embora o SVC seja versátil, algumas recomendações práticas são importantes:
Quando Usar SVC
- Problemas com limites de decisão complexos
- Quando o número de features é maior que o número de amostras
- Para problemas que requerem alta generalização
- Quando se tem recursos computacionais suficientes
Quando Preferir LinearSVC
- Datasets muito grandes
- Problemas linearmente separáveis
- Quando a velocidade é crucial
- Para problemas com muitas features
Considerações sobre Multiclasse
O scikit-learn implementa duas estratégias para classificação multiclasse:
- one-vs-one: Treina um classificador para cada par de classes (usado no SVC)
- one-vs-rest: Treina um classificador por classe contra todas as outras (usado no LinearSVC)
Enfim, a classificação com Support Vector Machines oferece uma abordagem robusta e flexível para diversos tipos de problemas, desde os mais simples até os mais complexos, sempre buscando a melhor generalização possível.
Referência: https://scikit-learn.org/0.21/modules/svm.html#classification