
SVM explicada: la presión en Pa hundió el AUC a 0,555 y el kernel exacto tardó 51 segundos
Qué es una máquina de vectores de soporte, qué hacen el margen, C y gamma, y cuándo falla, medido con clima diario de siete ciudades de Chile entre 1984 y 2026. Sin escalar, cambiar la presión de kPa a Pa bajó el AUC en validación de 0,835 a 0,555; con las 74.145 filas el kernel RBF tardó 51 s y, en la prueba de 2016-2026, quedó bajo un boosting que entrenó en 2,6 s.
Una SVM con kernel RBF, sin escalar las variables, dio AUC 0,835 en un período de validación para anticipar la lluvia de mañana. Escribí la misma presión atmosférica en pascales en vez de kilopascales, mil veces más grande, y el mismo modelo bajó a 0,555, casi azar. Estandarizando las variables, dio 0,845 en los dos casos.
Es la séptima entrega de la serie, con los mismos datos diarios de NASA POWER de siete ciudades de Chile que usé en Random Forest, regresión lineal, K-Means, regresión logística, árbol de decisión y gradient boosting. La pregunta sigue siendo si lloverá al menos 1 mm mañana. Entrené con 1984-2012 y evalué en la prueba de 2016-2026, en un contenedor con 8 CPU y scikit-learn 1.7.2. C y gamma los elegí ajustando con 1984-2009 y midiendo en 2010-2012. Como un solo ajuste con kernel sobre todas las filas tarda cerca de un minuto y elegir C y gamma exige decenas de ajustes, varias pruebas usan submuestras fijas de 10.000 o 20.000 días, y en cada comparación digo qué filas vio cada modelo.
¿Qué es una SVM?
Una máquina de vectores de soporte busca una frontera entre dos clases, días seguidos por lluvia y días seguidos por tiempo seco, y de todas las fronteras posibles elige la que deja más espacio a cada lado. Ese espacio es el margen. Casi nunca las clases se separan limpias, así que se permite que algunos días queden dentro del margen o del lado equivocado, con una penalización que regula el parámetro C. Es la formulación de Corinna Cortes y Vladimir Vapnik (1995).
Los días que quedan sobre el margen, dentro de él o del lado equivocado son los vectores de soporte. Solo ellos definen la frontera: si se borra un día que está lejos, la frontera no cambia.
- llueve mañana
- seco mañana
- SV
Con C = 0,01 el margen mide 3,43 y 164 de los 200 días son vectores de soporte; con C = 1, 1,51 y 118; con C = 100, 1,34 y 117. Solo sostienen la recta los días que quedan sobre el margen o dentro de él: en estas dos variables las clases se mezclan, así que más de la mitad de los días termina ahí. Medido en 2010-2012 con las mismas dos variables, el AUC pasa de 0,802 a 0,814.
Con dos variables, humedad y lluvia de hoy, y 200 días de entrenamiento (100 con lluvia al día siguiente y 100 sin), C = 0,01 dejó un margen de 3,43 y 164 vectores de soporte. Con C = 1 el margen se angostó a 1,51 y quedaron 118; con C = 100, 1,34 y 117. En estas dos variables las clases se mezclan tanto que más de la mitad de los días quedaron dentro del margen aun con C alto. En 2010-2012, con las mismas dos variables, el AUC pasó de 0,802 a 0,814.
El kernel dobla la frontera
Una frontera recta no siempre alcanza. El truco del kernel, que Boser, Guyon y Vapnik usaron en 1992 para clasificadores de margen máximo, permite calcular la SVM como si las variables vivieran en un espacio de muchas más dimensiones sin construirlo. El kernel RBF mide qué tan parecidos son dos días según su distancia, y gamma decide qué tan rápido cae ese parecido.
Con gamma 0,03 la frontera es casi recta: AUC 0,844 en los 200 días y 0,807 en 2010-2012. Con gamma 30 envuelve grupitos de días: 0,943 en los 200 días con que aprendió y 0,765 en 2010-2012. Un gamma más grande hace que la influencia de cada vector de soporte llegue menos lejos, y la frontera sigue a días sueltos en vez de a la tendencia.
Con gamma 0,03 la frontera sale casi recta: AUC 0,844 en los 200 días y 0,807 en 2010-2012. Con gamma 30 envuelve grupitos de días: 0,943 en los días con que aprendió y 0,765 en 2010-2012. Es sobreajuste, igual que el del árbol sin límite, con otra forma.
Escalar cambia la respuesta
Si el kernel mide distancias, las unidades importan. Probé con 10.000 días de 1984-2009 y medí en 2010-2012.
Con la presión en kPa, la SVM RBF sin escalar dio 0,835 y la estandarizada 0,845. Escribir la misma presión en Pa, mil veces más grande, hundió a la RBF sin escalar a 0,555, cerca del azar: la distancia entre días pasó a ser casi solo una diferencia de presión. Las versiones escaladas no se movieron (0,845 y 0,852), y la LinearSVC sin escalar bajó a 0,813.
Con la presión en kPa, como la entrega NASA POWER, la SVM RBF sin escalar dio 0,835, estandarizada 0,845 y con MinMaxScaler 0,852. Ninguna variable de esta tabla domina la distancia por órdenes de magnitud (las desviaciones estándar van de 0,4 a 19), así que la diferencia fue chica. Con la presión en Pa la distancia entre dos días pasó a ser casi solo su diferencia de presión, y la SVM sin escalar cayó a 0,555. Las versiones escaladas no se movieron, y la SVM lineal sin escalar bajó de 0,851 a 0,813.
En el post de regresión logística escalar cambió cuántas iteraciones tardaba el ajuste en converger. En una SVM, con o sin kernel, cambia la solución.
C y gamma se eligen en una rejilla
La mejor celda en 2010-2012 fue C = 1.000 con gamma = 0,001: AUC 0,860, con el 38 % de los días como vectores de soporte. Reentrenada con 10.000 días de 1984-2012, dio 0,865 en 2016-2026. La esquina de C y gamma grandes llega a AUC 1,000 en sus propios días de entrenamiento y cae en 2010-2012. La celda elegida no quedó en el borde de la rejilla.
Probé 42 combinaciones de C y gamma con 10.000 días de 1984-2009. La mejor en 2010-2012 fue C = 1.000 con gamma = 0,001, con AUC 0,860; C = 100 con gamma = 0,003 quedó a 0,0003, y la misma elección salió al repetir la mejor fila y la mejor columna con 20.000 días. Las dos primeras rejillas que armé dejaban la elección en el borde, así que las amplié hasta que dejó de estarlo. La esquina de C y gamma grandes llegó a AUC 1,000 en sus propios días de entrenamiento y a 0,790 en 2010-2012. Reentrenada con 10.000 días de 1984-2012, la combinación elegida dio 0,865 en 2016-2026.
El costo sube más rápido que las filas
scikit-learn implementa SVC sobre LIBSVM, que evalúa similitudes de kernel entre pares de ejemplos durante la optimización. Medí el tiempo de ajuste con un hilo sobre submuestras anidadas, con la SVM en sus valores por defecto (C = 1, gamma = ‘scale’) y los demás modelos sobre las mismas filas.
- SVM RBF
- bosque 200
- boosting 594
- LinearSVC
- logística
AUC en 2016-2026 por filas
Entre 5.000 y 40.000 filas, el tiempo de ajuste de la SVM creció con pendiente log-log 2,02: duplicar las filas multiplicó el tiempo por 4,1. Esa pendiente predecía 47,3 s para las 74.145 filas; tardó 50,8 s. Con esas mismas filas el boosting entrenó en 2,6 s y la regresión logística en 0,06 s.
Entre 5.000 y 40.000 días el tiempo creció con pendiente log-log 2,02: duplicar las filas multiplicó el tiempo por cuatro. Esa pendiente predecía 47 s para las 74.145 filas; tardó 51 s. Con esas filas la SVM guardó 27.707 vectores de soporte, tardó 17 s en puntuar los 27.256 días de prueba y quedó en AUC 0,849 en 2016-2026, con sus valores por defecto y no con la C y gamma de la rejilla. El boosting entrenó en 2,6 s y llegó a 0,883.
Pasar de 2.000 a 74.145 días movió a la SVM de 0,844 a 0,849; al boosting, de 0,852 a 0,883, y al bosque, de 0,866 a 0,882. Ocho hilos no ayudaron: con 40.000 días tardó 13,6 s con uno y con ocho, porque LIBSVM entrena en un solo hilo. Subir la memoria de caché del kernel de 200 a 2.000 MB tampoco la aceleró (16,3 s).
Cada predicción pasa por todos los vectores de soporte
Con C = 0,01 el modelo guardó 10.712 vectores de soporte, el 54 % de las filas de entrenamiento, y tardó 0,73 ms por día; con C = 1.000, 7.813 y 0,64 ms. El tamaño serializado sigue a los vectores de soporte, de 1,5 MB a 1,1 MB. Una regresión logística puntúa un día con un solo producto punto.
Con 20.000 días y gamma 0,001, subir C de 0,01 a 1.000 bajó los vectores de soporte de 10.712 (el 54 % de los días) a 7.813 (el 39 %). La latencia por día bajó de 0,73 a 0,64 ms y el modelo serializado, de 1,5 a 1,1 MB, siguiendo a los vectores de soporte. En todos los casos más del 98 % de los vectores de soporte quedaron en el tope de su penalización, es decir, en el margen o dentro de él, incluidos los mal clasificados: son los días difíciles de separar, no una selección de ejemplos bonitos.
Una SVM lineal no es una logística
Sin kernel, la SVM es un modelo lineal con otra función de pérdida. Con las 74.145 filas estandarizadas, LinearSVC, que pasa por LIBLINEAR y cuya C elegí en 2010-2012, dio AUC 0,849 en 0,08 s y la regresión logística 0,847 en 0,05 s. De los 15 coeficientes, 13 tuvieron el mismo signo en los dos modelos, y las tres variables de mayor peso coincidieron: lluvia de hoy, componente norte-sur del viento y latitud.
La trampa está en usar SVC(kernel="linear"), que pasa por LIBSVM. Con 20.000 días tardó 3,0 s contra 0,02 s de LinearSVC, para un modelo lineal parecido pero no idéntico: LinearSVC usa otra pérdida y penaliza el intercepto. El tiempo de SVC(kernel="linear") sigue subiendo como en la curva anterior.
Una SVM no devuelve probabilidades
decision_function en 2016-2026 · claro: todos los días · oscuro: días con lluvia mañana
probability=True corrió la calibración de Platt interna de libsvm, con 5 pliegues, y llevó el entrenamiento de 5,8 a 31,8 s. Predijo en promedio 24 % de lluvia contra 20 % observado (pérdida logarítmica 0,373), y en 31 días de prueba predict y predict_proba > 0,5 no coincidieron. Una sigmoide ajustada con 2010-2012 dio pérdida 0,367, una isotónica 0,352 y la regresión logística con las mismas filas 0,380.
decision_function es un puntaje con signo, proporcional a la distancia a la frontera, no una probabilidad. probability=True agrega una calibración de Platt con validación cruzada interna de cinco pliegues: con 20.000 días de 1984-2009 llevó el entrenamiento de 5,8 a 31,8 s. Predijo en promedio 24,2 % de lluvia contra 20,3 % observado en 2016-2026, con pérdida logarítmica 0,373, y en 31 días de 2016-2026 predict y predict_proba mayor a 0,5 no coincidieron, algo que la documentación de scikit-learn advierte.
Calibrar aparte con 2010-2012 funcionó mejor: en 2016-2026 una sigmoide dio pérdida 0,367 y una calibración isotónica 0,352, las dos con 21,5 % de lluvia predicha. Con las mismas filas, la regresión logística dio 0,380 y el boosting 0,343.
class_weight="balanced" le dio más peso a los días con lluvia. Con 20.000 días, la SVM sin pesos anticipó el 49 % de los días con lluvia de 2016-2026 y la balanceada el 83 %, con AUC 0,865 y 0,872. Después bajé el umbral de la SVM sin pesos hasta que, en 2010-2012, anticipara lo mismo que la balanceada (el 84 %), y lo dejé fijo: en 2016-2026 anticipó el 83 % con una exactitud balanceada de 0,793, casi la misma que la balanceada (0,795). En este experimento, mover el umbral reprodujo casi la sensibilidad y la exactitud balanceada de class_weight, pero no su aumento de AUC, de 0,865 a 0,872.
Un puente para muchas filas: aproximar el kernel
Si el kernel exacto no alcanza a ver todas las filas, se puede aproximar. Nystroem, la idea de Williams y Seeger (2001), construye variables nuevas a partir de una muestra de días; las variables aleatorias de Fourier de Rahimi y Recht (2007) aproximan el RBF con senos y cosenos. Después basta un modelo lineal.
- RBF exacta
- Nystroem + LinearSVC
- Fourier aleatorio + LinearSVC
tiempo de ajuste con 8 hilos
El kernel exacto con 20.000 filas dio 0,865 en 5,9 s. Nystroem con 300 componentes sobre las 74.145 filas llegó a 0,879 en 24,9 s, y el mejor Nystroem, con 1.000 componentes, a 0,879. Las aproximaciones con 74.145 filas ordenaron mejor que el kernel exacto con 20.000. Con 8 hilos, Nystroem 1.000 tardó 84,3 s.
Con el mismo gamma, la C del modelo lineal elegida en 2010-2012 para cada tamaño (3.000 componentes reutiliza la de 1.000) y los tamaños 100, 300, 1.000 y 3.000 que fijé antes de medir y que reporto como diagnóstico, Nystroem con 300 componentes sobre las 74.145 filas llegó en 2016-2026 a AUC 0,879 en 25 s, más que la SVM exacta con 20.000 días (0,865 en 5,9 s). Subir a 1.000 componentes mejoró solo 0,0005 y 3.000 no agregó nada, a un costo de 66 y 269 s. Con Fourier aleatorio, 3.000 componentes llegaron a 0,880 en 249 s. En esta comparación, las aproximaciones entrenadas con 74.145 filas ordenaron mejor que el kernel exacto entrenado con 20.000; el diseño no permite atribuir la diferencia solo al número de filas. Entre los tamaños cuya C ajusté, salvo Nystroem con 100 componentes, ganó C = 1.000, el tope que probé, y la validación todavía subía un poco ahí: con más C podría ganar algo más.
Para números: SVR
La misma idea sirve para predecir la máxima de mañana. Una SVR con kernel RBF, con gamma, C y épsilon elegidos en 2010-2012 (gamma 0,01, C = 1.000 en el tope que probé y épsilon 0,5 °C), entrenada con 10.000 días, erró por 1,49 °C en promedio en 2016-2026; la regresión lineal con todas las filas, por 1,70 °C, y el boosting, por 1,44 °C.
En la prueba de extrapolación de la serie, entrenar con los meses de abril a septiembre de Santiago y predecir los veranos de 2016-2026, la SVR llegó a predecir 35,73 °C, más que los 32,97 °C del día más caluroso que vio, y erró por 2,43 °C en promedio. El boosting, que no pasó de 29,56 °C, erró por 5,48 °C; la regresión lineal, por 1,72 °C. En este corte estacional la SVR superó el máximo que vio y el boosting no; eso no demuestra que una SVR extrapole en general. Es un corte por estación, no una prueba limpia fuera del rango: el verano cambia varias variables a la vez.
SVM, boosting, bosque, Nystroem y logística
A la mitad del tiempo real.
Puntuar un día tomó 0,64 ms a la SVM, 0,39 ms a la logística y 3,2 ms al boosting; serializados, la SVM ocupa 1,1 MB, el boosting 2,1 MB y el bosque 34 MB.
Con las mismas 20.000 filas, remuestreé 2.000 veces los bloques ciudad-año de 2016-2026 para comparar el AUC en pares. La SVM quedó por debajo del boosting por 0,012 (intervalo del 95 %: de −0,016 a −0,008) y por debajo de Nystroem con un modelo lineal por 0,013; quedó por encima de la regresión logística por 0,018. Ninguno de los tres intervalos cruza el cero.
Dónde vive una SVM en un sistema real
Medido con un hilo sobre las mismas 20.000 filas: la SVM RBF entrena en 5,44 s, serializada ocupa 1,1 MB, puntúa un día en 0,64 ms y los 27.256 días de prueba en 4,85 s (AUC 0,865). Nystroem con 1.000 componentes más LinearSVC: 15,06 s, 0,72 ms, AUC 0,877. Boosting: 1,18 s, 3,16 ms, AUC 0,877. Regresión logística: 0,011 s, AUC 0,847.
- Tablas medianas de variables numéricas. Miles a unas decenas de miles de filas, donde el costo cuadrático todavía cabe y la frontera no es lineal.
- El escalador dentro del artefacto. El
StandardScalertiene que viajar con el modelo, en el mismo pipeline. Si una fuente cambia de unidades, la SVM cambia su respuesta sin avisar. - API con pocos vectores de soporte. La latencia por fila crece con ellos: aquí 0,64 ms con 7.813.
- Con muchas filas, Nystroem más un modelo lineal. Aquí rindió más que el kernel exacto sobre una submuestra.
Cuándo la elegiría: para tablas medianas donde una frontera suave basta y se puede escalar con cuidado. Cuándo no: con cientos de miles de filas, o cuando hay que buscar C y gamma sobre decenas de miles, donde el costo de entrenar y de predecir crece con los vectores de soporte; cuando hacen falta probabilidades sin calibrar aparte; o cuando hay variables con unidades que pueden cambiar. En estos datos un boosting obtuvo mayor AUC en la prueba, entrenó más rápido y tuvo menor pérdida logarítmica.
Fuentes
- Cortes, C. y Vapnik, V. (1995). «Support-vector networks». Machine Learning, 20(3), 273–297. DOI 10.1007/BF00994018.
- Boser, B. E., Guyon, I. M. y Vapnik, V. N. (1992). «A training algorithm for optimal margin classifiers». COLT ‘92, 144–152. DOI 10.1145/130385.130401.
- Chang, C.-C. y Lin, C.-J. (2011). «LIBSVM: A library for support vector machines». ACM Transactions on Intelligent Systems and Technology, 2(3). DOI 10.1145/1961189.1961199.
- Fan, R.-E. et al. (2008). «LIBLINEAR: A Library for Large Linear Classification». Journal of Machine Learning Research, 9.
- Platt, J. (2000). «Probabilities for SV Machines». En Advances in Large-Margin Classifiers, 61–74. DOI 10.7551/mitpress/1113.003.0008.
- Lin, H.-T., Lin, C.-J. y Weng, R. C. (2007). «A note on Platt’s probabilistic outputs for support vector machines». Machine Learning, 68(3), 267–276. DOI 10.1007/s10994-007-5018-6.
- Williams, C. K. I. y Seeger, M. (2001). «Using the Nyström Method to Speed Up Kernel Machines». Advances in Neural Information Processing Systems 13.
- Rahimi, A. y Recht, B. (2007). «Random Features for Large-Scale Kernel Machines». Advances in Neural Information Processing Systems 20.
- Smola, A. J. y Schölkopf, B. (2004). «A tutorial on support vector regression». Statistics and Computing, 14(3), 199–222. DOI 10.1023/B:STCO.0000035301.49549.88.
- scikit-learn 1.7, máquinas de vectores de soporte y aproximación de kernels.
- NASA POWER, Daily API y fuentes de datos.
Comentarios
Todavía no hay comentarios. El primero es tuyo.