Ticket Predictor: Production ML Forecasting System
Python
scikit-learn
Flask
NLP
Time Series
The Problem
IT support management across multiple corporate sites was entirely reactive. No one knew whether tomorrow would bring 5 walk-ups or 50. Staffing decisions were based on gut feel, leading to either overstaffing (wasted budget) or understaffing (long wait times and frustrated employees).
What I Built
An end-to-end ML system that predicts daily contact volume per site for the next 14 days, detects historical spikes, and identifies repeat requester patterns. Predictions are served through a 6-page Flask web application used by management for staffing decisions.
Core Components
- Contact forecasting: Per-site daily predictions using GradientBoosting (high-volume sites) and Ridge regression (low-volume sites)
- Spike detection: Identifies anomalous high-volume days and extracts root causes using TF-IDF keyword analysis on ticket descriptions
- Requester analysis: Patterns for repeat visitors (frequency, categories, day-of-week tendencies)
- Resolution classification: Predicts resolution time category for incoming tickets (67.5% accuracy)
Feature Engineering
| Feature Group | Features |
| Day patterns | Day of week, cyclical encoding (sin/cos), is_weekend |
| Calendar | Day of month, week of year, month |
| Holidays | is_holiday, day before/after holiday (US holidays) |
| Lag features | 1, 2, 3, 7, 14, and 30 days ago |
| Rolling averages | 3-day, 7-day, and 14-day rolling mean |
| Same-weekday history | Average of last 4 and 8 same weekdays |
Model Performance
Trained on 534 days of historical data across multiple sites with independent per-building models.
| Metric | Top Sites | Median | Description |
| R-squared | 0.99 | 0.94 | Variance explained by the model |
| MAE | <0.1 contacts | 1.5 contacts | Average daily prediction error |
| Error % | <2% | 8% | MAE as % of average volume |
Floor rule: Predictions cannot drop below 80% of the same-weekday 4-week average. This prevents anomalous quiet days from dragging future predictions unrealistically low.
Impact
- Management uses forecasts to plan staffing levels for the upcoming week
- Team shifted from reactive scheduling to proactive allocation
- High-volume days are anticipated rather than discovered at 9am
- Spike analysis explains why volume surged (onboarding waves, recurring campaigns, hardware rollouts) so it can be prepared for next time
Architecture
- Data ingestion: Automated daily pull from ticketing system API
- Model training: Retrained on each data refresh with latest patterns
- Serving: Flask web app reads pre-computed JSON predictions
- Monitoring: Prediction-vs-actual tracking, drift detection, accuracy logging
Design Decisions
- Per-site models over one global model: Each building has unique patterns (some spike on Mondays, others are steady). A single model couldn't capture this.
- GradientBoosting for high-volume, Ridge for low-volume: Tree models overfit on sparse data. Ridge stays stable when a site averages <3 contacts/day.
- Contact-based, not ticket-based: One person's visit may generate multiple tickets. Contacts map to actual walk-ups, which is what staffing cares about.
What I Would Improve
- Add confidence intervals to predictions (quantile regression)
- Incorporate external signals (company all-hands, building moves, new hire start dates)
- A/B test staffing recommendations against the baseline
- Real-time anomaly alerts when actual volume deviates significantly from prediction