Five models, scored against reality
Every model predicts the same thing: Jackson's next ranked champion. Each row of the scoreboard is measured, never claimed, using a strict walk-forward test.
Five models on a ladder of complexity: the two-step sampler (the front-page pick) trades accuracy for variety; the logistic argmax always takes its most-likely pick; XGBoost is kept in to show how a data-hungry model handles a few hundred games; the decay baseline does no learning ("what he's played lately"); the uniform model is the random floor.
All five train on ranked solo queue only (queue 420), where Jackson's picks are deliberate and carry real signal. Normals and ARAMs are experiments, so they'd just teach a model noise. The Statistics and Playstyle pages use every game.
Everything has to beat the decay baseline. "What he's played lately" is free, has no parameters to overfit, and is hard to improve on with this little data, so it stays in the lineup as model 4 to keep that bar on the board rather than merely asserted.
Capacity is matched to data size. A regularized logistic regression learns a handful of coefficients a hundred-odd games can support; XGBoost carries far more and tends to memorize noise here, so it usually trails the simpler models. It's deployed and scored anyway, because turning "boosted trees overfit small data" into a number on this page beats claiming it.
Live scoreboard
A walk-forward backtest: for every ranked game, each model is trained only on games before it, then its pick is written beside the champion actually played. No model can peek at the answer, and correctness is inherent in every row (pick equals actual), so there's no separate verification to trust.
Logistic argmax
A regularized logistic regression over the champion pool that always deploys its single most likely pick, auto-selecting against a plain recency baseline.
Decay frequency
No learning at all: whatever has been played lately, with older games fading out exponentially. The yardstick every fitted model must beat.
XGBoost
Gradient-boosted trees on identical features. Kept in deliberately to measure how a data-hungry model behaves on a few hundred games.
Two-step sampler
Samples a role, then samples a champion in it. The only model with randomness, so it is the site's live pick: varied on purpose, less accurate by design.
Uniform random
A seeded pick from every champion ever played. The deliberate floor: any model that cannot clearly beat this is not predicting anything.
At a few hundred games the margin is roughly ±6 points, so models within ~5 points are a tie. Read the ordering, not the small gaps.
Recent scored predictions
| Actually played | Two-step sampler | Logistic argmax | XGBoost | Decay frequency | Uniform random | Date |
|---|---|---|---|---|---|---|
| Graves | Jarvan IV | Lillia | Lillia | Jarvan IV | Malphite | 21 Jul |
| Jarvan IV | FiddleSticks | Lillia | Lillia | Jarvan IV | Jarvan IV | 21 Jul |
| Lillia | Jarvan IV | Lillia | Lillia | Jarvan IV | Lee Sin | 21 Jul |
| Lillia | Lillia | Graves | Graves | Jarvan IV | FiddleSticks | 20 Jul |
| Mordekaiser | Jarvan IV | Lillia | Lillia | Jarvan IV | Garen | 20 Jul |
| Lillia | Jarvan IV | Bel'Veth | Bel'Veth | Jarvan IV | Kindred | 20 Jul |
| Bel'Veth | Bel'Veth | Lillia | Lillia | Jarvan IV | Shaco | 20 Jul |
| Bel'Veth | Graves | Lillia | Lillia | Jarvan IV | Lillia | 19 Jul |
| Lillia | Jarvan IV | Lillia | Graves | Jarvan IV | Ekko | 19 Jul |
| Bel'Veth | Garen | Lillia | Lillia | Jarvan IV | Kindred | 19 Jul |
| Graves | Lillia | Lillia | Graves | Jarvan IV | Thresh | 19 Jul |
| Lillia | Jarvan IV | Lillia | Graves | Jarvan IV | Yasuo | 19 Jul |
| Graves | Jarvan IV | Lillia | Lillia | Jarvan IV | FiddleSticks | 19 Jul |
| Ornn | Bel'Veth | Lillia | Lillia | Jarvan IV | Bel'Veth | 19 Jul |
| Lillia | Lillia | Lillia | Lillia | Jarvan IV | Yone | 19 Jul |
Green = the pick matched what was played. One ranked game per row, newest first.
Parameters, in plain language
Two-step sampler
| Parameter | Value | What it does |
|---|---|---|
| role halflife (days) | 120 | How fast old games stop counting toward role odds: a game this many days old carries half the weight of one played today. |
| role temperature | 0.6 | Sharpens the role odds before sampling. Below 1.0 favours the main role more; 1.0 would sample the raw frequencies. |
| champion recency halflife (days) | 100 | Same idea for champions: how quickly a champ fades from the pool when it stops being played. |
| sampling temperature | 0.7 | The variety knob. The displayed pick is sampled from the model's odds reshaped by this: lower is safer and more repetitive, higher is more chaotic. |
| min games to be a candidate | 3 | A champion only enters the candidate pool after this many games in the sampled role, so one-off picks don't pollute the odds. |
| regularization grid (C) | [0.03, 0.1, 0.3, 1.0, 3.0] | Candidate regularization strengths; grouped cross-validation on the training games picks whichever generalizes best. |
| features | champ_freq_score, days_since_last_on_champ, in_role_score, is_last_pick | Deliberately tiny feature set: a few hundred training games can't support more. |
| decision rule | sample role, then sample champion | The only model allowed randomness. Both draws are seeded from the previous game's id, so a re-run reproduces the identical pick. |
Logistic argmax
| Parameter | Value | What it does |
|---|---|---|
| recent-games window | 10 | Each champ's share of the last N games -- a strong 'what am I on right now' signal the two-step lacks. |
| min games to be a candidate | 3 | Same pool rule as the two-step model, but across ALL roles at once (no role step). |
| holdout games | 20 | The most recent games are hidden from training and used only to measure the model, so its choices are earned on unseen data. |
| features | champ_freq_score, days_since_last_on_champ, is_last_pick, recent_share | Role-agnostic features over the whole champion pool. |
| decision rule | argmax + holdout auto-select | Always shows its single most-likely champion. If the plain decay baseline beats the fitted model on held-out games, it deploys the baseline instead -- simpler wins ties. |
XGBoost
| Parameter | Value | What it does |
|---|---|---|
| n_estimators | 150 | How many small trees are stacked in sequence, each one correcting the errors of the trees before it. More trees means more capacity to fit -- and on tiny data, to memorize noise. |
| max_depth | 2 | How many yes/no splits each tree may make. Depth 2 keeps every tree nearly trivial, the main defence against overfitting a small dataset. |
| learning_rate | 0.1 | How much each new tree is allowed to change the running prediction. Lower is more cautious: many small corrections instead of a few big ones. |
| min_child_weight | 5 | A leaf must cover at least this much data to exist. Stops the model carving out rules that only ever applied to one or two games. |
| subsample / colsample_bytree | 0.8 / 0.8 | Each tree only sees a random 80% of the games and 80% of the features, so no single quirk of the data gets baked into every tree. |
| reg_lambda | 2.0 | An L2 penalty that shrinks leaf values toward zero, the boosted-tree cousin of the C knob on the logistic models. |
| features | champ_freq_score, days_since_last_on_champ, is_last_pick, recent_share | Identical inputs to the argmax model, imported from the same module. Any difference in the scores is the model, never the plumbing. |
| decision rule | argmax, always deploys itself | Never falls back to the decay baseline even when the baseline evaluates better. Deploying itself is the experiment: its hit rate is tracked head-to-head on the same table. |
Decay frequency
| Parameter | Value | What it does |
|---|---|---|
| recency halflife (days) | 100 | A champion's score is its pick count with old games fading out exponentially; a game this many days old counts half. |
| decision rule | argmax of decayed frequency | No learning at all: 'whatever he's been playing lately'. The yardstick every fitted model must beat to justify existing. |
Uniform random
| Parameter | Value | What it does |
|---|---|---|
| pool | every champion ever played | All champions in the history get an equal share, no matter how long ago or how rarely played. |
| decision rule | seeded uniform draw | The deliberately bad floor: long-run accuracy should sit near 1 / pool size. A model that can't clearly beat this isn't predicting anything. |
Glossary, in plain language
| Term | What it means here |
|---|---|
| logistic regression | The simplest useful classifier: a weighted sum of the features pushed through a squashing function to get a probability. Few parameters, hard to overfit, easy to read (each feature gets one coefficient). |
| gradient boosting (XGBoost) | Builds many small decision trees in sequence, each tree correcting the mistakes of the ones before. The industry default for tabular data, but it is data hungry: with only a few hundred games it tends to memorize noise instead of learning patterns. |
| decay / recency baseline | Not a learned model at all: just 'what has he played lately', with older games fading out exponentially. Every real model must beat this to justify existing. It is embarrassingly hard to beat. |
| uniform floor | A pick drawn at random from every champion ever played. Its accuracy is what zero skill looks like on this data -- the number every other model's accuracy should be read against. |
| argmax vs sampling | Argmax always outputs the single most likely champion (accurate, repetitive). Sampling draws from the whole probability distribution (less accurate per pick, but varied and honest about uncertainty). The two-step samples; the comparison models argmax. |
| walk-forward backtest | Every row in the predictions table was computed as if standing just before that game: trained only on earlier games, seeded from the previous game's id. A backfilled prediction is informationally identical to one made live at the time. |
| temporal holdout | Within each training pass, the most recent 20 games are hidden and used only for scoring, so model choices (like argmax's auto-select) are earned on games the model never saw. |
| grouped cross-validation | During tuning, all candidate rows belonging to one game stay in the same fold, so the model can never peek at part of a game it is being tested on. |
| regularization (C / reg_lambda) | A penalty on model complexity. Stronger regularization forces the model to stay simple, trading a little training-set fit for better behavior on new games. |
| accuracy (top-1) | The share of games where the champion actually played was the model's pick. With ~275 scored games, differences of a few percentage points are statistical noise (roughly a ±6-point margin) -- read the scoreboard accordingly. |
| overfitting | When a model learns the training data's coincidences instead of its patterns: great scores on games it has seen, poor scores on games it has not. The expected story here: the flexible XGBoost trails the simpler models, and that gap is the concrete reason simple models are trusted on small data. |