AskarT's picture
docs: link the weather model training scripts
28a0398 verified
|
Raw History Blame Contribute Delete
11.5 kB
---
license: mit
language:
- en
library_name: sklearn
pipeline_tag: tabular-classification
tags:
- catboost
- scikit-learn
- tabular-classification
- flight-delay
- aviation
- weather
- gradient-boosting
datasets:
- usdot/flight-delays
metrics:
- roc_auc
- recall
- precision
model-index:
- name: flight-delay-catboost
results:
- task:
type: tabular-classification
name: Flight arrival delay (> 15 min) classification
dataset:
type: usdot/flight-delays
name: 2015 Flight Delays and Cancellations (US DOT) + METAR weather, 73 whole days held out
metrics:
- type: roc_auc
value: 0.698
name: ROC-AUC on 73 unseen days (weather model)
- type: recall
value: 0.545
name: Recall @ calibrated threshold 0.20 (weather model)
- type: precision
value: 0.309
name: Precision @ calibrated threshold 0.20 (weather model)
- task:
type: tabular-classification
name: Flight arrival delay (> 15 min) classification
dataset:
type: usdot/flight-delays
name: 2015 Flight Delays and Cancellations (US DOT), 20 % hold-out of the first 2.1 M rows
metrics:
- type: roc_auc
value: 0.786
name: ROC-AUC (full model)
- type: recall
value: 0.818
name: Recall @ threshold 0.37 (full model)
- type: precision
value: 0.306
name: Precision @ threshold 0.37 (full model)
- type: roc_auc
value: 0.779
name: ROC-AUC (compact model)
- type: recall
value: 0.822
name: Recall @ threshold 0.37 (compact model)
- type: precision
value: 0.297
name: Precision @ threshold 0.37 (compact model)
---
# Flight delay risk: CatBoost pipeline
Binary classifier that estimates the probability that a US domestic flight arrives **more than
15 minutes late** (the FAA definition of a delayed flight) from information known at scheduling
time only: airline, origin and destination airports, date, scheduled departure hour, distance and
scheduled flight time. The weather model, the default of the service, also takes the expected
weather at both airports.
This repository holds the model artifacts used by the
[Flight Delay Prediction & Risk Analysis](https://github.com/Askar-Turanazarov/FlightDelay-Service)
service (Streamlit UI with SHAP explanations and an FAA-based expected-loss estimate).
Live demo: https://flight-delay-askar.streamlit.app · project page: https://huggingface.co/spaces/AskarT/flight-delay-risk
## Files
| File | Size | Contents |
|---|---|---|
| `model_pipeline_weather.pkl` | 40 MB | **weather model**, the default of the live demo: flight + weather at both airports, all of 2015 except 73 held-out days, `max_ctr_complexity=2` |
| `calibration_weather.json` | 8 KB | isotonic calibration of the weather model, its threshold and risk bands |
| `model_pipeline_compact.pkl` | 114 MB | **compact diploma variant**, also offered by the live demo: the same pipeline as the full one, trained with `max_ctr_complexity=3` |
| `model_pipeline_main.pkl` | 433 MB | **full diploma variant**, the reference model (`max_ctr_complexity` default = 4) |
## Weather model
Same `FlightFeatureEngineer` + `CatBoostClassifier` pipeline (2500 trees, depth 7,
`scale_pos_weight=4.2`, `max_ctr_complexity=2`), with eight more categorical inputs after the 13
flight columns: `ORIGIN_WIND, ORIGIN_VISIBILITY, ORIGIN_PRECIP, ORIGIN_HAZARD, DEST_WIND,
DEST_VISIBILITY, DEST_PRECIP, DEST_HAZARD`. They come from hourly METAR reports of 2015 (Iowa
Environmental Mesonet, IEM ASOS), the worst conditions of the hour at the origin in the departure hour
and at the destination in the arrival hour:
| Column | Values |
|---|---|
| `*_WIND` (max of wind and gust, kt) | light < 10, moderate 10–19, strong 20–33, gale ≥ 34 |
| `*_VISIBILITY` (statute miles) | good ≥ 5, reduced 1–5, poor < 1 |
| `*_PRECIP` | none, rain, snow, freezing |
| `*_HAZARD` | none, fog, thunderstorm, icing, other |
**Why it exists.** The diploma models below score 0.78 on random flights, but those flights come
from dates the model had already seen; on new dates (June–December) they score 0.63–0.64. Trained
on the whole year without weather the same setup scores 0.659 on 73 held-out days; with weather,
0.699. The light version (`max_ctr_complexity=2`) scores the same on new dates (0.698) at a quarter
of the size and under half the memory.
**Evaluation on the 73 held-out days (1,116,989 flights, delay share 0.179):** ROC-AUC 0.698,
PR-AUC 0.368. The raw output is inflated by the class weight (mean 0.41), so it is calibrated with
`calibration_weather.json` (ECE 0.233 → 0.012). At the calibrated threshold 0.20, right if a missed
delay costs about four false alarms: recall 0.545, precision 0.309, 32 % of flights flagged.
| Risk band (calibrated p) | Flights | Delayed in fact |
|---|---|---|
| low, < 0.12 | 35.8 % | 8.3 % |
| moderate, 0.12–0.20 | 32.1 % | 16.1 % |
| high, 0.20–0.35 | 24.9 % | 25.4 % |
| critical, ≥ 0.35 | 7.2 % | 48.5 % |
The model learned from observed weather; used with a forecast it scores lower. 40 MB on disk,
about 0.4 GB of RAM after loading. Training scripts:
[`training/weather/`](https://github.com/Askar-Turanazarov/FlightDelay-Service/tree/main/training/weather).
## Diploma models
Both diploma files are `sklearn.pipeline.Pipeline` = `FlightFeatureEngineer` (custom transformer) +
`CatBoostClassifier`, saved with `joblib.dump(..., compress=3)`, and share data, split, features
and every other training parameter. CatBoost stores counter (CTR) tables for combinations of
categorical features (`ROUTE` ≈ 4 200 values × `DAY` × `MONTH` × ...); limiting the combinations to
three features cuts the model from 433 MB / ~1.5 GB RAM to 114 MB / ~0.6 GB RAM at a cost of
0.007 ROC-AUC. The full model was kept unchanged; the compact one was added so that the public demo
fits the free tier of Streamlit Community Cloud.
| | Full model | Compact model |
|---|---|---|
| Training script | `src/train_final.py` | `src/train_compact.py` |
| ROC-AUC (408 907 hold-out flights) | 0.786 | 0.779 |
| Recall / precision @ 0.37 | 0.818 / 0.306 | 0.822 / 0.297 |
| Recall / precision @ 0.50 | 0.660 / 0.396 | 0.657 / 0.386 |
| Pipeline on disk | 433 MB | 114 MB |
| RAM after `joblib.load` / peak while loading | ~1.5 GB / ~2.8 GB | ~0.6 GB / ~0.9 GB |
Smaller configurations (`max_ctr_complexity` 2 and 1, 5–52 MB) were also trained and lost
0.03–0.05 ROC-AUC; the comparison is in `reports/metrics/compact_experiments.txt` of the service repository.
## Intended use
Portfolio / educational demonstration of an end-to-end ML service. The model was trained on 2015
US data; airports, airlines and traffic patterns are those of 2015. It is not an operational tool.
## Training data
[2015 Flight Delays and Cancellations](https://www.kaggle.com/datasets/usdot/flight-delays)
(US Department of Transportation). First 2.1 M rows of `flights.csv`, 80/20 stratified split.
Target: `ARRIVAL_DELAY > 15` minutes, positive rate 18.9 %. Only pre-departure columns are used:
`MONTH, DAY, DAY_OF_WEEK, AIRLINE, ORIGIN_AIRPORT, DESTINATION_AIRPORT, SCHEDULED_DEPARTURE,
SCHEDULED_ARRIVAL, SCHEDULED_TIME, DISTANCE`.
## Features (built inside the pipeline)
`hour_sin`, `hour_cos` (cyclic departure hour), `traffic_density` (departures from the origin in
that month/day/hour), `AIRLINE_FLIGHT_COUNT` (carrier departures from the origin that day),
`ROUTE` (origin–destination pair), `plan_speed` (distance / scheduled time), `IS_NIGHT`,
`IS_WEEKEND`. Categorical features passed to CatBoost: `MONTH, DAY, DAY_OF_WEEK, AIRLINE,
ORIGIN_AIRPORT, DESTINATION_AIRPORT, ROUTE, IS_WEEKEND, IS_NIGHT`.
## Training
CatBoost 1.2.8 on GPU: 2500 iterations, learning rate 0.03, depth 7, `l2_leaf_reg=12`,
`scale_pos_weight=4.2`, Bernoulli subsample 0.8, early stopping on AUC (100 rounds).
The compact variant adds `max_ctr_complexity=3`; nothing else differs.
## Evaluation (408 907 hold-out flights)
| Metric | Full model | Compact model |
|---|---|---|
| ROC-AUC | 0.786 | 0.779 |
| Recall @ 0.37 (chosen threshold) | 0.818 | 0.822 |
| Precision @ 0.37 | 0.306 | 0.297 |
| Recall / Precision @ 0.50 | 0.660 / 0.396 | 0.657 / 0.386 |
The decision threshold 0.37 was chosen to favour recall: a missed delay costs the airline more
than a false alarm. Raw `predict_proba` is not calibrated.
## How to use
The pickle references the custom class as `src.feature_engineering.FlightFeatureEngineer`, so run
the snippet from the root of the service repository (or put that root on `sys.path`). Versions
matter: Python 3.10, catboost 1.2.8, scikit-learn 1.7.2, numpy 2.2.6, pandas 2.3.3.
```bash
git clone https://github.com/Askar-Turanazarov/FlightDelay-Service.git
cd FlightDelay-Service
pip install -r requirements.txt
```
```python
import os, sys, joblib, pandas as pd
from huggingface_hub import hf_hub_download
sys.path.insert(0, os.getcwd()) # repository root, so that `src.feature_engineering` resolves
path = hf_hub_download("AskarT/flight-delay-catboost", "model_pipeline_compact.pkl") # or model_pipeline_main.pkl
pipe = joblib.load(path)
flight = pd.DataFrame([{
"MONTH": 7, "DAY": 15, "DAY_OF_WEEK": 3, "AIRLINE": "AA",
"ORIGIN_AIRPORT": "JFK", "DESTINATION_AIRPORT": "LAX",
"SCHEDULED_DEPARTURE": 1800, "SCHEDULED_ARRIVAL": 2115, # HHMM as in the source data
"SCHEDULED_TIME": 375, "DISTANCE": 2475,
"DEP_HOUR": 18, "ARR_HOUR": 21, "IS_WEEKEND": 0, # derived by the caller, see src/app.py
}])
prob = pipe.predict_proba(flight)[0, 1]
print(f"P(delay > 15 min) = {prob:.3f}, flagged = {prob >= 0.37}")
# Weather model: the same 13 columns plus the weather, then the calibration
import json, numpy as np
weather = {"ORIGIN_WIND": "moderate", "ORIGIN_VISIBILITY": "good", "ORIGIN_PRECIP": "none", "ORIGIN_HAZARD": "none",
"DEST_WIND": "strong", "DEST_VISIBILITY": "reduced", "DEST_PRECIP": "rain", "DEST_HAZARD": "thunderstorm"}
pipe_w = joblib.load(hf_hub_download("AskarT/flight-delay-catboost", "model_pipeline_weather.pkl"))
cal = json.load(open(hf_hub_download("AskarT/flight-delay-catboost", "calibration_weather.json")))
raw = pipe_w.predict_proba(flight.assign(**weather))[0, 1]
p = float(np.interp(raw, cal["x"], cal["y"]))
print(f"calibrated P = {p:.3f}, flagged = {p >= cal['threshold']}")
```
`DEP_HOUR` / `ARR_HOUR` are the scheduled departure and arrival hours (0–23); `IS_WEEKEND` is 1 for
Saturday and Sunday. The service computes them in `src/app.py` before calling the pipeline.
The two diploma variants give slightly different probabilities for the same flight (this example:
0.469 compact, 0.375 full). In the service the visitor picks the model in the sidebar; the
`MODEL_VARIANT` environment variable sets the default (`weather` unless set).
## Limitations
* 2015 US data only; no real-time information. The weather model was trained on observed weather.
* Only the weather model is calibrated; the diploma models return the raw probability, and the
service shows it next to the 18.9 % base rate.
* Traffic features fall back to 1 for airport/day/hour combinations unseen in training.
## Author
Askar Turanazarov, Data Science diploma project, 2026. MIT license.