
Red neuronal explicada: igualó al boosting con 2.177 pesos, y cambiar la semilla le movió el AUC 0,004
Qué es una red neuronal, qué hace cada capa y cuándo falla, medido con clima diario de siete ciudades de Chile entre 1984 y 2026. Una capa oculta de 128 unidades, 2.177 pesos y 81 KB, llegó a AUC 0,883 en la prueba de 2016-2026: la misma cifra que un boosting de 2,1 MB, con 0,40 ms por fila contra 3,09. Entrenarla costó cinco veces más, y repetir el entrenamiento cambiando solo la semilla movió el AUC de validación entre 0,881 y 0,884.
Una capa oculta de 128 unidades, 2.177 pesos y 81 KB serializados, llegó a AUC 0,8829 en la prueba de 2016-2026. Un boosting de 594 rondas y 2,1 MB llegó a 0,8830. La diferencia pareada entre ambos es de −0,00002, con un intervalo del 95 % que cruza el cero: al ordenar los días, el bootstrap no detectó una diferencia concluyente. Lo que sí se distingue es todo lo demás.
Es la décima 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, gradient boosting, SVM, KNN y Naive Bayes. 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. El tamaño de la red lo elegí ajustando con 1984-2009 (hasta el 30 de diciembre, porque la etiqueta del 31 es la lluvia del 1 de enero de 2010) y midiendo en 2010-2012; la regularización, el paso, la activación y el lote los barrí en ese mismo período y me quedé con alpha=1e-4, learning_rate_init=1e-3, ReLU y el lote de 256 que fijé para todo el banco (el valor por defecto de scikit-learn es auto, que acá serían 200 filas). Los modelos de comparación usan la configuración de sus propios posts, y las curvas y ejemplos de 2016-2026 son descriptivos.
¿Qué es una red neuronal?
Cada unidad de una capa combina linealmente lo que recibe, le suma un sesgo y le aplica una activación: acá, ReLU en las capas ocultas y la sigmoide en la salida binaria. Sin capa oculta, lo que queda calcula lo mismo que una regresión logística. Lo que cambia es que hay muchas en paralelo, que la salida de una capa alimenta a la siguiente, y que el ajuste corrige todos los pesos a la vez, propagando el error hacia atrás, el método que Rumelhart, Hinton y Williams popularizaron en 1986. La unidad suelta es más vieja: es el perceptrón de Rosenblatt (1958).
Una red sin capa oculta es exactamente una regresión logística: 3 pesos, frontera recta, AUC 0,838 en esos días y 0,803 en 2010-2012. Con 32 unidades la frontera se dobla y 2010-2012 sube a 0,806. Con dos capas de 32, 1.185 pesos, el ajuste en los 200 días trepa a 0,886 mientras 2010-2012 cae a 0,800: una brecha mayor, indicio de más sobreajuste en esta corrida. Los 200 días son una muestra balanceada, 100 con lluvia y 100 sin ella, no la frecuencia real.
Con dos variables y los mismos 200 días de los posts anteriores, una red sin capa oculta tiene 3 pesos y traza una recta: es exactamente una regresión logística. Con 32 unidades la frontera se dobla y el AUC en 2010-2012 sube de 0,803 a 0,806. Con dos capas de 32, 1.185 pesos para 200 días, el ajuste en esos días trepa a 0,886 y 2010-2012 baja a 0,800: la brecha se abre, indicio de sobreajuste. Esos 200 días están balanceados a propósito, 100 con lluvia y 100 sin ella, así que no reproducen la frecuencia real.
Que la frontera pueda doblarse tanto es lo que demostró Cybenko en 1989 y generalizó Hornik en 1991: con una capa oculta y suficientes unidades, una red puede aproximar cualquier función continua en un dominio compacto. El teorema dice que la forma existe, no que se pueda estimar con los datos disponibles.
Más grande no es mejor
Una regresión logística, que es esta misma red sin capa oculta, tiene 16 pesos y llegó a 0,850. Una capa oculta de 128 unidades, 2.177 pesos, llegó a 0,882 y fue la elegida. De ahí en adelante, las arquitecturas mayores evaluadas con este optimizador y este presupuesto quedaron más abajo: 3 capas de 64, 9.409 pesos, cayeron a 0,850, al nivel de la regresión logística en este período de validación. Reentrenada con 1984-2012, la red elegida dio 0,883 en 2016-2026.
Probé ocho tamaños sobre las 66.466 filas de 1984-2009, tres inicializaciones cada uno, midiendo en 2010-2012. La regresión logística, que es esta misma red sin capa oculta, tiene 16 pesos y dio 0,850. Una capa de 4 unidades ya sube a 0,873, y de 32 a 0,882. La elegida fue una capa de 128, con 2.177 parámetros entre pesos y sesgos y 0,882 en validación, que reentrenada con 1984-2012 dio 0,883 en la prueba.
De ahí para arriba, las arquitecturas mayores que evalué con este optimizador y este presupuesto quedaron más abajo: 512 unidades bajó a 0,879, dos capas de 128 (18.689 pesos) a 0,855 y tres capas de 64 a 0,850, empatando con la regresión logística. Varias de ellas agotaron las 200 épocas disponibles. Con estas 66.466 filas de selección y 15 variables, la red que convino fue pequeña, y es la que después reajusté con las 74.145. Es lo que Grinsztajn y coautores midieron en 2022 a lo largo de muchos conjuntos tabulares: los modelos de árboles siguen siendo difíciles de superar en este terreno.
Escalar antes de entrenar
Sin escalar y con la presión en kPa, la red llegó a AUC 0,874 con una pérdida logarítmica de 0,364; estandarizada, 0,884 y 0,349. Al escribir la misma presión en pascales, sin escalar, el AUC solo baja a 0,845 pero la pérdida se dispara a 6,81: se detuvo a las 30 épocas prediciendo en promedio 1,9 % de lluvia contra el 22,9 % observado en 2010-2012, así que el orden sobrevive y la probabilidad no. Escaladas, las dos unidades dan exactamente los mismos números.
Sin escalar y con la presión en kPa, la red llegó a 0,874 con pérdida logarítmica 0,364; estandarizada, 0,883 y 0,349. La trampa de unidades de la serie, escribir la misma presión en pascales, acá se comporta distinto que en los posts anteriores: el AUC apenas baja a 0,845, pero la pérdida se dispara a 6,81. El ajuste se detuvo a las 30 épocas y el modelo terminó prediciendo 1,9 % de lluvia en promedio contra el 22,9 % que llovió de verdad en 2010-2012. Ordena los días de forma parecida y miente al decir cuánto, que es un modo de fallar más difícil de notar que caer al azar. Escaladas, las dos unidades dan exactamente los mismos números.
Época a época
- 4
- 32
- 128 · 128
- filas de ajuste
- época de parada temprana
La pérdida final quedó muy por debajo de la primera en los tres tamaños, y eso no dice nada sobre si el modelo mejoró afuera: las dos capas de 128 (18.689 parámetros, entre pesos y sesgos) llegan a la pérdida más baja, 0,313, y en la época 40 dan 0,914 en las filas de ajuste contra 0,883 en 2010-2012, una brecha de 0,031. Con una capa de 32 la brecha es 0,018. La marca señala la época y nada más, y viene de otro protocolo, no de una parada sobre esta curva: un ajuste aparte con early_stopping, que aparta el 10 % de las filas de ajuste, vigila el acierto en ellas con paciencia 5 y restaura los mejores pesos. Ese se detuvo en la época 16 para la red de 32 y quedó en 0,874 en 2010-2012, contra 0,882 acá.
La pérdida final quedó muy por debajo de la inicial en los tres tamaños, aunque no baje en todas y cada una de las épocas, y no dice si el modelo mejoró afuera. Las dos capas de 128 llegan a la pérdida más baja, 0,313, y son las que más se separan: 0,914 en las filas de ajuste contra 0,883 en 2010-2012, una brecha de 0,031. Con una capa de 32 la brecha es 0,018.
El early_stopping de scikit-learn aparta al azar el 10 % de las filas de ajuste —después de que el escalador ya vio las 66.466— y corta cuando el acierto en ese pedazo deja de mejorar; no vigila el AUC ni respeta el corte temporal. Con paciencia 5 se detuvo a las 16 épocas para la red de 32 y quedó en 0,874 en 2010-2012, contra el 0,882 del ajuste largo. Son dos protocolos distintos, no la misma corrida detenida antes: cambian las filas que actualizan los pesos, la paciencia y el criterio de parada, y al final restaura los mejores pesos, que no son necesariamente los de la época 16. La curva de la derecha tampoco es un entrenamiento continuo: la medí reajustando de a una época, lo que reinicia el optimizador en cada pasada.
La misma red, diez veces
Diez corridas de la misma capa oculta de 128 unidades dieron AUC entre 0,8806 y 0,8842, una diferencia de 0,0037, con mediana 0,8825. También se detuvieron en momentos distintos: entre 159 y 200 épocas. No cambió nada más. Informar un solo número de una sola corrida esconde ese rango, que acá es tan ancho como la distancia entre dos modelos distintos.
Diez corridas con la misma arquitectura, las mismas filas y una sola diferencia, la semilla que fija los pesos iniciales y el orden de los lotes, dieron AUC entre 0,8806 y 0,8842, y se detuvieron entre las 159 y las 200 épocas. Esa diferencia de 0,0037 es del mismo orden que la que separa a dos arquitecturas distintas. Es el motivo por el que conviene fijar la semilla en el artefacto y reportar varias corridas: una sola corrida sirve para comparar resultados puntuales, pero no dice cuánto se mueve el entrenamiento. Y fijar la semilla no alcanza para reproducir un ajuste si cambia el orden de las filas, como se ve más abajo.
Los otros botones
La regularización L2, que en scikit-learn es alpha, movió la validación de 0,881 con 1e-6 a 0,884 con 0,01, y la hundió a 0,851 con 10, donde el ajuste en las propias filas de entrenamiento también cae a 0,860. El paso inicial importa menos de lo que parece dentro de un rango amplio: entre 1e-4 y 1e-2 la validación se mueve entre 0,881 y 0,883, y recién con 0,1 se rompe, a 0,868 en 32 épocas. Entre las tres activaciones, la sigmoide logística dio la mejor validación (0,8846) y la más lenta (17,2 s), contra 0,8823 y 14,7 s de relu. En los cuatro barridos la mayor mejora sobre la configuración base quedó dentro del rango que mueve la semilla, 0,0037: 0,0037 en regularización, 0,0021 en paso, 0,0024 en activación y 0,0031 en lote. Las caídas sí lo superan de lejos, como los 0,029 de alpha en 10, así que ese rango acota las mejoras y no las caídas. Comparar contra el rango de diez semillas es una decisión heurística, no una prueba de equivalencia, y las activaciones usan medianas de tres semillas mientras los otros barridos usan una sola. Con eso me quedé con la configuración base.
Los lotes de 32 filas tardaron 0,215 s por época, 4,4 veces más que los de 2.048 (0,049 s), y además quedaron más abajo: 0,879 contra 0,884. El lote completo, una sola actualización por época sobre las 66.466 filas, es el peor de los cuatro con 0,870. El menor número de actualizaciones es una explicación posible, no aislada acá: el presupuesto de épocas fue el mismo para los cuatro, el de actualizaciones no.
El tamaño del lote es el botón que más cambia el tiempo. Los lotes de 32 filas tardaron 0,215 s por época, 4,4 veces más que los de 2.048, y además quedaron más abajo en validación. El lote completo, con una sola actualización por época, fue el peor de los cuatro con 0,8704. El menor número de actualizaciones es una explicación posible, no aislada acá: igualé el presupuesto de épocas, no el de actualizaciones.
Probabilidades algo confiadas
Con las 74.145 filas, la red terminó con pérdida logarítmica 0,338, la tercera mejor de la serie, después del boosting (0,332) y del bosque (0,335), y bastante por debajo de la regresión logística (0,378). Mirando por tramos, se le nota la confianza en la banda alta: entre los días a los que les dio más de 0,9, predijo 0,947 en promedio y llovió el 0,872; entre los de 0,7 a 0,8, predijo 0,749 y llovió el 0,594. No hace falta calibrarla para ordenar, y sí conviene revisarla antes de usar el número como probabilidad.
Para números, y el techo que sí rompe
- red neuronal
- regresión lineal
- boosting
Entrenados solo con las filas de abril a septiembre, la máxima de mañana más alta que vieron al entrenar fue 32,97 °C, y los veranos reales de diciembre a febrero promediaron 29,63 °C. En los días reales de verano la red llegó a 38,10 °C, más allá de todo lo que había visto, y erró por 4,03 °C (la línea de arriba, con las demás variables fijas en su mediana, se queda mucho más abajo); el boosting no pasó de 29,56 °C y erró por 5,48 °C. La regresión lineal, la más simple de las tres, fue la más precisa acá: 1,72 °C. Extrapolar no es lo mismo que extrapolar bien: la red se sale de su rango, y eso por sí solo no la vuelve correcta. En la tarea normal, predecir la máxima de mañana con todas las filas, erró por 1,46 °C contra 1,44 °C del boosting.
Para predecir la máxima de mañana con todas las filas, la red erró por 1,46 °C en promedio, entre el boosting (1,44 °C) y la regresión lineal (1,70 °C).
La prueba de extrapolación de la serie es más interesante. Entrenados solo con las filas de abril a septiembre de Santiago, y preguntados por las de diciembre a febrero de 2016-2026, la máxima de mañana más alta que vieron al entrenar fue 32,97 °C. La red predijo hasta 38,1 °C, por encima de todo lo que vio, y erró por 4,03 °C; el boosting no pasó de 29,56 °C y erró por 5,48 °C. Salirse del rango no la vuelve correcta: la regresión lineal, la más simple de las tres, fue la más precisa acá con 1,72 °C. Es un corte por estación, no una prueba limpia fuera del rango: el verano cambia varias variables a la vez.
La red contra toda la serie
A un cuarto del tiempo real.
Las 27.256 filas, en tiempo real.
Serializados, la red ocupa 81 KB, el boosting 2,1 MB, el bosque 124 MB y KNN 9,5 MB. Puntuar una fila tomó 0,40 ms a la red, 3,09 ms al boosting y 1,92 ms a KNN.
Con las mismas filas, remuestreé 2.000 veces los bloques ciudad-año de 2016-2026 para comparar el AUC en pares. Contra el boosting, la red quedó en −0,00002 con un intervalo de −0,0025 a 0,0022, y contra el bosque en 0,0006, de −0,0021 a 0,0030: los dos intervalos cruzan el cero. Contra KNN quedó 0,013 arriba, contra el árbol 0,021, contra la regresión logística 0,036 y contra Naive Bayes 0,061, y esos cuatro intervalos no cruzan el cero.
El ajuste de la red tomó 13,4 s con un hilo en la corrida de comparación. Con ocho hilos tardó lo mismo, 13,4 s: los hilos no ayudaron. En la corrida de costo tardó 8,5 s, porque con otro orden de filas se detuvo a las 104 épocas.
Dónde vive una red neuronal en un sistema real
Medido con un hilo sobre las 74.145 filas, todo de la corrida de comparación: una capa oculta de 128 unidades tarda 13,4 s, serializada ocupa 81 KB, puntúa una fila en 0,40 ms y todo el período de prueba en 0,007 s, con AUC 0,883 y pérdida logarítmica 0,338. El boosting llega a AUC 0,883 en 2,6 s, pero ocupa 2,1 MB y tarda 3,09 ms por fila. La regresión logística: 0,049 s, AUC 0,847. Con ocho hilos el ajuste tardó 13,4 s, lo mismo que ese hilo único. Una corrida de costo aparte, con las filas en otro orden, se detuvo a las 104 épocas en 8,5 s y 80 KB; ahí no se mide calidad.
- Predicción en línea con muchas consultas. Puntuar una fila toma 0,40 ms, la latencia más baja entre los modelos que quedaron arriba en AUC, y el artefacto entero pesa 81 KB.
- El escalador dentro del artefacto. El artefacto tiene que conservar el preprocesamiento con el que se entrenó. En este experimento, entrenar sin escalar y con la presión en pascales perjudicó mucho más la pérdida logarítmica que el AUC.
- Semilla fija y varias corridas. Sin eso el mismo código entrega números distintos y no se puede saber si un cambio mejoró algo.
- Datos que no entran en una tabla. Donde una red se despega de verdad es en texto, imágenes o audio, no en quince columnas numéricas.
Cuándo la elegiría: cuando la latencia por fila y el tamaño del artefacto importan, cuando hay señal no lineal que un modelo lineal deja afuera, o cuando el problema deja de ser tabular. Cuándo no: para una tabla mediana donde un boosting llega al mismo AUC en un quinto del tiempo y sin escalar, con la configuración de boosting que fijé para esta comparación.
Fuentes
- Rosenblatt, F. (1958). «The perceptron: A probabilistic model for information storage and organization in the brain». Psychological Review, 65(6), 386–408. DOI 10.1037/h0042519.
- Rumelhart, D. E., Hinton, G. E. y Williams, R. J. (1986). «Learning representations by back-propagating errors». Nature, 323, 533–536. DOI 10.1038/323533a0.
- Cybenko, G. (1989). «Approximation by superpositions of a sigmoidal function». Mathematics of Control, Signals and Systems, 2(4), 303–314. DOI 10.1007/BF02551274.
- Hornik, K. (1991). «Approximation capabilities of multilayer feedforward networks». Neural Networks, 4(2), 251–257. DOI 10.1016/0893-6080(91)90009-T.
- Kingma, D. P. y Ba, J. (2015). «Adam: A Method for Stochastic Optimization». ICLR 2015. Es el optimizador por defecto de
MLPClassifier. - Grinsztajn, L., Oyallon, E. y Varoquaux, G. (2022). «Why do tree-based models still outperform deep learning on typical tabular data?». NeurIPS Datasets and Benchmarks.
- scikit-learn 1.7, redes neuronales supervisadas.
- NASA POWER, Daily API y fuentes de datos.
Comentarios
Todavía no hay comentarios. El primero es tuyo.