Fundamentos · Machine Learning supervisado Entregado · 9,00 / 10

Nueve millones de equipos
en ocho gigas de RAM

Un modelo LightGBM que estima si una máquina Windows acabará infectada, entrenado sobre la telemetría real de Microsoft. El dataset pesa 14 GB al abrirlo por las bravas; el portátil tenía 8. El proyecto trata sobre todo de lo segundo: qué hay que decidir antes de modelar para que el modelo llegue a existir.

0,7356AUC · validación
8.921.483registros procesados
2,1 GBen RAM · desde 14 GB
19,5 minentrenamiento · M2

El cuello de botella

El límite no era el modelo. Era la memoria.

Con la lectura estándar de pandas, los 8,9 millones de filas del dataset de Microsoft ocupan unos 14 GB: el sistema empieza a tirar de disco y el kernel muere antes de llegar a entrenar nada. Cuatro decisiones tomadas antes de la primera línea de modelado lo dejaron en 2,1 GB.

Tipado Mapa explícito de dtypes aplicado en la lectura, no después: int8 para banderas, category para texto repetido, float32 para numérico. Sin él, pandas infiere int64 y object y multiplica el gasto por ocho.
Filtrado Auditoría de vacíos previa y carga selectiva con usecols: 83 columnas del origen, 69 leídas. Las descartadas nunca llegan a memoria.
Checkpoints Tres hitos serializados en Parquet con compresión snappy — _1_ingested · _2_clean · _3_engineered. Si algo revienta a mitad, se retoma desde el último en menos de dos segundos en lugar de reprocesar.
Dev / Prod Una bandera DEBUG_MODE alterna entre cargar el 10 % (iterar rápido) y el 100 % (ejecución final). El pipeline es el mismo; sólo cambia cuánta realidad entra.

Nota de la bitácora: float16 se descartó a mitad de camino — el motor C de pandas no lo admite (KeyError: dtype('float16')). Se sustituyó por float32 y se dejó escrito en el notebook, con el error y el porqué. Ahorra menos memoria; funciona.


Cómo se construyó

Seis fases, y el 80 % del trabajo antes de modelar

01 · Ingesta Carga con esquema de tipos y columnas filtradas en origen. 14 GB → 2,1 GB (2.178 MB medidos en RAM).
02 · Auditoría Objetivo balanceado: 50,14 % sano / 49,86 % infectado — sin necesidad de remuestreo. 21 columnas con vacíos, y seis cuasi-constantes detectadas por varianza (IsBeta y PuaMode tenían el 100 % de las filas con el mismo valor).
03 · Limpieza Fuera lo irrecuperable (más del 50 % vacío) y lo invariante. Normalización de texto: SmartScreen venía con mayúsculas y minúsculas mezcladas, lo que inventaba categorías que no existían.
04 · Variables Descomposición vectorizada de las versiones de software en mayor y menor: AvSigVersion pasa de 7.163 valores distintos a dos columnas ordenables. Un string de versión no dice nada; el número de versión sí.
05 · Modelado LightGBM con num_leaves=60, learning_rate=0.05 y 2.000 rondas. Sin one-hot: el modelo trata las categorías de forma nativa, y codificarlas habría inflado el dataset por cientos de columnas justo cuando la memoria era el problema.
06 · Evaluación AUC, matriz de confusión e importancia de variables sobre 1.784.297 registros que el modelo no vio jamás.

El entrenamiento

Primero el 10 %, y sólo entonces los nueve millones

Entrenar dos veces sale más barato que entrenar mal una. La primera pasada usa el 10 % de los datos (891.509 filas) y termina en 42 segundos con un AUC de 0,7101: suficiente para saber que el pipeline se sostiene. La segunda pasa el dataset entero — 7.137.186 filas de entrenamiento, 71 variables, 28 de ellas categóricas — y tarda 19 minutos y 31 segundos.

AUC por ronda de boosting · 2.000 árboles entrenamientovalidación

Ronda 50 — entrenamiento 0,7046 · validación 0,7039. Ronda 2.000 — entrenamiento 0,7439 · validación 0,7356. Las dos series suben juntas de principio a fin.

La distancia entre las dos líneas al final es de 0,0083 de AUC. Es la señal de que el modelo aprendió del fenómeno y no de memoria: si se hubiese aprendido los datos, la línea de entrenamiento se despegaría hacia arriba y la de validación se quedaría plana o caería.

Los resultados

Un AUC no dice a quién le falla

AUC 0,7356 sobre el conjunto de validación. La competición original de Kaggle se movía en 0,67–0,71, pero los dos números no son comparables: allí se puntuaba contra un conjunto de prueba desplazado en el tiempo —máquinas de meses posteriores, con otras versiones y otras campañas de malware— y aquí la validación es un corte aleatorio del mismo fichero. El segundo examen es más fácil, y decir lo contrario sería regalarse una victoria. Lo que el AUC sí sostiene es que el modelo separa las dos clases muy por encima del azar. Y como resume la curva entera, para saber qué hace en un despliegue real hay que bajar a los cuatro números que salen de fijar un umbral: estos son los suyos, sobre 1.784.297 equipos.

Pieza del instrumento La báscula de los errores
Dice: sano Dice: infectado Sano
602.279acierto
290.239falsa alarma
Infectado
302.492se le escapa
589.287acierto
589.287 ÷ 891.779
aciertos entre infectados reales
66,08 %
50 % · azar100 %

De cada 100 equipos realmente infectados, el modelo señala 66. Los otros 34 pasan desapercibidos.

Los dos errores están casi empatados: 290.239 falsas alarmas frente a 302.492 infecciones que se le escapan. El modelo no se ha decantado por ninguno de los dos miedos — y esa simetría es una decisión, no una casualidad: mover el umbral cambia el reparto. Una infraestructura crítica querría menos escapes aunque suban las falsas alarmas; un equipo doméstico, lo contrario.

Los cuatro números son la fuente. Las métricas de arriba no están escritas a mano: se calculan al vuelo desde las cuatro celdas de la matriz, igual que las escalas del resto del portfolio. Si un conteo cambiara, cambiarían solas.


Qué mira el modelo

Manda el estado del sistema, no la marca del equipo

Las doce variables que el modelo de producción usó más veces para decidir. Arriba están la versión del sistema operativo y el estado del antivirus; la geografía entra pronto y con fuerza; el hardware aparece tarde y como aproximación de otra cosa — la gama del equipo, y con ella el tipo de usuario.

1Census_OSVersionSistema
2AVProductStatesIdentifierAntivirus
3CountryIdentifierGeografía
4AvSigVersion_2Antivirus
5Census_OSInstallTypeNameSistema
6OsBuildLabSistema
7AppVersion_2Antivirus
8SmartScreenProtección
9Census_SystemVolumeTotalCapacityHardware
10CityIdentifierGeografía
11LocaleEnglishNameIdentifierGeografía
12Census_ProcessorModelIdentifierHardware

Qué mide exactamente este ranking: el número de veces que el modelo usó cada variable para partir una rama, no la ganancia que obtuvo al hacerlo. Son dos preguntas distintas — «cuánto la consulta» y «cuánto le rinde» — y no dan el mismo orden. La longitud de las barras es relativa a la primera. Ordenando por ganancia sobre la muestra de desarrollo, quien encabeza la lista es SmartScreen: pocas consultas, mucho rendimiento por consulta.

Lo que se sostiene en las dos lecturas

El estado del antivirus y sus firmas. AVProductStatesIdentifier y AvSigVersion_2 —la versión de firmas ya descompuesta en la fase 04— están arriba se mire como se mire. Traducido: no protege tanto tener antivirus como tenerlo al día y encendido. Y el peso de SmartScreen apunta al mismo sitio — quien apaga la protección que ya trae el sistema aparece en el lado infectado con más frecuencia.


Lo que este trabajo no hace

Los tres huecos, en su sitio

El proyecto se entregó como práctica del máster y se corrigió con un 9,00. La corrección señaló tres carencias reales, y tienen más valor aquí que en un cajón: enseñan dónde estaba el límite del trabajo.

El EDA se hizo a ciegas La exploración fue numérica —vacíos, cardinalidad, balance— sin una sola gráfica. No hay constancia visual de qué variables separan mejor las dos clases. Cuatro o cinco histogramas condicionados al objetivo lo habrían resuelto antes de modelar.
Un solo modelo, sin validación cruzada Se entrenó LightGBM y se dio por bueno. Una comparación honesta pide al menos dos alternativas y búsqueda de hiperparámetros con validación cruzada. El 0,7356 es un resultado de una sola tirada, no el techo de nada.
El encoding no quedó explicado Las categóricas se pasaron directamente a LightGBM sin documentar que el modelo las gestiona de forma nativa. La decisión era correcta; el notebook no la justificaba, y una decisión sin escribir se lee como un olvido.

Con qué está hecho

Herramientas

LightGBM · modelo pandas · dtypes y categóricas NumPy scikit-learn · split y métricas pyarrow · checkpoints Parquet Plotly · ROC y matriz interactivas joblib · modelo y reglas serializadas gc · liberación activa de memoria MacBook M2 · 8 GB

El principio

La restricción no fue el obstáculo del proyecto. Fue lo que lo obligó a estar bien diseñado.