scikit-learn

ScikitLearn

Tutorial ScikitLearn: Clasificación SVM con SVC

Scikit Learn y Máquinas de Soporte Vectorial SVM SVC: Domina la clasificación con SVC en Python, cubriendo teoría, preprocesamiento, modelado y ajustes para mejorar tus modelos de aprendizaje automático.

Aprende ScikitLearn GRATIS y certifícate

Introducción teórica a SVM para clasificación

Las Máquinas de Soporte Vectorial (SVM, por sus siglas en inglés) son algoritmos de aprendizaje supervisado utilizados para tareas de clasificación y regresión. En el contexto de la clasificación, las SVM buscan encontrar el hiperplano óptimo que maximiza el margen entre las clases en un espacio de características.

El concepto clave detrás de las SVM es la idea de que el mejor hiperplano separador es aquel que deja el mayor margen posible entre las muestras de diferentes clases. Este margen se define como la distancia más corta entre el hiperplano y los puntos más cercanos de cada clase, conocidos como vectores de soporte. Al maximizar este margen, se obtiene un modelo más generalizable y con mejor capacidad de generalización ante datos no vistos.

Matemáticamente, el objetivo es resolver un problema de optimización que minimiza la norma del vector de pesos $\mathbf{w}$, sujeto a restricciones que aseguran la correcta clasificación de las muestras:

$$
\min_{\mathbf{w}, b} \frac{1}{2} |\mathbf{w}|^2 \quad \text{sujeto a} \quad y_i(\mathbf{w}^\top \mathbf{x}_i + b) \geq 1, \quad \forall i
$$

Donde $\mathbf{x}_i$ son las muestras de entrenamiento, $y_i$ son las etiquetas correspondientes y $b$ es el sesgo.

En situaciones donde los datos no son linealmente separables, se introducen variables de holgura (slack variables) para permitir ciertos errores de clasificación. Esto conduce al SVM de margen suave, que equilibra la maximización del margen y la minimización de errores mediante un parámetro de regularización $C$. Este parámetro $C$ controla la compensación entre un margen amplio y un menor error de clasificación.

Otra característica fundamental de las SVM es el uso del truco del núcleo (kernel trick), que permite manejar relaciones no lineales entre las variables. Al aplicar una función de núcleo adecuada, los datos se proyectan a un espacio de mayor dimensionalidad donde pueden ser linealmente separables. Algunos de los núcleos más comunes son:

  • Núcleo lineal: adecuado cuando los datos son aproximadamente linealmente separables.
  • Núcleo polinómico: permite modelar relaciones polinomiales de grado especificado.
  • Núcleo de base radial (RBF): útil para capturar relaciones complejas y no lineales.

El núcleo RBF es especialmente popular debido a su capacidad para manejar fronteras de decisión no lineales sin aumentar significativamente el coste computacional. La definición del núcleo RBF es:

$$
K(\mathbf{x}_i, \mathbf{x}_j) = \exp\left(-\gamma |\mathbf{x}_i - \mathbf{x}_j|^2\right)
$$

Donde $\gamma$ es un parámetro que determina el alcance de la influencia de una única muestra de entrenamiento. Un valor pequeño de $\gamma$ implica una influencia amplia, mientras que un valor grande implica una influencia reducida.

Para ilustrar cómo las SVM funcionan en la práctica, consideremos un ejemplo sencillo utilizando Scikit-Learn:

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

# Cargar el conjunto de datos Iris
iris = datasets.load_iris()
X = iris.data[:, :2]  # Utilizamos solo dos características para facilitar la visualización
y = iris.target

# Dividir el conjunto de datos en entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)

# Estandarizar las características
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# Crear y entrenar el modelo SVM con un núcleo lineal
svm = SVC(kernel='linear', C=1.0)
svm.fit(X_train, y_train)

# Evaluación del modelo
accuracy = svm.score(X_test, y_test)
print(f'Precisión del modelo: {accuracy:.2f}')

En este código, se utiliza el conjunto de datos Iris, disponible en la librería Scikit-Learn, para entrenar un modelo SVM. Se aplica una escalado estándar a las características, lo cual es importante para que todas las variables contribuyan de manera equitativa al modelo. El modelo utiliza un núcleo lineal y el parámetro $C$ se establece en 1.0, lo que representa un equilibrio entre maximizar el margen y minimizar los errores de clasificación.

Es importante destacar que la elección de los parámetros $C$, $\gamma$ y el tipo de núcleo puede influir significativamente en el desempeño del modelo. Por lo tanto, es común utilizar técnicas de validación cruzada y búsqueda en cuadrícula para encontrar la combinación óptima de hiperparámetros.

Las SVM presentan varias ventajas, como su eficacia en espacios de alta dimensionalidad y su memoria eficiente, ya que solo utilizan un subconjunto de puntos de entrenamiento (vectores de soporte). Sin embargo, también pueden tener desventajas, como un rendimiento reducido en conjuntos de datos muy grandes y sensibilidad a los valores atípicos.

Preprocesados específicos para SVC

El algoritmo Support Vector Classifier (SVC) de Scikit-Learn es particularmente sensible al escalado de las características debido a que se basa en la distancia entre puntos y el producto escalar para construir el hiperplano óptimo de separación. Por ello, es esencial aplicar preprocesamientos específicos antes de entrenar un modelo SVC para asegurar un rendimiento óptimo.

Uno de los pasos fundamentales es la normalización o escalado de las características. Sin un escalado adecuado, las variables con valores numéricos más grandes pueden dominar el cálculo de las distancias y afectar negativamente al modelo. Las técnicas más comunes para el escalado son:

  • Estandarización con StandardScaler: transforma las características para que tengan media cero y desviación estándar uno.
  • Escalado mínimo-máximo con MinMaxScaler: escala las características para que estén en un rango específico, generalmente entre 0 y 1.
  • Escalado robusto con RobustScaler: utiliza la mediana y los cuartiles para reducir el impacto de los valores atípicos.

Por ejemplo, para aplicar StandardScaler:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

Además del escalado, es importante manejar adecuadamente las variables categóricas. Dado que SVC trabaja con datos numéricos, se deben convertir las variables categóricas utilizando técnicas como One-Hot Encoding o Ordinal Encoding. La elección del método dependerá de si las categorías tienen un orden inherente o no.

Para aplicar One-Hot Encoding con OneHotEncoder:

from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer

# Suponiendo que 'categorical_features' es una lista de nombres de columnas categóricas
onehot_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
preprocessor = ColumnTransformer(
    transformers=[
        ('onehot', onehot_encoder, categorical_features)],
    remainder='passthrough')

X_train_encoded = preprocessor.fit_transform(X_train)
X_test_encoded = preprocessor.transform(X_test)

Otra consideración es la reducción de la dimensionalidad en casos donde el número de características es muy grande. Técnicas como Análisis de Componentes Principales (PCA) pueden ayudar a disminuir la dimensionalidad, reduciendo el ruido y mejorando el rendimiento computacional. Sin embargo, es crucial aplicar PCA después del escalado de las características para mantener la coherencia en los datos.

Aplicación de PCA:

from sklearn.decomposition import PCA

pca = PCA(n_components=10)  # Por ejemplo, reducir a 10 componentes principales
X_train_pca = pca.fit_transform(X_train_scaled)
X_test_pca = pca.transform(X_test_scaled)

También es esencial abordar el problema de los datos desbalanceados si las clases no están representadas equitativamente. Métodos como SMOTE (Synthetic Minority Over-sampling Technique) pueden ayudar a equilibrar las clases generando muestras sintéticas de la clase minoritaria.

Uso de SMOTE:

from imblearn.over_sampling import SMOTE

smote = SMOTE(random_state=42)
X_train_balanced, y_train_balanced = smote.fit_resample(X_train_scaled, y_train)

Finalmente, es recomendable realizar una selección de características para eliminar variables irrelevantes o redundantes que puedan afectar negativamente al modelo. Técnicas como SelectKBest o Recursive Feature Elimination (RFE) pueden ser útiles en este contexto.

Ejemplo con SelectKBest:

from sklearn.feature_selection import SelectKBest, f_classif

selector = SelectKBest(score_func=f_classif, k=10)  # Seleccionar las 10 mejores características
X_train_selected = selector.fit_transform(X_train_scaled, y_train)
X_test_selected = selector.transform(X_test_scaled)

En resumen, los preprocesamientos específicos para SVC incluyen:

  • Escalado de las características para asegurar que todas contribuyan equitativamente al modelo.
  • Codificación de variables categóricas a numéricas.
  • Reducción de la dimensionalidad para mejorar la eficiencia y eliminar ruido.
  • Balanceo de clases en caso de datos desbalanceados.
  • Selección de características para identificar las variables más relevantes.

Estos pasos son cruciales para aprovechar al máximo el algoritmo SVC y garantizar resultados precisos y fiables en tareas de clasificación.

Modelado con SVC en Scikit Learn

El Support Vector Classifier (SVC) es una herramienta robusta para tareas de clasificación en Scikit-Learn. Permite construir modelos que separan las clases mediante hiperplanos en espacios de alta dimensionalidad. A continuación, se muestra cómo implementar SVC en un flujo típico de aprendizaje automático.

Primero, es necesario importar las librerías requeridas:

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

A modo de ejemplo, utilizaremos el conjunto de datos Iris, ampliamente conocido en problemas de clasificación:

# Cargar el conjunto de datos Iris
iris = datasets.load_iris()
X = iris.data  # Características
y = iris.target  # Etiquetas

Dividimos los datos en conjuntos de entrenamiento y prueba para evaluar el rendimiento del modelo:

# División de los datos
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y)

Es fundamental escalar las características antes de entrenar el modelo, ya que SVC es sensible a la escala de los datos:

# Escalado de características
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

Procedemos a crear una instancia del modelo SVC. Por defecto, el kernel es 'rbf', pero puede ajustarse según las necesidades:

# Creación del modelo SVC
svc = SVC(kernel='rbf', C=1.0, gamma='scale')

Entrenamos el modelo utilizando el método fit:

# Entrenamiento del modelo
svc.fit(X_train_scaled, y_train)

Una vez entrenado, realizamos predicciones sobre el conjunto de prueba:

# Predicciones
y_pred = svc.predict(X_test_scaled)

Evaluamos el rendimiento del modelo utilizando métricas como la exactitud y el informe de clasificación:

# Evaluación del modelo
accuracy = accuracy_score(y_test, y_pred)
print(f'Exactitud del modelo: {accuracy:.2f}')

print('Informe de clasificación:')
print(classification_report(y_test, y_pred))

print('Matriz de confusión:')
print(confusion_matrix(y_test, y_pred))

El resultado muestra la capacidad del modelo para clasificar correctamente las muestras. La matriz de confusión proporciona información detallada sobre las predicciones correctas e incorrectas.

Para mejorar el rendimiento, es posible ajustar los hiperparámetros utilizando técnicas como la búsqueda en cuadrícula:

from sklearn.model_selection import GridSearchCV

# Definición del rango de hiperparámetros
param_grid = {
    'C': [0.1, 1, 10],
    'gamma': ['scale', 'auto', 0.01, 0.1],
    'kernel': ['rbf', 'linear']
}

# Configuración de GridSearchCV
grid_search = GridSearchCV(SVC(), param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train_scaled, y_train)

# Mejores parámetros encontrados
print('Mejores hiperparámetros:')
print(grid_search.best_params_)

Con los mejores hiperparámetros, se puede reentrenar el modelo:

# Reentrenamiento con los mejores hiperparámetros
best_svc = grid_search.best_estimator_
best_svc.fit(X_train_scaled, y_train)

# Nueva predicción y evaluación
y_pred_best = best_svc.predict(X_test_scaled)
accuracy_best = accuracy_score(y_test, y_pred_best)
print(f'Exactitud con hiperparámetros ajustados: {accuracy_best:.2f}')

Al ajustar los hiperparámetros C y gamma, es posible mejorar la generalización del modelo. El parámetro C controla el equilibrio entre maximizar el margen y minimizar el error de clasificación. Un valor pequeño de C permite un margen más amplio a costa de más errores, mientras que un valor grande de C busca minimizar los errores, pudiendo llevar a un sobreajuste.

El parámetro gamma determina la influencia de cada muestra de entrenamiento. Valores pequeños de gamma implican un alcance amplio, mientras que valores grandes se enfocan en muestras cercanas. Es crucial encontrar un equilibrio adecuado para evitar modelos subajustados o sobreajustados.

En algunos casos, es beneficioso utilizar un pipeline para encapsular los pasos de preprocesamiento y modelado:

from sklearn.pipeline import Pipeline

# Creación del pipeline
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('svc', SVC(kernel='rbf', C=1.0, gamma='scale'))
], memory = None)

# Entrenamiento del pipeline
pipeline.fit(X_train, y_train)

# Predicción y evaluación
y_pred_pipeline = pipeline.predict(X_test)
accuracy_pipeline = accuracy_score(y_test, y_pred_pipeline)
print(f'Exactitud del pipeline: {accuracy_pipeline:.2f}')

El uso de un pipeline garantiza que las transformaciones se apliquen correctamente tanto en el conjunto de entrenamiento como en el de prueba, evitando errores comunes en el preprocesamiento.

Para problemas donde se requiere estimar las probabilidades de pertenencia a cada clase, se puede habilitar el parámetro probability:

# Modelo con probabilidad habilitada
svc_prob = SVC(kernel='rbf', C=1.0, gamma='scale', probability=True)
svc_prob.fit(X_train_scaled, y_train)

# Predicción de probabilidades
probabilities = svc_prob.predict_proba(X_test_scaled)
print('Probabilidades de las clases:')
print(probabilities)

Aunque habilitar probability=True aumenta el tiempo de entrenamiento, proporciona información adicional útil en ciertas aplicaciones, como en análisis de riesgo o cuando se requiere una medida de confianza en las predicciones.

Cuando se trabaja con conjuntos de datos grandes, es recomendable considerar estrategias para reducir el tiempo de cómputo. Por ejemplo, se puede utilizar una muestra representativa de los datos o ajustar parámetros para simplificar el modelo. Opcionalmente, para problemas lineales, el uso de LinearSVC puede ser más eficiente:

from sklearn.svm import LinearSVC

# Modelo utilizando LinearSVC
linear_svc = LinearSVC(C=1.0, max_iter=10000)
linear_svc.fit(X_train_scaled, y_train)

# Predicción y evaluación
y_pred_linear = linear_svc.predict(X_test_scaled)
accuracy_linear = accuracy_score(y_test, y_pred_linear)
print(f'Exactitud con LinearSVC: {accuracy_linear:.2f}')

Es importante tener en cuenta que LinearSVC no soporta el método predict_proba, ya que no calcula probabilidades.

En situaciones donde las clases están desbalanceadas, es esencial manejar este desequilibrio para mejorar el rendimiento del modelo. SVC permite ajustar el parámetro class_weight para penalizar más los errores en la clase minoritaria:

# Modelo con ajuste de pesos de clase
svc_weighted = SVC(kernel='rbf', C=1.0, gamma='scale', class_weight='balanced')
svc_weighted.fit(X_train_scaled, y_train)

# Predicción y evaluación
y_pred_weighted = svc_weighted.predict(X_test_scaled)
accuracy_weighted = accuracy_score(y_test, y_pred_weighted)
print(f'Exactitud con class_weight ajustado: {accuracy_weighted:.2f}')

El uso de class_weight='balanced' ajusta automáticamente los pesos inversamente proporcionales a las frecuencias de las clases en los datos, ayudando a mejorar la sensibilidad en clases minoritarias.

Para finalizar, es buena práctica guardar el modelo entrenado para su posterior uso. Scikit-Learn permite hacerlo mediante la biblioteca joblib:

import joblib

# Guardar el modelo
joblib.dump(best_svc, 'modelo_svc.pkl')

# Cargar el modelo
modelo_cargado = joblib.load('modelo_svc.pkl')

Al almacenar el modelo, se facilita su despliegue en entornos de producción y su reutilización sin necesidad de reentrenamiento.

En resumen, el modelado con SVC en Scikit-Learn es un proceso que involucra preparación de los datos, ajuste de hiperparámetros y evaluación del modelo. Utilizando las herramientas que ofrece la biblioteca, es posible desarrollar modelos de alta calidad para diversas tareas de clasificación.

Parámetros de SVC

El modelo SVC de Scikit-Learn proporciona una amplia variedad de parámetros que permiten ajustar y optimizar el comportamiento de las Máquinas de Vectores de Soporte para tareas de clasificación. A continuación, se detallan los principales parámetros y cómo influencian el modelo.

  • C: Este parámetro es fundamental y controla el grado de penalización que se aplica a los errores de clasificación. Un valor alto de C intenta minimizar los errores de clasificación en el entrenamiento, permitiendo que el modelo se adapte más a los datos, lo que puede conducir a un sobreajuste. Por el contrario, un valor bajo de C busca maximizar el margen entre las clases, tolerando algunos errores de clasificación, lo que puede mejorar la capacidad de generalización del modelo.

Ejemplo de uso ajustando el parámetro C:

from sklearn.svm import SVC

# Modelo con C bajo para maximizar el margen
svc_margen_amplio = SVC(C=0.1)
svc_margen_amplio.fit(X_train_scaled, y_train)

# Modelo con C alto para minimizar errores en el entrenamiento
svc_margen_estrecho = SVC(C=10)
svc_margen_estrecho.fit(X_train_scaled, y_train)
  • kernel: Define la función de núcleo que se utiliza para transformar los datos en un espacio de mayor dimensionalidad. Los valores comunes son 'linear', 'poly', 'rbf', 'sigmoid' y 'precomputed'. El núcleo 'rbf' (Función Radial Básica) es el predeterminado y suele ser una elección adecuada para problemas no lineales. La selección del núcleo apropiado es crucial para el rendimiento del modelo.

Ejemplo de selección de diferentes núcleos:

# Núcleo lineal
svc_lineal = SVC(kernel='linear')
svc_lineal.fit(X_train_scaled, y_train)

# Núcleo polinómico de grado 3
svc_polinomial = SVC(kernel='poly', degree=3)
svc_polinomial.fit(X_train_scaled, y_train)

# Núcleo sigmoide
svc_sigmoide = SVC(kernel='sigmoid')
svc_sigmoide.fit(X_train_scaled, y_train)
  • degree: Especifica el grado del polinomio cuando se utiliza el núcleo polinómico (kernel='poly'). Este parámetro se ignora para otros tipos de núcleo. Aumentar el grado permite capturar relaciones más complejas, pero también puede incrementar el riesgo de sobreajuste.

Ejemplo ajustando el grado del núcleo polinomial:

# Núcleo polinómico de grado 2
svc_poly_grado2 = SVC(kernel='poly', degree=2)
svc_poly_grado2.fit(X_train_scaled, y_train)

# Núcleo polinómico de grado 5
svc_poly_grado5 = SVC(kernel='poly', degree=5)
svc_poly_grado5.fit(X_train_scaled, y_train)
  • gamma: Controla la influencia de una muestra de entrenamiento en el cálculo de la frontera de decisión. Valores pequeños de gamma implican un alcance amplio, mientras que valores grandes hacen que la influencia sea cercana. Este parámetro es relevante para los núcleos 'rbf', 'poly' y 'sigmoid'. Se puede establecer como 'scale' (valor predeterminado) o 'auto', o bien asignar un valor numérico.

Ejemplo variando el parámetro gamma:

# Gamma bajo - alcance amplio
svc_gamma_bajo = SVC(gamma=0.01)
svc_gamma_bajo.fit(X_train_scaled, y_train)

# Gamma alto - alcance reducido
svc_gamma_alto = SVC(gamma=1)
svc_gamma_alto.fit(X_train_scaled, y_train)
  • coef0: Afecta únicamente a los núcleos 'poly' y 'sigmoid'. Este parámetro controla el término independiente en el núcleo y puede influir en la flexibilidad del modelo. Ajustar coef0 puede mejorar el rendimiento en ciertos casos.

Ejemplo utilizando coef0 con diferentes valores:

# Núcleo polinómico con coef0 = 0 (valor predeterminado)
svc_coef0_cero = SVC(kernel='poly', coef0=0)
svc_coef0_cero.fit(X_train_scaled, y_train)

# Núcleo polinómico con coef0 = 1
svc_coef0_uno = SVC(kernel='poly', coef0=1)
svc_coef0_uno.fit(X_train_scaled, y_train)
  • shrinking: Parámetro booleano que indica si se emplea el heurístico de reducción. Por defecto es True. Desactivar la reducción (shrinking=False) puede incrementar la velocidad en algunos casos, pero no siempre es así. Es recomendable mantener el valor predeterminado a menos que se experimente con diferentes configuraciones.

Ejemplo alterando el parámetro shrinking:

# Modelo con shrinking desactivado
svc_no_shrinking = SVC(shrinking=False)
svc_no_shrinking.fit(X_train_scaled, y_train)
  • probability: Si se establece en True, el modelo habilita el cálculo de probabilidades mediante una estimación pareada. Desactivar este parámetro (valor predeterminado False) reduce el tiempo de entrenamiento y predicción. Activarlo es útil cuando se requieren las probabilidades de cada clase, pero implica un coste computacional adicional.

Ejemplo habilitando el cálculo de probabilidades:

# Modelo con cálculo de probabilidades activado
svc_con_probabilidad = SVC(probability=True)
svc_con_probabilidad.fit(X_train_scaled, y_train)

# Predicción de probabilidades
probabilidades = svc_con_probabilidad.predict_proba(X_test_scaled)
  • tol: Representa la tolerancia para el criterio de parada del algoritmo de optimización. El valor predeterminado es 1e-3. Ajustar este parámetro puede afectar la convergencia del modelo. Un valor más pequeño puede conducir a una solución más precisa pero requerirá más tiempo de entrenamiento.

Ejemplo configurando la tolerancia:

# Modelo con tolerancia ajustada
svc_tol_bajo = SVC(tol=1e-5)
svc_tol_bajo.fit(X_train_scaled, y_train)
  • cache_size: Especifica el tamaño de la caché de kernel en megabytes. El valor predeterminado es 200. Aumentar este valor puede mejorar el rendimiento si se dispone de suficiente memoria RAM, especialmente en conjuntos de datos grandes.

Ejemplo aumentando el tamaño de caché:

# Modelo con cache_size aumentado
svc_cache_grande = SVC(cache_size=500)
svc_cache_grande.fit(X_train_scaled, y_train)
  • class_weight: Permite asignar un peso a cada clase, útil cuando se trabaja con datos desbalanceados. Puede establecerse como un diccionario {clase: peso} o utilizar 'balanced' para asignar pesos inversamente proporcionales a las frecuencias de las clases.

Ejemplo utilizando class_weight:

# Asignar pesos balanceados automáticamente
svc_balanceado = SVC(class_weight='balanced')
svc_balanceado.fit(X_train_scaled, y_train)

# Asignar pesos manualmente
pesos = {0: 1, 1: 2, 2: 1}  # Suponiendo tres clases
svc_pesos_manual = SVC(class_weight=pesos)
svc_pesos_manual.fit(X_train_scaled, y_train)
  • verbose: Permite imprimir información adicional durante el entrenamiento para propósitos de depuración. Un valor entero mayor que cero aumenta el detalle de la salida. Es útil para monitorear la convergencia del algoritmo.

Ejemplo activando el modo verbose:

# Modelo con salida detallada del entrenamiento
svc_verbose = SVC(verbose=1)
svc_verbose.fit(X_train_scaled, y_train)
  • max_iter: Define el número máximo de iteraciones que realiza el solucionador de optimización. El valor predeterminado es -1, lo que significa que no hay límite. Establecer un límite puede ser útil para evitar tiempos de entrenamiento excesivamente largos en casos donde el modelo no converge.

Ejemplo limitando el número de iteraciones:

# Modelo con máximo de iteraciones establecido
svc_max_iter = SVC(max_iter=1000)
svc_max_iter.fit(X_train_scaled, y_train)
  • decision_function_shape: Determina la forma de la función de decisión en problemas multiclase. Puede ser 'ovr' (uno contra el resto) o 'ovo' (uno contra uno). El valor predeterminado es 'ovr'. En la práctica, 'ovr' es generalmente más eficiente y recomendado.

Ejemplo cambiando la forma de la función de decisión:

# Modelo con decision_function_shape 'ovo'
svc_ovo = SVC(decision_function_shape='ovo')
svc_ovo.fit(X_train_scaled, y_train)
  • break_ties: Parámetro booleano que, si se establece en True, hace que el modelo rompa empates en las predicciones, lo que puede ser relevante en problemas multiclase. Solo es válido cuando decision_function_shape='ovr' y probability=False. Habilitar este parámetro puede aumentar el tiempo de predicción.

Ejemplo habilitando break_ties:

# Modelo con break_ties activado
svc_break_ties = SVC(break_ties=True)
svc_break_ties.fit(X_train_scaled, y_train)
  • random_state: Controla la semilla del generador aleatorio para efectos de reproducibilidad. Es relevante cuando el modelo utiliza procesos aleatorios intermedios. Establecer este parámetro asegura que los resultados sean consistentes entre ejecuciones.

Ejemplo estableciendo el random_state:

# Modelo con random_state fijo
svc_random = SVC(random_state=42)
svc_random.fit(X_train_scaled, y_train)

Es importante experimentar con diferentes configuraciones y utilizar técnicas de validación como la validación cruzada para seleccionar los hiperparámetros óptimos.

Interpretabilidad de SVC en Scikit Learn

La interpretabilidad en modelos de Máquinas de Vectores de Soporte (SVC) es un desafío debido a la complejidad inherente de estos algoritmos, especialmente cuando se utilizan núcleos no lineales. Sin embargo, Scikit-Learn proporciona herramientas que permiten entender y visualizar el funcionamiento interno de un modelo SVC, facilitando su análisis y comprensión.

Una forma de interpretar un modelo SVC es examinando los vectores de soporte. Estos son los puntos de datos que definen el hiperplano separador y, por tanto, son críticos en la construcción del modelo. Identificar estos vectores puede ayudar a entender qué muestras están influenciando más la frontera de decisión.

Para obtener los vectores de soporte, se puede acceder al atributo support_vectors_ del modelo entrenado:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
from sklearn.datasets import load_wine
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# Cargar y preparar los datos
wine = load_wine()
X = wine.data[:, :2]  # Utilizar dos características para facilitar la visualización
y = wine.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y)

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# Entrenar el modelo SVC
svc = SVC(kernel='linear', C=1.0)
svc.fit(X_train_scaled, y_train)

# Obtener los vectores de soporte
vectores_soporte = svc.support_vectors_

En este ejemplo, hemos entrenado un modelo SVC con un núcleo lineal y extraído los vectores de soporte. Podemos visualizarlos para entender su impacto en la clasificación:

# Visualización de los vectores de soporte
plt.scatter(X_train_scaled[:, 0], X_train_scaled[:, 1], c=y_train, cmap='viridis')
plt.scatter(vectores_soporte[:, 0], vectores_soporte[:, 1], s=100, facecolors='none', edgecolors='r')
plt.title('Vectores de Soporte')
plt.xlabel('Característica 1')
plt.ylabel('Característica 2')
plt.show()

Los puntos resaltados en rojo representan los vectores de soporte, evidenciando las muestras que están definiendo la frontera de decisión. Esta visualización es útil para comprender cómo el modelo está separando las clases.

Además, en modelos SVC con núcleo lineal, es posible acceder a los coeficientes del hiperplano separador a través del atributo coef_. Estos coeficientes indican la importancia de cada característica en la clasificación:

# Obtener los coeficientes del hiperplano
coeficientes = svc.coef_
intercepto = svc.intercept_

print('Coeficientes del hiperplano:', coeficientes)
print('Intercepto:', intercepto)

Este enfoque permite interpretar el modelo de forma similar a una regresión logística, identificando qué variables tienen mayor peso en la clasificación.

Para visualizar la frontera de decisión, podemos crear una malla de puntos y predecir la clase para cada punto, generando un mapa de las regiones de clasificación:

# Crear una malla de puntos
x_min, x_max = X_train_scaled[:, 0].min() - 1, X_train_scaled[:, 0].max() + 1
y_min, y_max = X_train_scaled[:, 1].min() - 1, X_train_scaled[:, 1].max() + 1
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 500), np.linspace(y_min, y_max, 500))

# Predecir la clase para cada punto en la malla
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# Visualización de la frontera de decisión
plt.contourf(xx, yy, Z, alpha=0.3, cmap='viridis')
plt.scatter(X_train_scaled[:, 0], X_train_scaled[:, 1], c=y_train, cmap='viridis', edgecolors='k')
plt.scatter(vectores_soporte[:, 0], vectores_soporte[:, 1], s=100, facecolors='none', edgecolors='r')
plt.title('Frontera de Decisión del SVC')
plt.xlabel('Característica 1')
plt.ylabel('Característica 2')
plt.show()

Esta gráfica muestra cómo el modelo SVC divide el espacio de características para clasificar las muestras. La línea que separa las regiones corresponde al hiperplano definido por el modelo.

En casos donde se utiliza un núcleo no lineal, como el núcleo RBF, la interpretación se vuelve más compleja debido a la transformación implícita de las características. Sin embargo, la visualización de la frontera de decisión sigue siendo una herramienta valiosa:

# Modelo SVC con núcleo RBF
svc_rbf = SVC(kernel='rbf', C=1.0, gamma='scale')
svc_rbf.fit(X_train_scaled, y_train)

# Predecir y visualizar la frontera de decisión
Z_rbf = svc_rbf.predict(np.c_[xx.ravel(), yy.ravel()])
Z_rbf = Z_rbf.reshape(xx.shape)

plt.contourf(xx, yy, Z_rbf, alpha=0.3, cmap='viridis')
plt.scatter(X_train_scaled[:, 0], X_train_scaled[:, 1], c=y_train, cmap='viridis', edgecolors='k')
plt.scatter(svc_rbf.support_vectors_[:, 0], svc_rbf.support_vectors_[:, 1], s=100, facecolors='none', edgecolors='r')
plt.title('Frontera de Decisión con Núcleo RBF')
plt.xlabel('Característica 1')
plt.ylabel('Característica 2')
plt.show()

Observamos que la frontera de decisión no es lineal, reflejando la capacidad del núcleo RBF para capturar relaciones más complejas entre las variables.

Otra forma de entender el modelo es analizando la función de decisión, que proporciona una medida de la distancia de una muestra al hiperplano. En Scikit-Learn, se puede acceder a esta información mediante el método decision_function:

# Calcular la función de decisión para el conjunto de prueba
decision_scores = svc.decision_function(X_test_scaled)

print('Puntajes de la función de decisión:', decision_scores)

Estos puntajes indican qué tan confiado está el modelo en sus predicciones. Valores más grandes en magnitud implican mayor confianza en la clasificación.

Para una interpretación más profunda, especialmente en modelos con múltiples características, se pueden utilizar herramientas como Permutación de Importancia. Scikit-Learn ofrece la función permutation_importance que permite evaluar la importancia de cada característica en las predicciones:

from sklearn.inspection import permutation_importance

# Calcular la importancia por permutación
resultado = permutation_importance(svc, X_test_scaled, y_test, n_repeats=10, random_state=42)

importancias = resultado.importances_mean
indices = np.argsort(importancias)[::-1]

# Mostrar las importancias
for idx in indices:
    print(f'Característica {idx}: Importancia = {importancias[idx]:.4f}')

Este método proporciona una estimación de cómo la permutación aleatoria de una característica afecta la exactitud del modelo, ofreciendo insights sobre las variables más relevantes.

Es importante mencionar que para modelos SVC no lineales, las interpretaciones basadas en coeficientes son limitadas. En estos casos, se recomienda utilizar técnicas de interpretabilidad más avanzadas, como LIME o SHAP, que, aunque no forman parte de Scikit-Learn, pueden integrarse con los modelos entrenados.

Para ilustrar el uso de SHAP con un modelo SVC, se requiere instalar la librería shap:

pip install shap

Y luego aplicar el análisis:

import shap

# Crear un explainer con el modelo SVC
explainer = shap.KernelExplainer(svc.predict, X_train_scaled)

# Calcular los valores SHAP para una muestra del conjunto de prueba
X_sample = X_test_scaled[:10]
shap_values = explainer.shap_values(X_sample)

# Visualizar los valores SHAP
shap.summary_plot(shap_values, X_sample, feature_names=['Característica 1', 'Característica 2'])

Los valores SHAP ayudan a entender la contribución de cada característica en las predicciones individuales, proporcionando una explicación más detallada del comportamiento del modelo.

Finalmente, es posible extraer información sobre la probabilidad de las predicciones si el modelo ha sido entrenado con probability=True:

# Modelo SVC con probabilidad habilitada
svc_prob = SVC(kernel='rbf', C=1.0, gamma='scale', probability=True)
svc_prob.fit(X_train_scaled, y_train)

# Obtener las probabilidades de predicción
probabilidades = svc_prob.predict_proba(X_test_scaled)

print('Probabilidades de las clases:')
print(probabilidades)

Las probabilidades permiten evaluar la confianza del modelo en cada predicción, lo que es útil en aplicaciones donde es necesario cuantificar la incertidumbre.

La interpretabilidad de los modelos SVC puede ser compleja, Scikit-Learn ofrece diversas herramientas para explorar y entender sus decisiones. La visualización de fronteras de decisión, el análisis de vectores de soporte y la utilización de técnicas como la importancia por permutación son recursos valiosos para interpretar estos modelos y extraer conclusiones significativas.

Aprende ScikitLearn GRATIS online

Ejercicios de esta lección Clasificación SVM con SVC

Evalúa tus conocimientos de esta lección Clasificación SVM con SVC con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de ScikitLearn

Accede a todas las lecciones de ScikitLearn y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Aprendizaje Automático

scikit-learn

Introducción Y Entorno

Introducción E Instalación

scikit-learn

Introducción Y Entorno

Introducción Al Preprocesamiento De Datos

scikit-learn

Preprocesamiento De Datos

Identificación Y Tratamiento De Valores Faltantes

scikit-learn

Preprocesamiento De Datos

Escalado De Datos

scikit-learn

Preprocesamiento De Datos

Normalización De Datos

scikit-learn

Preprocesamiento De Datos

Codificación De Variables Categóricas

scikit-learn

Preprocesamiento De Datos

Ingeniería De Características

scikit-learn

Preprocesamiento De Datos

Selección De Características

scikit-learn

Preprocesamiento De Datos

Extracción De Características

scikit-learn

Preprocesamiento De Datos

Particionamiento De Datos

scikit-learn

Preprocesamiento De Datos

Preprocesamiento De Datos Desbalanceados

scikit-learn

Preprocesamiento De Datos

Introducción A La Regresión

scikit-learn

Regresión

Regresión Lineal

scikit-learn

Regresión

Regresión Knn Kneighborsregressor

scikit-learn

Regresión

Regresión Svm Con Svr

scikit-learn

Regresión

Regresión Con Árboles Decisiontreeregressor

scikit-learn

Regresión

Regresión Con Algoritmos De Conjunto

scikit-learn

Regresión

Introducción A La Clasificación

scikit-learn

Clasificación

Clasificación Con Regresión Logística

scikit-learn

Clasificación

Clasificación Knn Kneighborsclassifier

scikit-learn

Clasificación

Clasificación Svm Con Svc

scikit-learn

Clasificación

Clasificación Con Árboles Decisiontreeclassifier

scikit-learn

Clasificación

Clasificación Con Algoritmos De Conjunto

scikit-learn

Clasificación

Reducción De La Dimensionalidad Con Pca

scikit-learn

Aprendizaje No Supervisado

Clustering Con Kmeans

scikit-learn

Aprendizaje No Supervisado

Clustering Jerárquico

scikit-learn

Aprendizaje No Supervisado

Clustering De Densidad Con Dbscan

scikit-learn

Aprendizaje No Supervisado

Preprocesamiento De Textos Para Nlp

scikit-learn

Nlp

Representación De Texto Y Extracción De Características

scikit-learn

Nlp

Clasificación De Texto Con Scikit Learn

scikit-learn

Nlp

Análisis De Sentimiento

scikit-learn

Nlp

Técnicas Avanzadas De Extracción De Características

scikit-learn

Nlp

Introducción Al Análisis De Series Temporales

scikit-learn

Series Temporales

Preprocesamiento De Datos De Series Temporales

scikit-learn

Series Temporales

Ingeniería De Características Para Series Temporales

scikit-learn

Series Temporales

Transformación Y Escalado De Series Temporales

scikit-learn

Series Temporales

Validación Y Evaluación De Modelos En Series Temporales

scikit-learn

Series Temporales

Validación Y Evaluación De Modelos

scikit-learn

Validación De Modelos

Técnicas De Validación Cruzada

scikit-learn

Validación De Modelos

Métricas De Regresión

scikit-learn

Validación De Modelos

Métricas De Clasificación

scikit-learn

Validación De Modelos

Ajuste De Hiperparámetros

scikit-learn

Validación De Modelos

Introducción A Pipelines

scikit-learn

Pipelines Y Despliegue

Creación De Pipelines Básicos

scikit-learn

Pipelines Y Despliegue

Preprocesamiento De Datos Con Pipelines

scikit-learn

Pipelines Y Despliegue

Pipelines Y Validación Cruzada

scikit-learn

Pipelines Y Despliegue

Pipelines Con Columntransformer

scikit-learn

Pipelines Y Despliegue

Exportar E Importar Pipelines

scikit-learn

Pipelines Y Despliegue

Accede GRATIS a ScikitLearn y certifícate

Objetivos de aprendizaje de esta lección

  • Comprender los fundamentos teóricos de las Máquinas de Soporte Vectorial para clasificación.
  • Aplicar preprocesamientos específicos para SVC en conjuntos de datos.
  • Implementar modelos de clasificación con SVC utilizando Scikit Learn.
  • Ajustar y optimizar los parámetros clave del SVC para mejorar el rendimiento.
  • Interpretar y visualizar los resultados de los modelos SVC.
  • Manejar problemas de datos desbalanceados y variables categóricas en SVC.
  • Utilizar técnicas de validación y ajuste de hiperparámetros en SVC.