Skip to content

5. Modelos probabilistas

yushanyang09 edited this page May 6, 2025 · 7 revisions

Predicción del despegue en el estado siguiente

Para realizar esta predicción primero hemos tenido que definir qué se considera el «estado siguiente». Nuestra decisión (basada en la distribución de la variable takeoff_time) ha sido discretizar la variable respuesta en seis intervalos de 30 segundos (el último de ellos abarca todos los valores superiores). La nueva variable será la variable objetivo a la que hemos nombrado will_takeoff_afterX.

Se han entrenado dos modelos. El primero es más simple y sirve como baseline. La evaluación se ha realizado principalmente atendiendo al accuracy y a la matriz de confusión.

Hay una parte de preprocesamiento común a ambos modelos, en la que se eliminan las variables que contienen información del futuro o dependen de él para evitar data leakage, así como otras variables de tipo ID o que son irrelevantes para el modelo.

Además, se prepara el conjunto de validación para las pruebas de los modelos. Para ello, dentro del conjunto de entrenamiento, hemos establecido un corte temporal del 1 al 14 de enero para dividir en conjunto de validación (observaciones dentro de dicho corte) y entrenamiento (observaciones fuera del corte).

Naïve Bayes

En primer lugar, hemos desarrollado Naïve Bayes como el modelo base. En este primer caso, el preprocesamiento continuó con la eliminación de las variables que podrían contener valores negativos (pues no son soportados durante el entrenamiento), esto es, únicamente las variables relacionadas con la temperatura.

A continuación, indexamos las variables categóricas usando StringIndexer de PySpark. El pipeline del modelo incluirá esta indexación, además del transformador VectorAssembler que combina todas las variables explicativas en un solo vector.

Pero la mayor dificultad al enfrentar este modelo, ha sido la incapacidad inicial para predecir las distintas clases debido a que éstas estaban muy desbalanceadas. Para tratar de mejorar esto, añadimos weightCol="weight" para que el modelo Naïve Bayes diera más importancia a las clases minoritarias durante el entrenamiento. Los pesos se calcularon de forma inversa a la frecuencia de cada clase en el conjunto de entrenamiento.

Para optimizar el modelo, realizamos una búsqueda manual de hiperparámetros mediante validación hold-out temporal. Concretamente, se definió una cuadrícula probando diferentes valores para los parámetros smoothing y modelType del modelo Naïve Bayes. Tras evaluar las combinaciones sobre el conjunto de validación, se seleccionó como mejor configuración smoothing=0.0 y modelType="multinomial", obteniendo finalmente una precisión del 32.61% sobre el conjunto de test.

Hidden Markov Model (HMM)

Para este segundo modelo, no existe una biblioteca en PySpark que incluya el HMM por defecto (como sí lo hace con Naïve Bayes). Por tanto, y dado que para este ejercicio era obligatorio utilizar bibliotecas en vez de implementar nuestro propio algoritmo, después de preparar los datos, los hemos pasado a pandas para poder usar la biblioteca hmmlearn.

Este modelo solo acepta números reales, por lo que aplicamos Label Encoding a las variables categóricas (mejor que One-hot Encoding ya que se trata de secuencias). Además, ya que queremos usar los datos como secuencia temporal, tenemos que respetar el orden por timestamp.

Tras entrenar un primer modelo, decidimos automatizar la codificación de las variables categóricas para tratar de mejorar los resultados de 3.73% de precisión haciendo un mapping automático. Con esta nueva función que transforma las categóricas a numéricas como un Label Encoding “manual”, hacemos una búsqueda de los mejores hiperparámetros mediante validación hold-out temporal (mismo proceso que en el modelo anterior). Tras varias pruebas, se obtiene un 28.29% como mejor precisión en test.

Sin embargo, aún parecía insuficiente, por lo que decidimos tratar el problema de desbalance de clases, en este caso, haciendo oversampling: aumentamos artificialmente el número de instancias de las clases minoritarias mediante muestreo con reemplazo, igualando su tamaño al de la clase mayoritaria.

Posteriormente, realizamos otra búsqueda manual de hiperparámetros probando diferentes configuraciones para el modelo, variando el número de componentes, el tipo de covarianza, el número máximo de iteraciones y la tolerancia. La mejor combinación encontrada tras el balanceo fue: n_components = 5, covariance_type = full, n_iter = 100, tol = 0.01, logrando una accuracy de 36.67% en validación y de 28.83% en test.

Cabe destacar que, tanto en Naïve Bayes como en HMM, hemos probado predecir la variable objetivo considerando intervalos de 30, 60 y 100 segundos. Observamos que, al aumentar el intervalo a 100 segundos, el accuracy podía llegar hasta el 52%; sin embargo, las matrices de confusión mostraban que el modelo solo era capaz de predecir correctamente una o dos clases principales (las clases mayoritarias). Al aumentar el intervalo, disminuye el número de clases y cambia su distribución, concentrándose la frecuencia de ejemplos en pocas clases, lo que explicaría los aparentes mejores resultados. En cambio, con 30 segundos, al menos el modelo es capaz de identificar más de dos clases de manera significativa, lo que nos pareció más adecuado para el objetivo del ejercicio.

img

Clasificación de casos

Para la construcción de los modelos de este apartado hemos empleado la librería NumPyro. Hemos seguido dos enfoques diferentes:

Día de la semana

Decidimos calcular la probabilidad de que un nuevo caso fuera un día de la semana laboral (de lunes a viernes), o bien fin de semana/festivo (sábado y domingo). Cabe destacar que, debido a la escasez de días festivos presentes en el conjunto de datos, decidimos no hacer una clase exclusiva para ellos y optamos por unirlos a la clase de fin de semana, ya que como se vio en un apartado anterior, el tráfico en el aeropuerto es menor tanto en días festivos como en fines de semana.

Tras la creación de la variable respuesta (considerando los días laborales como la clase negativa y los fines de semana/festivo como la clase positiva), realizamos el preprocesamiento de los datos, codificando las variables categóricas y escalando las numéricas, puesto que NumPyro solo acepta tipos numéricos.

El principal problema lo supuso el desbalance de clases. La clase negativa contaba con 83752 ejemplos, mientras que la positiva tenía 39981. Utilizamos SMOTE como técnica de oversampling sobre la clase minoritaria hasta igualar el número de ejemplos en ambas clases.

A continuación implementamos el modelo de regresión logística. Utiliza una distribución Bernoulli para modelar las probabilidades de pertenencia a una clase. Para el entrenamiento ejecuta un muestreo MCMC usando el No-U-Turn Sampler (NUTS) para inferir los parámetros del modelo.

Tras la evaluación en el conjunto de test extraemos las siguientes conclusiones: el modelo presenta una precisión relativamente baja (29,22), lo que indica que tiene dificultades para identificar correctamente la clase positiva (fin de semana/festivo) en comparación con la clase negativa (día laboral). Si analizamos la precisión individual de cada clase vemos un 81% para la clase negativa frente a un 29% de la positiva. Esto puede deberse a un sobreajuste debido al oversampling realizado. El modelo puede estar sobreajustado a las nuevas instancias sintéticas, lo que se traduce en una mala generalización.

Confusion Matrix ROC Curve

Categoría de turbulencia

Como segundo enfoque decidimos clasificar un nuevo caso en la categoría de turbulencia correspondiente (Heavy, High performance, High vortex aircraft, Light, Medium 1, Medium 2).

Realizamos el preprocesado de los datos de la misma forma que para el modelo anterior. Debido al gran desbalance de clases (llegando a haber una diferencia de más de 25000 muestras entre algunas clases) decidimos agrupar los datos por callsign y día para después seleccionar un mensaje aleatorio de cada agrupación. De esta forma reducimos la diferencia entre clases y aplicamos oversampling como anteriormente, quedándonos con unas 1500 muestras de cada clase.

Seguidamente implementamos el modelo de tipo One-vs-All, donde para cada clase se aprenden parámetros alpha (coeficientes de características) y beta (sesgos), y se modela la probabilidad de cada una usando una distribución Categorical. Obtuvimos unos resultados en test poco concluyentes (29,9% de accuracy y 33,9% de precisión), por lo que decidimos reentrenar el modelo uniendo las clases Medium 1 y Medium 2 en una única. Tras esto obtuvimos unas métricas globales relativamente más elevadas (una precisión del 44,6% y un accuracy del 41,9%).

Si nos fijamos en la matriz de confusión de más abajo podemos ver como las dos clases cuya clasificación es más acertada son High vortex aircraft y Medium, que además son las clases mayoritarias (antes de aplicar oversampling). Cabe destacar que el modelo tiende a confundir estas dos clases entre sí. En cuanto al resto de clases (Heavy, High performance, Light) vemos que la clasificación es mala a pesar del sobremuestreo realizado, seguramente debido a la escasez de ejemplos originales pertenecientes a estas, en comparación a las dos clases mayoritarias.

img

Clone this wiki locally