File size: 22,842 Bytes
96bba34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
# SADAR

**Smart Anomaly Detection for Aviation Routes**

Memoria técnica

---

**Proyecto:** SADAR · Flight Conformance Monitor
**Dominio:** Vigilancia de tráfico aéreo · datos ADS-B
**Aeropuerto de estudio:** Madrid-Barajas (LEMD)
**Enfoque:** Aprendizaje profundo de una sola clase para detección de anomalías en trayectorias
**Fecha:** 2026

---

## Resumen ejecutivo

SADAR es un sistema de aprendizaje profundo que aprende el patrón normal de las
operaciones de aproximación y despegue en Madrid-Barajas (LEMD) a partir de datos de
vigilancia ADS-B y señala en tiempo real cualquier trayectoria que se aparte de ese
patrón. El sistema está concebido como **monitor de conformidad de vuelos**: no clasifica
eventos concretos, asigna a cada vuelo del espacio aéreo una puntuación interpretable de
anomalía para que un operador pueda revisar los casos que quedan fuera de la
distribución aprendida.

Se entrenan tres autoencoders secuenciales en igualdad de condiciones sobre unos 20.000
vuelos reales obtenidos de la red OpenSky (un autoencoder LSTM, un autoencoder
Transformer y un VAE-LSTM), junto con un baseline no secuencial basado en Isolation
Forest. Los cuatro detectores se evalúan sobre el mismo conjunto de test y sobre un banco
sintético con cinco tipos de inyección y varias intensidades. Se selecciona el
**VAE-LSTM** como modelo de producción: obtiene la mejor PR-AUC sobre datos reales
(0,299) y la mejor ROC-AUC media en el banco sintético (0,792). También se evalúan dos
estrategias de ensemble (consenso y más sensible) y se descartan, porque ninguna mejora
al mejor modelo individual.

El modelo seleccionado se sirve a través de una aplicación FastAPI y de un dashboard
React + Vite que combina un radar en vivo estilo torre de control, un ranking de
anomalías, una página de métricas y un simulador interactivo. Todo el sistema es
reproducible desde una única imagen Docker y está listo para desplegarse en Hugging Face
Spaces.

---

## 1. Motivación y alcance

La monitorización de trayectorias es una función central de la gestión del tráfico
aéreo. Hoy se apoya en reglas deterministas y en supervisión humana: separación,
perfiles de descenso, esperas o códigos de transpondedor de emergencia se vigilan
contra umbrales fijos. Esas reglas funcionan bien para las situaciones para las que
fueron diseñadas, pero no pueden anticipar comportamientos que sean inusuales sin ser
una violación de manual.

SADAR explora un enfoque complementario, basado en datos. En lugar de codificar reglas,
el sistema **aprende** cómo es una operación normal en LEMD a partir de una muestra
amplia de vuelos reales, y trata cada nueva trayectoria como más o menos compatible con
esa distribución. La salida es una puntuación continua de conformidad que el operador
puede ordenar, filtrar y umbralizar.

El alcance del proyecto es deliberadamente acotado:

- **Qué hace.** Detecta desviaciones respecto al patrón normal de tráfico de un único
  aeropuerto (LEMD) a partir de un conjunto fijo de variables dinámicas extraídas de las
  observaciones ADS-B.
- **Qué no hace.** Predecir eventos operativos concretos, sustituir al controlador,
  emitir recomendaciones de seguridad certificadas, ni generalizar sin reentrenamiento a
  aeropuertos con procedimientos distintos.

Esta formulación como **monitor de conformidad** es la que hace tratable el problema con
los datos disponibles: solo requiere ejemplos de vuelo normal, que son abundantes, y
deja clara la interpretación de la salida ("esta trayectoria no se parece a las que el
modelo ha visto"), sin sobrevender.

---

## 2. Datos

### 2.1 Fuente

El dataset se construye a partir de observaciones ADS-B captadas por la red OpenSky en
la zona terminal de Madrid-Barajas. Cubre aproximadamente 18 días de operaciones
muestreados entre junio de 2017 y marzo de 2020. Cada aeronave se reporta una vez cada
10 segundos, la cadencia natural de ADS-B.

| Propiedad | Valor |
|---|---|
| Trayectorias totales | ≈ 20.000 (≈ 950 a 1.200 por día) |
| Filas por día | 140.000 a 240.000 |
| Columnas | 21 |
| Puntos por vuelo (mín · mediana · máx) | 40 · 188 · 1.246 |

### 2.2 Variables

El esquema en bruto contiene información posicional (latitud, longitud, tiempo),
dinámica (altitud barométrica y geométrica, velocidad respecto al suelo, rumbo, régimen
vertical), campos derivados (distancia a pista, fase de vuelo), identidad (ICAO24,
indicativo, identificador de vuelo) y estado del transpondedor (squawk, indicador de
"en tierra", indicador de alerta, SPI y último contacto). Un campo, `operation`, está
vacío en todo el dataset y se descarta.

### 2.3 Calidad y limpieza

Un análisis de perfilado sobre el dataset completo revela varios problemas que se
gestionan en el pipeline de preprocesado:

- **Valores ausentes.** `geoaltitude` falta en el 34,9 % de las filas, `baroaltitude` en
  el 19,6 %, los campos cinemáticos (`velocity`, `heading`, `vertrate`) en torno al
  19 %. El resto se queda por debajo del 4 %.
- **Archivo duplicado.** Un día llega dos veces con nombres distintos y se deduplica por
  hash de contenido.
- **Días vacíos o erróneos.** Algunos días llegan sin filas o con errores en el
  manifest y se descartan.
- **Huecos de cobertura.** Cerca del 8 % de los vuelos en aire muestran un salto
  superior a 120 s entre observaciones consecutivas. Casi siempre son artefactos de
  cobertura del receptor, no eventos operativos, por lo que se utilizan como
  característica, jamás como etiqueta.

Tras la limpieza, el dataset contiene un conjunto estable de operaciones normales en
LEMD que abarca varias estaciones e incluye el inicio de 2020, lo que sirve además como
cambio de distribución natural para poner a prueba el split temporal.

### 2.4 Observaciones destacadas

El análisis exploratorio confirma un pequeño conjunto de casos raros que se reservan
únicamente para validación:

- Cuatro vuelos llevan un código de transpondedor de emergencia en algún punto.
- Aproximadamente un centenar de vuelos muestran un patrón claro de motor y al aire
  (aproximación seguida de ascenso sostenido).

Ninguno de estos vuelos entra en el conjunto de entrenamiento. Se utilizan como prueba
de cordura del modelo desplegado.

---

## 3. Formulación del problema

El dataset contiene muchos vuelos normales y casi ninguna anomalía etiquetada. Eso
descarta la clasificación supervisada y apunta al **aprendizaje de una sola clase**:
entrenar un modelo que capture la distribución de trayectorias normales y puntuar los
nuevos vuelos según su compatibilidad con esa distribución.

En la práctica, los tres modelos profundos son **autoencoders** entrenados solo con
vuelos normales. El objetivo de entrenamiento es reconstruir la ventana de entrada a
partir de una representación latente comprimida; en inferencia se utiliza el **error de
reconstrucción** como puntuación de conformidad. Una trayectoria parecida a los patrones
normales se reconstruye con precisión y recibe un score bajo; una trayectoria que se
aparta de esos patrones es más difícil de reconstruir y recibe un score alto.

Esta formulación encaja con el contexto operativo por tres motivos. Sólo necesita datos
normales, que son los únicos disponibles a escala. Produce una puntuación continua e
interpretable en lugar de una etiqueta dura, lo que es la salida adecuada para una
herramienta de apoyo a un operador humano. Y se comporta bien ante modos de fallo
desconocidos: cualquier trayectoria que el modelo no haya aprendido a reconstruir
emerge como anómala con independencia de qué es lo que la hace inusual.

---

## 4. Pipeline de preprocesado

El pipeline transforma los parquet en bruto en tensores de longitud fija ya
estandarizados y listos para entrenar. Cada paso está implementado como una función
pequeña y testeable bajo `src/sadar/data/`.

1. **Carga y fusión.** Se leen todos los parquet bajo `$SADAR_DATA_DIR` con pyarrow, se
   concatenan y se deduplican. Los días vacíos o erróneos se descartan.
2. **Transformación de coordenadas.** La latitud y la longitud se proyectan a un sistema
   métrico relativo a pista con `pyproj`. Así el modelo es robusto a la curvatura de las
   coordenadas y recibe metros como unidad.
3. **Codificación del rumbo.** El rumbo se codifica como `(sin(rumbo), cos(rumbo))` para
   evitar la discontinuidad entre 0 y 360 grados.
4. **Tratamiento de ausentes.** Los huecos cortos dentro de una trayectoria por lo demás
   completa se rellenan con interpolación lineal. Las trayectorias con demasiados
   ausentes se descartan.
5. **Resampleado.** Cada vuelo se resamplea a una rejilla uniforme de 10 s, que coincide
   con la cadencia nominal de ADS-B.
6. **Ventanado.** Cada trayectoria resampleada se trocea en ventanas de longitud fija.
   La longitud de ventana es un hiperparámetro definido en
   `configs/preprocessing.yaml`.
7. **Estandarización.** Cada variable se normaliza a media cero y varianza unidad. El
   escalador se ajusta **solo con el conjunto de entrenamiento** para evitar fugas, y se
   guarda como `data/processed/scaler.npz`, de manera que la misma transformación se
   aplica en inferencia.
8. **Split sin fugas.** La división se hace conjuntamente por `flight_id` y por fecha:
   ningún vuelo aparece en más de un conjunto, y el test es estrictamente posterior en
   el tiempo al entrenamiento. Los años 2017 a 2019 se usan para entrenamiento y
   validación; 2020 se reserva para test. Este split realista es lo que permite tomar
   las cifras de latencia con confianza.
9. **Limpieza del set de entrenamiento.** Los pocos vuelos con squawks de emergencia y
   los go-around sospechosos se eliminan del entrenamiento. Sólo trayectorias
   "normales" entran al modelo.

La entrada de todos los modelos profundos es una ventana de siete variables:
`[x_rel, y_rel, baroaltitude, velocity, sin_hdg, cos_hdg, vertrate]`.

---

## 5. Modelos

### 5.1 Baseline Isolation Forest

Detector de referencia, no secuencial. Cada ventana se resume por estadísticos por
variable (media, desviación, mínimo, máximo) y se alimenta a un Isolation Forest. El
baseline sirve para cuantificar cuánto añade realmente el modelado secuencial.

### 5.2 Autoencoder LSTM

Un encoder LSTM de dos capas comprime la ventana de entrada en un vector latente, y un
decoder LSTM espejado la reconstruye. Se entrena de extremo a extremo con MSE y el loop
de entrenamiento compartido descrito más abajo. Es la arquitectura caballo de batalla:
estable, rápida en inferencia y alineada con la bibliografía sobre modelado de
trayectorias ADS-B.

### 5.3 Autoencoder Transformer

El mismo esqueleto encoder-decoder, pero con atención multi-cabeza en lugar de
recurrencia. El Transformer captura dependencias a largo plazo dentro de la ventana sin
el cuello de botella secuencial de las LSTM, a cambio de más parámetros y una superficie
de hiperparámetros mayor.

### 5.4 VAE-LSTM (modelo de producción seleccionado)

Un autoencoder variacional construido sobre encoder y decoder LSTM. En lugar de producir
un único vector latente, el encoder produce una distribución posterior; el decoder
reconstruye a partir de una muestra. La función de pérdida es la ELBO habitual: MSE de
reconstrucción más un término KL que regulariza la posterior hacia una gaussiana
estándar, escalado por un factor beta. Esto aporta una interpretación probabilística al
score y se comporta mejor en el paso de selección de umbral.

### 5.5 Ensembles (evaluados y descartados)

Como parte de la comparación se evalúan dos estrategias de ensemble. Tras calibrar cada
modelo con z-score sobre las normales de validación, los tres modelos profundos se
combinan por la **media** de sus scores (consenso) o por el **máximo** (más sensible).
Ninguna combinación supera al mejor modelo individual en el test real, así que el
ensemble queda documentado y descartado. El detector final es el VAE-LSTM en solitario.

### 5.6 Infraestructura de entrenamiento compartida

Los tres modelos profundos comparten el mismo loop de entrenamiento, implementado una
sola vez en `src/sadar/models/training.py`. El loop usa:

- **Adam** con weight decay,
- planificador **ReduceLROnPlateau**,
- **early stopping** sobre la pérdida de validación,
- **MLflow** para tracking (losses, hiperparámetros, mejor checkpoint),
- **Optuna** para búsqueda de hiperparámetros, usado sobre todo en el VAE-LSTM.

Cada arquitectura tiene su propio fichero YAML bajo `configs/`. La reproducibilidad se
garantiza con semillas fijas y guardando junto al checkpoint la configuración exacta de
preprocesado utilizada.

---

## 6. Banco de anomalías sintéticas

Como las anomalías reales son escasas y carecen de etiqueta, se construye un banco
controlado sobre los vuelos normales del test. Cada escenario parte de una ventana
normal real e inyecta una perturbación conocida y etiquetada que se aplica de forma
gradual a partir de la mitad de la ventana. Se implementan cinco tipos de inyección,
cada uno en varias intensidades:

| Tipo | Descripción |
|---|---|
| Desviación de ruta | Salida lateral del corredor, parametrizada en metros. |
| Anomalía de altitud | Desplazamiento de altitud inconsistente con la fase. |
| Anomalía de velocidad | Aceleración o deceleración multiplicativa. |
| Holding | Giro de 360 ° repetido con periodo configurable. |
| Congelado de transpondedor | La señal se mantiene fija desde un punto dado. |

El banco produce etiquetas de verdad (cada inyección sabe exactamente cuándo empieza) y
por tanto permite dos métricas que los datos reales no pueden dar: **PR-AUC por tipo de
anomalía** y **latencia de detección** (mediana de segundos entre el inicio de la
inyección y el primer instante en que el score por paso cruza el umbral de alerta).

El banco sintético se utiliza únicamente para evaluación. Ninguna ventana sintética
entra jamás en el entrenamiento.

---

## 7. Evaluación

### 7.1 Conjunto de test real

Los cuatro detectores se puntúan sobre el mismo split de test. La métrica principal es
**PR-AUC**, más informativa que la ROC-AUC dado el fuerte desbalance de clases en datos
reales.

| Modelo | ROC-AUC | PR-AUC | ROC-AUC media sintética | Latencia mediana |
|---|---|---|---|---|
| Baseline Isolation Forest | 0,515 | 0,133 | 0,593 | n/d |
| Autoencoder LSTM | 0,648 | 0,260 | 0,779 | 115 s |
| Autoencoder Transformer | 0,614 | 0,227 | 0,743 | 115 s |
| **VAE-LSTM (seleccionado)** | **0,659** | **0,299** | **0,792** | 120 s |
| Ensemble (media) | 0,652 | 0,273 | 0,778 | n/d |
| Ensemble (máximo) | 0,658 | 0,278 | 0,774 | n/d |

Se desprenden tres conclusiones:

- Los modelos profundos aportan valor sustancial sobre el baseline (la PR-AUC
  aproximadamente se duplica).
- El VAE-LSTM es el mejor en conjunto: mayor PR-AUC sobre datos reales, mayor ROC-AUC
  media sintética y latencia competitiva.
- Las dos estrategias de ensemble no superan al mejor modelo individual y no se
  retienen.

### 7.2 Banco sintético (ROC-AUC por anomalía)

El VAE-LSTM es el mejor en todos los tipos de anomalía. El patrón es consistente: las
perturbaciones grandes y sostenidas son más fáciles que las sutiles, y las maniobras
estructuradas (holding, cambios fuertes de velocidad) son más fáciles que los
desplazamientos pequeños.

| Anomalía | Intensidad | Baseline | LSTM | Transformer | VAE-LSTM |
|---|---|---|---|---|---|
| Desviación de ruta | 20.000 m | 0,513 | 0,556 | 0,543 | 0,558 |
| Desviación de ruta | 40.000 m | 0,537 | 0,684 | 0,657 | 0,700 |
| Desviación de ruta | 80.000 m | 0,618 | 0,883 | 0,865 | 0,899 |
| Desviación de altitud | 300 m | 0,502 | 0,512 | 0,505 | 0,514 |
| Desviación de altitud | 800 m | 0,518 | 0,581 | 0,531 | 0,593 |
| Desviación de altitud | 1.500 m | 0,561 | 0,726 | 0,606 | 0,752 |
| Factor de velocidad | x1,6 | 0,620 | 0,901 | 0,835 | 0,927 |
| Factor de velocidad | x2,2 | 0,743 | 0,985 | 0,965 | 0,989 |
| Factor de velocidad | x0,4 | 0,673 | 0,901 | 0,884 | 0,925 |
| Holding | 240 s/giro | 0,614 | 0,972 | 0,979 | 0,978 |
| Holding | 120 s/giro | 0,634 | 0,975 | 0,985 | 0,984 |
| Congelado transpondedor | fijo | 0,582 | 0,668 | 0,558 | 0,686 |

### 7.3 Curvas y matrices de confusión

Para cada detector se generan curvas precision-recall y ROC, junto con una matriz de
confusión tomada al umbral del percentil 99 de validación. Las figuras se guardan como
PNG en `reports/figures/` y los arrays subyacentes se almacenan dentro de
`reports/model_comparison.json`, de modo que el dashboard puede renderizarlas sin
recalcular.

---

## 8. Inferencia y servicio

El VAE-LSTM seleccionado se sirve mediante una aplicación FastAPI compacta
(`src/sadar/serve/app.py`). En el arranque el servicio carga:

- el checkpoint del modelo de producción,
- el escalador ajustado con los datos de entrenamiento,
- el informe de métricas precomputado,
- y una muestra curada de trayectorias para que el dashboard pueda funcionar sin los
  datos brutos.

La superficie HTTP es deliberadamente reducida. El dashboard se comunica con el backend
a través de cinco endpoints:

| Endpoint | Función |
|---|---|
| `GET /api/health` | Sonda de vida (también devuelve un identificador de build). |
| `GET /api/scene` | Escena de radar actual: aeronaves, scores, umbral. |
| `GET /api/flights` | Lista ordenada de vuelos monitorizados con metadatos. |
| `GET /api/metrics` | Métricas comparativas y curvas precomputadas. |
| `POST /api/simulate` | Inyecta una anomalía en un vuelo y devuelve la respuesta. |

En producción, el mismo proceso FastAPI también sirve la SPA de React ya compilada (la
SPA se monta en `/`, la API queda bajo `/api`). Todo el sistema corre en un único
contenedor.

---

## 9. Frontend

El dashboard es una aplicación React 18 + Vite + TypeScript diseñada para que parezca y
se sienta como una consola de torre de control: fondo oscuro, bloques de datos en
monoespaciada, criticidad codificada por color (verde y cian para normal, ámbar y rojo
para alerta). Expone cuatro pantallas:

1. **Consola torre.** Un radar en directo centrado en LEMD con un panel lateral que
   lista todos los vuelos monitorizados y su estado actual. Las aeronaves en seguimiento
   o en alerta se diferencian por color.
2. **Simulador.** El corazón interactivo de la demo. El operador elige un vuelo, un tipo
   de anomalía, una intensidad y un instante de inicio, e inyecta la perturbación en
   tiempo real. El score de la derecha reacciona a la inyección y la latencia de
   detección se reporta en segundos.
3. **Métricas.** El informe comparativo completo: curvas ROC y PR, desglose de PR-AUC
   por anomalía, justificación de la selección del modelo y resumen del detector final.
4. **Presentación.** Un recorrido guiado utilizado para presentaciones en vivo del
   proyecto.

La aplicación está internacionalizada en inglés y español mediante un pequeño contexto
de traducción.

---

## 10. Reproducibilidad y despliegue

El proyecto está diseñado para que el pipeline completo (preprocesado, entrenamiento,
evaluación, servicio) pueda reproducirse desde cero.

- **Entorno Python.** Fijado con `uv` y `pyproject.toml`; un único comando
  (`uv sync`) reconstruye el entorno.
- **Entorno de frontend.** Gestionado con `pnpm` y `pnpm-lock.yaml`.
- **Configuración.** Todos los parámetros (rutas, longitud de ventana, dimensiones del
  modelo, plan de entrenamiento, umbrales de evaluación) viven en ficheros YAML bajo
  `configs/`. El código no lee rutas literales.
- **Semillas.** Una única semilla se fija al inicio de cada entry point y se propaga a
  NumPy, scikit-learn y PyTorch.
- **Tracking.** MLflow registra todas las ejecuciones en local; Optuna guarda su
  historial de búsqueda junto a los hiperparámetros resultantes.
- **Containerización.** Un único Dockerfile construye una imagen autocontenida que
  incluye el modelo entrenado, el escalador, los informes precomputados y la SPA. La
  misma imagen se utiliza en local (`docker compose up`) y en producción (Hugging Face
  Spaces).

Un `Makefile` expone el flujo como targets con nombre: `make install`,
`make preprocess`, `make train-lstm`, `make train-transformer`, `make train-vae`,
`make tune-vae`, `make compare`, `make serve`, `make dev`, `make docker-up`.

---

## 11. Limitaciones y trabajo futuro

### 11.1 Limitaciones

- **Alcance.** El dataset cubre un solo aeropuerto (LEMD) y un periodo acotado. No se
  espera que el modelo transfiera a otras terminales sin reentrenamiento.
- **Sin planes de vuelo.** La "ruta prevista" se aproxima como "patrón normal
  aprendido". Un vuelo que se aparte de su plan de vuelo pero permanezca dentro del
  patrón normal del tráfico podría no ser marcado.
- **Huecos de cobertura.** Los huecos del transpondedor en ADS-B están dominados por la
  cobertura del receptor. Se usan como característica de entrada, no como etiqueta.
- **Desbalance de clases.** Los eventos anómalos reales son extremadamente raros. Las
  cifras de PR-AUC sobre el test real se calculan con un conjunto positivo pequeño; el
  banco sintético es el referente cuantitativo principal.

### 11.2 Trabajo futuro

- Ampliar el dataset a más aeropuertos y validar la generalización entre terminales.
- Incorporar los planes de vuelo, cuando estén disponibles, como señal auxiliar.
- Combinar el score de conformidad con un clasificador posterior entrenado sobre
  eventos operativos etiquetados (motor y al aire, aproximaciones frustradas, holding)
  para producir alertas más interpretables.
- Explorar ensembles probabilísticos que ponderen cada modelo por su verosimilitud
  calibrada en lugar de hacerlo con un reductor fijo.

---

## 12. Conclusiones

SADAR muestra que un enfoque de aprendizaje profundo de una sola clase es una base
viable para la monitorización de conformidad de trayectorias en un aeropuerto
importante. Tres autoencoders secuenciales entrenados con los mismos datos y evaluados
sobre el mismo banco arrojan una elección de modelo clara y defendible: el
**VAE-LSTM** combina la mejor PR-AUC sobre datos reales, el mejor desempeño medio en el
banco sintético y una latencia mediana de detección competitiva, mejorando con holgura
a un baseline no secuencial. El sistema es completamente reproducible, se empaqueta en
un único contenedor y se sirve a través de un dashboard construido en torno a un caso
de uso real.

El resultado no es un producto cerrado, pero sí un prototipo sólido de cómo la
monitorización de conformidad basada en datos puede complementar las herramientas
basadas en reglas que usan hoy los operadores del tráfico aéreo.

---

**Repositorio.** Smart Anomaly Detection for Aviation Routes (SADAR).
Madrid-Barajas (LEMD) · 2026.