After studying this material, you should be able to:
Traffic forecasting means predicting how long it takes to drive each road segment at any given future time.
GPS Ping (every 4 seconds)
↓
Road Segment Traversal Time Measured
↓
Forecast Future Traversal Times (ETTs)
↓
Routing Engine Sums ETTs Along Route
↓
Arrival Time Estimate Delivered to Rider
| Downstream System | Depends On Traffic Forecasts |
|---|---|
| Route Selection | Needs fastest path |
| Arrival Time (ETA) | Sums segment ETTs |
| Pricing | Reflects trip duration |
| Driver Navigation | Turn-by-turn guidance |
Key Insight: Traffic forecasting sits upstream of everything. Small improvements here compound across millions of trips daily.
The legacy system blended:
This worked well but struggled in three specific scenarios:
Scenario 1: Rapidly Changing Conditions
├── Incidents, weather, major events
└── Old system reacts too slowly
Scenario 2: Sparse Roads
├── Outside dense urban areas
├── Few observations available
└── Old system lacks generalization
Scenario 3: Long Trips
├── Small segment errors multiply
└── Final ETA becomes significantly wrong
These gaps pointed toward deep learning because it can:
Before any modeling began, two major decisions were made. Understanding why these decisions were made is as important as knowing what they were.
Option A (Rejected): End-to-End Training
[Traffic Model] → [Routing Engine] → [Trip Outcome] → Optimize
Option B (Chosen): Clean Boundary
[Traffic Model] → outputs ETTs → [Routing Engine consumes them]
Lesson: In production ML, shippability beats theoretical elegance.
Option A: Dynamic Compute Graph (e.g., GNN)
Raw observations (variable count) → Model
Problem: Must downsample at scale → loses information
Option B: Fixed-Size Compute Graph (Chosen)
Pre-aggregated observations (fixed shape) → Model
Benefit: Predictable inference, uses all available data
| Property | Dynamic Graph | Fixed-Size Graph |
|---|---|---|
| Input size | Variable | Fixed |
| Downsampling needed | Yes | No |
| Inference latency | Unpredictable | Constant |
| Production friendliness | Harder | Easier |
Lesson: System design constraints should drive architecture choices, not the other way around.
A contract defines exactly what the system promises to deliver. DeepETT has two:
Input: Segment ID + Timestamp + Horizon (0–180 min)
Output: Expected traversal time (ETT) in milliseconds
Metric: Mean Squared Error (MSE)
Frequency: Every 5 minutes
Why MSE? Routing needs an expected value to make consistent fastest-path decisions. MSE optimizes for the mean, which is exactly what routing needs.
Input: Sum of segment ETTs along a route
Output: Unrefined arrival time estimate
Metric: Mean Absolute Error (MAE)
Why is this harder?
Even if every segment prediction improves under MSE, the sum of those predictions is not guaranteed to improve under MAE at the trip level.
This is the segment-to-trip paradox — a critical concept explained in the next step.
This is the most conceptually important section of the article.
Forecast Quality
├── Resolution → Information content
└── Calibration → Systematic error
Resolution = How much of real-world variability does the forecast explain?
Example:
Segment-level resolution: ~30% variance explained
Trip-level resolution: ~85% variance explained
Why the jump? Small gains at segment level COMPOUND across many segments.
Calibration = Are predictions systematically too high or too low?
Perfect calibration:
Predicted = Observed (flat residual line at y=0)
Poor calibration:
Predicted consistently 10% too high (curve drifts above y=0)
Key property: Calibration error can be corrected after training. Resolution cannot — it must be built into the model.
Segment MSE improves → Resolution improves ✓
→ Calibration may drift ✗
→ Trip MAE could worsen ✗
Solution strategy:
Each road segment receives a fixed-size input matrix of views:
│ Last Hour │ Historical │ Long-term │
─────────┼─────────────┼──────────────┼─────────────┤
Segment │ ✓ │ ✓ │ ✓ │
Neighbors│ ✓ │ ✓ │ ✓ │
Region │ ✓ │ ✓ │ ✓ │
Why multiple fallback levels?
Dense urban road:
→ Model leans on recent segment-level observations
Sparse rural road:
→ Model shifts attention to neighborhood or regional aggregates
The model always receives the same shape of input but learns which views matter most in each situation.
Each spatiotemporal view becomes a token:
View 1 (segment, last hour) → Token 1 ─┐
View 2 (neighbors, last hour) → Token 2 │
View 3 (region, historical) → Token 3 ├→ Transformer Blocks → ETT Prediction
... │
View N (context features) → Token N ─┘
What the transformer learns:
| Feature Type | Embedding Method |
|---|---|
| Segment IDs | Feature hashing + in-model embeddings |
| Graph structure | Pre-computed message-passing embeddings |
| Time | Minute-of-week in local time |
| Holidays/Events | Event embeddings + days until/since |
| Forecast horizon | Embedded as model input |
One model answers both "right now" and "3 hours from now" queries by embedding the horizon as an input.
Apache Spark (Batch)
└── Precomputes historical and weekly feature aggregates
Apache Flink (Streaming)
└── Delivers real-time updates every few minutes
Feature ingestion: 160,000 rows/second
Prediction serving: 2,000,000 predictions/second
Availability: No downtime globally
After deployment, something unexpected happened:
Week 1 after retraining: Calibration error = Low ✓
Week 2: Calibration curve starts drifting
Week 3: Drift varies by city and time of day
Result: Downstream arrival time models degrade ✗
Why is drift dangerous?
Downstream model trained on: "Forecast X means travel time Y"
After drift: "Forecast X now means travel time Z"
Result: Downstream model makes wrong predictions
Small segment-level miscalibrations snowball into large trip-level errors.
Step 1: Bucket forecasts by city into 10-minute travel-time bins
↓
Step 2: Join buckets with most recent observed traversal times
↓
Step 3: Learn correction factor
↓
Step 4: Apply correction → drives calibration error toward zero
↓
Result: Flat residuals, even during high-traffic events (e.g., NYE NYC)
Key Lesson: Calibrate once at training time = not enough. You need continuous, real-time calibration in production.
| Metric | Improvement |
|---|---|
| Long-trip arrival time accuracy | +6% |
| Forecast variance explained | +19% |
| Navigation defects | -2.73% |
| Annual revenue uplift | ~$100 million |
Same trip: Sao Paulo airport, 8:10am
Baseline system:
→ Route passes through slow city center segments
→ Arrival time error: 1.2 minutes
DeepETT:
→ Forecast captures slowdown patterns accurately
→ Route avoids congestion
→ Arrival time error: 2 seconds
What does the model promise?
What metrics define success?
Where does the model's responsibility end?
→ Prevents scope creep, aligns teams
Resolution = can only be improved by better modeling
Calibration = can be fixed post-training
→ Focus model effort on resolution
→ Fix calibration separately and continuously
Training-time calibration → drifts in production
Real-time calibration → stays locked
→ Especially critical when one model feeds another
Production constraints (latency, scale, reliability)
→ Fixed compute graph over dynamic GNN
→ Pre-aggregated views over raw observations
→ Transformer over recurrent model
DEEPETT IN ONE DIAGRAM
GPS Pings
↓
Road Segment Traversal Times
↓
Spatiotemporal Feature Aggregation (Spark + Flink)
↓
Fixed-Size Multi-View Input Matrix
↓
Graph-Aware Transformer (DeepETT)
↓
Segment ETT Prediction
↓
Real-Time Calibration (Flink)
↓
Calibrated ETT → Routing Engine
↓
Route Selection + Arrival Time Estimate
↓
Rider Experience