|
--- |
|
library_name: keras |
|
license: apache-2.0 |
|
pipeline_tag: tabular-classification |
|
tags: |
|
- tensorflow |
|
- keras |
|
- tabular |
|
- classification |
|
- ensemble |
|
- transportation |
|
model-index: |
|
- name: imt-ml-track-ensemble-20250906-124755 |
|
results: |
|
- task: |
|
type: tabular-classification |
|
name: Track classification |
|
dataset: |
|
name: MBTA Track Assignment (custom) |
|
type: custom |
|
split: validation |
|
metrics: |
|
- type: accuracy |
|
name: Average individual accuracy |
|
value: 0.5957 |
|
- type: accuracy |
|
name: Best individual accuracy |
|
value: 0.6049 |
|
- type: loss |
|
name: Average individual loss |
|
value: 1.2251 |
|
--- |
|
|
|
# imt-ml Track Prediction — Ensemble (2025-09-06 12:47:55) |
|
|
|
Predicts which MBTA commuter rail track/platform a train will use, using a small tabular neural-network ensemble trained on historical assignments. This card documents the artifacts in `output/ensemble_20250906_124755`. |
|
|
|
## Model Summary |
|
|
|
- Task: Tabular multi-class classification (13 track classes) |
|
- Library: Keras (TensorFlow backend) |
|
- Architecture: 6-model ensemble (diverse dense nets with embeddings + cyclical time features); softmax outputs averaged at inference |
|
- Inputs (preprocessed): |
|
- Categorical: `station_id` (int index), `route_id` (int index), `direction_id` (0/1) |
|
- Time (cyclical): `hour_sin`, `hour_cos`, `minute_sin`, `minute_cos`, `day_sin`, `day_cos` |
|
- Continuous: `scheduled_timestamp` (float seconds since epoch; normalized in-model) |
|
- Outputs: Probability over 13 track labels (softmax) |
|
- License: MIT |
|
|
|
## Files in This Repo |
|
|
|
- `track_prediction_ensemble_model_0_final.keras` … `track_prediction_ensemble_model_5_final.keras` — individual ensemble members |
|
- `track_prediction_ensemble_model_*_best.keras` — best checkpoints during training (may match `final`) |
|
- `training_report.md` — training configuration and metrics |
|
|
|
Note: Ensemble training currently does not emit a `*_vocab.json`. See “Preprocessing & Vocab” below. |
|
|
|
## Preprocessing & Vocab |
|
|
|
Models expect integer indices for `station_id` and `route_id`, and raw `direction_id` 0/1. In training, indices are produced by lookup tables built from the dataset vocabularies. To reproduce inference exactly, you must use the same vocabularies (station/route/track) that were present at training time or ensure consistent mapping. |
|
|
|
What to use: |
|
- The training pipeline’s dataset loader (`imt_ml.dataset.create_feature_engineering_fn`) defines the exact feature mapping. If you need the vocab files, re-run a training or export step to generate them for your data snapshot, or save the vocab mapping alongside the model. |
|
|
|
## Metrics (validation) |
|
|
|
From `training_report.md`: |
|
- Average validation loss: 1.2251 |
|
- Average validation accuracy: 0.5957 |
|
- Best individual accuracy: 0.6049 |
|
- Worst individual accuracy: 0.5812 |
|
- Ensemble accuracy stdev: 0.0087 |
|
- Dataset size: 24,832 records (310 train steps/epoch, 77 val steps/epoch) |
|
|
|
These metrics reflect individual model performance; at inference time, average the softmax probabilities across all 6 models to produce ensemble predictions. |
|
|
|
## Example Usage (local Python) |
|
|
|
This snippet loads all six Keras models and averages their softmax outputs. Replace the feature values with your preprocessed tensors/arrays, ensuring they match the training feature schema and index mappings. |
|
|
|
```python |
|
import numpy as np |
|
import keras |
|
|
|
# Load ensemble members |
|
paths = [ |
|
"track_prediction_ensemble_model_0_final.keras", |
|
"track_prediction_ensemble_model_1_final.keras", |
|
"track_prediction_ensemble_model_2_final.keras", |
|
"track_prediction_ensemble_model_3_final.keras", |
|
"track_prediction_ensemble_model_4_final.keras", |
|
"track_prediction_ensemble_model_5_final.keras", |
|
] |
|
models = [keras.models.load_model(p, compile=False) for p in paths] |
|
|
|
# Prepare one example (batch size 1) — values shown are placeholders. |
|
# You must convert raw strings to indices using the same vocab mapping used in training. |
|
features = { |
|
"station_id": np.array([12], dtype=np.int64), # int index |
|
"route_id": np.array([3], dtype=np.int64), # int index |
|
"direction_id": np.array([1], dtype=np.int64), # 0 or 1 |
|
"hour_sin": np.array([0.707], dtype=np.float32), |
|
"hour_cos": np.array([0.707], dtype=np.float32), |
|
"minute_sin": np.array([0.0], dtype=np.float32), |
|
"minute_cos": np.array([1.0], dtype=np.float32), |
|
"day_sin": np.array([0.433], dtype=np.float32), |
|
"day_cos": np.array([0.901], dtype=np.float32), |
|
"scheduled_timestamp": np.array([1.7260e9], dtype=np.float32), |
|
} |
|
|
|
# Predict per model and average probabilities |
|
probs = [m.predict(features, verbose=0) for m in models] |
|
avg_prob = np.mean(probs, axis=0) # shape: (batch, num_tracks) |
|
pred_class = int(np.argmax(avg_prob, axis=-1)[0]) |
|
print({"predicted_track_index": pred_class, "probabilities": avg_prob[0].tolist()}) |
|
``` |
|
|
|
Tip: If you have the track vocabulary used at training time, you can map `pred_class` back to its track label string by indexing into that `track_vocab` list. |
|
|
|
## Training Data |
|
|
|
- Source: Historical MBTA track assignments exported from Redis to TFRecord |
|
- Features: |
|
- Categorical: `station_id`, `route_id`, `direction_id` |
|
- Temporal: hour, minute, day_of_week (encoded as sin/cos pairs) |
|
- Target: `track_number` (13 classes) |
|
|
|
## Training Procedure |
|
|
|
- Command: `ensemble` |
|
- Num models: 6 (architectural diversity: deep, wide, standard) |
|
- Epochs: 150 |
|
- Batch size: 64 |
|
- Base learning rate: 0.001 (varied 0.8x–1.2x per model) |
|
- Regularization: L1/L2, Dropout, BatchNorm; cosine LR scheduling and early stopping when enabled |
|
|
|
## Intended Use & Limitations |
|
|
|
- Intended for assisting real-time track/platform assignment predictions for MBTA commuter rail. |
|
- Not a safety system; always defer to official dispatch/operations. |
|
- Sensitive to concept drift (schedule/operational changes) and to unseen stations/routes. |
|
- Requires consistent categorical index mapping between training and inference. |
|
|
|
|