18. Máquinas de soporte vectorial (SVM)

18.1 Una idea elegante para separar clases

Las máquinas de soporte vectorial, conocidas como SVM, son modelos de clasificación que buscan separar las clases con una frontera lo más sólida posible.

La intuición principal no es solo “separar”, sino separar con margen. Es decir, elegir una frontera que deje la mayor distancia posible entre los grupos.

18.2 Qué significa el margen

Imaginemos dos grupos de puntos: compradores y no compradores. Muchas líneas podrían separarlos. SVM intenta elegir la que deje el espacio más amplio posible entre ambos grupos.

Ese espacio se llama margen. Cuanto mayor sea, más robusta tiende a ser la separación frente a pequeñas variaciones en los datos.

18.3 Qué son los vectores de soporte

No todos los puntos del dataset influyen igual. Los más importantes para definir la frontera son los que quedan más cerca del borde entre clases.

Esos puntos se llaman vectores de soporte. Son los ejemplos que “sostienen” la frontera de decisión.

Por eso el algoritmo lleva ese nombre.

18.4 Por qué SVM suele funcionar bien

SVM puede rendir muy bien cuando:

  • hay una separación razonable entre las clases;
  • el dataset no es gigantesco;
  • necesitamos una frontera de decisión robusta.

Es un modelo especialmente conocido por su buen desempeño en muchos problemas de clasificación, incluso cuando las relaciones no son triviales.

18.5 La importancia del escalado en SVM

SVM depende mucho de distancias y geometría del espacio de variables. Por eso, cuando unas columnas tienen escalas muy distintas de otras, el resultado puede distorsionarse.

En la práctica, es muy común usar SVM junto con StandardScaler. No es un detalle menor: en muchos casos mejora claramente el comportamiento del modelo.

18.6 El parámetro C explicado de forma simple

Uno de los parámetros más importantes de SVM es C. De forma intuitiva:

  • un C grande penaliza más los errores y busca ajustar más estrictamente los datos;
  • un C más chico permite una frontera más flexible y tolera más errores.

No hace falta profundizar demasiado todavía. Lo importante es entender que C controla el equilibrio entre ajuste y generalización.

18.7 Ejemplo muy claro: clasificar clientes con SVM

Vamos a predecir si un cliente comprará según dos variables:

  • cantidad de páginas vistas;
  • tiempo en el sitio.

Usaremos un Pipeline con StandardScaler y SVC. También activaremos probability=True para obtener probabilidades estimadas.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

clientes = pd.DataFrame({
    "paginas_vistas": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 5, 8],
    "minutos_sitio": [1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 3, 4],
    "compra": [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1]
})

X = clientes[["paginas_vistas", "minutos_sitio"]]
y = clientes["compra"]

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

modelo = Pipeline([
    ("escalador", StandardScaler()),
    ("svm", SVC(kernel="rbf", C=1.0, probability=True, random_state=42))
])

modelo.fit(X_train, y_train)

y_pred = modelo.predict(X_test)
print("Valores reales:", y_test.values)
print("Predicciones:", y_pred)
print("Exactitud:", accuracy_score(y_test, y_pred))

nuevo_cliente = pd.DataFrame({
    "paginas_vistas": [7],
    "minutos_sitio": [4]
})

prediccion = modelo.predict(nuevo_cliente)[0]
probabilidad = modelo.predict_proba(nuevo_cliente)[0, 1]

print("Predicción para el nuevo cliente:", prediccion)
print(f"Probabilidad de compra: {probabilidad:.3f}")

Salida resumida esperada:

Valores reales: [...]
Predicciones: [...]
Exactitud: ...
Predicción para el nuevo cliente: ...
Probabilidad de compra: ...

18.8 Qué está pasando en el ejemplo

El modelo primero escala las variables para que páginas vistas y minutos en el sitio queden en magnitudes comparables. Después, SVM busca una frontera que separe compradores y no compradores con el mejor margen posible.

Como usamos un kernel rbf, el modelo puede capturar relaciones no lineales de forma más flexible que una simple línea recta.

18.9 Qué significa kernel

El kernel define la forma de la frontera de decisión. Para comenzar, alcanza con esta idea:

  • linear: intenta separar con una frontera lineal;
  • rbf: permite fronteras más flexibles;
  • poly: usa una forma polinómica.

En la práctica introductoria, rbf es una opción muy común porque puede adaptarse a más situaciones.

18.10 Explicación detallada del código

  • StandardScaler(): escala las variables antes de entrenar SVM.
  • SVC(...): crea el clasificador SVM.
  • kernel="rbf": permite una frontera no lineal.
  • probability=True: habilita el cálculo de probabilidades estimadas.
  • Pipeline([...]): garantiza que el mismo flujo se aplique en entrenamiento, prueba y predicción.

18.11 Ventajas y limitaciones

Ventajas:

  • suele clasificar muy bien en muchos problemas;
  • puede manejar fronteras complejas mediante kernels;
  • busca una separación robusta entre clases.

Limitaciones:

  • puede ser más costoso que otros modelos cuando el dataset crece mucho;
  • su interpretación no es tan directa como la de un árbol;
  • requiere cuidado con el escalado y con la elección de parámetros.

18.12 Errores frecuentes

  • No escalar los datos: es uno de los errores más comunes al usar SVM.
  • Usar parámetros por defecto sin validar: conviene probar distintas configuraciones.
  • Creer que siempre es mejor que otros modelos: depende del problema y del tamaño de los datos.
  • Ignorar el costo computacional: puede volverse más pesado que modelos simples en datasets grandes.

18.13 Qué deberías retener

  • SVM busca separar clases con el mayor margen posible.
  • Los vectores de soporte son los puntos clave que determinan la frontera.
  • El escalado suele ser fundamental para que funcione bien.
  • Los kernels permiten construir fronteras más flexibles.
  • Es un modelo potente y clásico para problemas de clasificación.