Shamsher Football Match Predictor
A small-model Gradio dashboard for football match predictor.
I've watched hundreds of football matches. Argued over lineups, debated formations, lost sleep over scorelines I was certain I had right. So when the Build Small Hackathon kicked off, a Hugging Face and Gradio jam for open-weight models under 32B parameters, I knew exactly what I wanted to build: a football match predictor that thinks the way a football analyst actually does.
Not just "home team wins 60% of the time." Something that reasons about who is playing, how they're set up, who their manager is, and what their last five matches looked like.
This is the story of how I built it, what broke, and whether it actually works.
Most football prediction tools treat a match as a row of statistics. Win rate here, goal difference there, maybe an Elo rating if you're fancy. But a match is a graph. Eleven players connected by position, chemistry, and tactical role, facing eleven others in a live tactical duel.
Shamsher tries to encode exactly that. The name means "sword" in Bangla. A good prediction should cut through the noise.
Pre-match inputs:
Outputs:
It's the full analyst report, generated from a 3.3M parameter model running on CPU.
The hackathon's spirit is clear: the future of AI doesn't have to live in someone else's data center. I took that literally. Shamsher runs entirely on CPU, no GPU required, no cloud API bill, and sits at roughly 3.3 million trainable parameters. Small enough to fit in RAM, fast enough to generate predictions in seconds.
Every match report, every squad stat, every scoreline was sourced from open data archives: FBref-style match reports, StatsBomb open data, Understat-like player JSONs. Processed entirely on my own machine. No external model API in the prediction loop.
This is where it gets interesting, and maybe a little over-engineered for a hackathon. I couldn't help myself.
Each squad is encoded as a small graph where nodes are players and edges represent positional and chemical relationships. A lightweight Graph Attention Network (GNN) reads this graph and produces a single team embedding. This matters because Mbappe in a 4-3-3 and Mbappe as a lone striker are different threats.
The model fuses seven separate information streams:
All of these pass through a single Transformer encoder layer, then into a residual fusion MLP to produce a shared match representation.
From that shared representation, five heads fire simultaneously:
Missing labels in training data are handled with masks rather than zero-fill, so the model was never punished for not knowing xG on matches where only the final score was recorded.
The training set spans 8,853 match reports from competitions across multiple seasons. Of those, 8,716 had complete lineup data, which is what really matters. Without lineups, squad graphs can't be built.
Supervision targets include scorelines, formations, managers, starters, bench squads, goalscorers, shots, and shots on target. Regression targets like xG, passes, and possession are sparser but still present across thousands of matches.
One significant challenge was name normalization. Canonical keys are shared across all preparation and prediction code:
USA -> united statesCzech Republic -> czechiaJoΓ£o -> joaoMbappΓ© -> mbappeThis matters because user input at prediction time rarely matches the exact strings in raw data. A shared normalization layer means the model degrades gracefully on slightly different spellings.
The interface is deliberately simple. You paste a lineup, select teams and date, and hit predict. The output renders as a match preview card: probabilities, expected scoreline, top scorer candidates, and a confidence score.
Internally the flow looks like this:
lineup text -> name normalization -> squad matrix rebuild
-> chemistry graph rebuild -> model forward pass
-> consistency post-processing -> JSON payload -> Gradio UI
Post-processing enforces hard constraints before anything hits the UI. Win + draw + loss must sum to 100%. Home + away possession must sum to 100%. Shots on target cannot exceed shots. These aren't model outputs. They're prediction contracts.
I tested Shamsher on four real matches and recorded the results honestly. Here's what happened.
The model's best result. It called the exact scoreline correctly: 1-0 Scotland. Possession came in at 45/55 predicted vs 50/50 actual. Shots on target at 4/6 predicted vs 3/3 actual. The structural picture and the outcome were both right. For a 3.3M parameter model running on CPU, this is exactly what you want to see.
The top prediction was 0-2 Switzerland, which didn't land. But the draw was ranked as the third most probable outcome, so the model wasn't blindsided, it just didn't elevate it to the top slot. More importantly, Switzerland's dominance in possession and shot volume was correctly captured. The actual scoreline came down to conversion efficiency and variance on the day, which no pre-match model can fully encode.
The most honest failure. The model leaned toward a Turkey win (0-1), while Australia won cleanly 2-0. Shot balance and activity levels were modeled reasonably well but the result diverged significantly. This is the real lesson in football prediction: statistical dominance doesn't guarantee the result. Australia converted. Turkey didn't. A 3.3M parameter model can't predict conversion luck and it shouldn't pretend to.
Perhaps the most impressive tactical result despite missing the scoreline. The model predicted 611 passes for Netherlands vs 516 actual, and possession at 59.3% vs 60% actual, essentially perfect. Three of the four actual goalscorers appeared in the model's top scorer probability rankings. The final score was missed because of Japan's 89th-minute equaliser. Timing is football's final variable and the hardest to model.
Shamsher has genuine tactical intelligence. It understands possession patterns, squad dominance, and shot dynamics quite well. Where it falls short is conversion variance and late-match chaos, which is where all football prediction models struggle regardless of size. The honest read: it performs like a well-informed analyst who reads the game right but can't predict moments of individual brilliance or defensive errors.
Bangla commentary layer. The model outputs JSON, but wrapping that in natural-language commentary in Bangla would make it genuinely accessible to the South Asian football audience I care about.
Live data integration. The pipeline already has hooks for live lineup injection. Connecting a real-time source would close the loop.
Learned calibration. A small calibration head trained on held-out predictions rather than rules.
Richer squad graphs. The current node dim is 20 features. With more granular Opta or StatsBomb data per player, this could expand significantly.
Built for the Build Small Hackathon (Hugging Face x Gradio, June 2026). Backyard AI track.
A small-model Gradio dashboard for football match predictor.
More from this author