Lion Cipher Lab
Break a security eval score down by slice and catch the regression the average hides: Simpson's paradox, post-stratification and a slice gate
- AI Security
- Intermediate
- ~90 min
- Free · no account required
Why it matters
A team runs its alert-triage model, v1, against an eval and gets 0.9260. A quarter later the vendor ships v2, the eval is refreshed, v2 scores 0.9290, and the swap goes on the change calendar. Nobody broke the number down. If they had, they would have seen v2 is worse at every severity: a little worse on low-severity alerts, and 24 points worse on critical ones - the ransomware precursors and the data leaving the building, the alerts the whole SOC exists for. The average hid it because the refreshed eval was re-sampled with three-quarters low-severity items, where every model does well. That…
What you'll learn
- building an answer-keyed security eval where every item carries slice metadata (severity, log source, ATT&CK tactic), so one overall score can be broken down into the slices a deployment decision actually depends on
- reporting accuracy per slice with a 95% Wilson interval next to every number, and reading when a slice is too small to say anything
- spotting Simpson's paradox in an eval by hand from a 2x2 table: a candidate model worse in EVERY severity slice (critical 0.5667 against 0.8067) and still better overall (0.9290 against 0.9260), because its eval run was re-sampled with a different slice mix
- post-stratifying both models to the production slice mix to get the honest comparison (v1 0.9260, v2 0.8845), and fixing the root cause by scoring both models on one frozen, slice-balanced eval
- scoring models by expected cost per 1,000 production alerts, where a missed critical escalation costs 100 times a false escalation
- writing and running a pre-declared slice gate (PASS / BLOCK / UNDECIDED per critical slice, margin 3 points, fails closed) that blocks the bad swap and passes the fixed one
- measuring three ways slicing fails: slices too small to decide (2,791 items needed per model per critical slice), 40 slices on two identical models producing 2.05 false regressions per run until a Holm correction, and a latent slice nobody labelled hiding a 35-point drop
Steps in this lab
- The words first: eval, slice, disaggregated evaluation, Simpson's paradox, post-stratification, margin - and the fact that the models are stubs
- Open a terminal, check Python, make a scratch folder (Windows, macOS, Linux)
- One-step recap: an interval on the overall score is necessary, and not enough
- Build the eval: three runs of answer-keyed alerts with slice metadata
- Write the three STUB models - read their rates before you trust any number
- Write the statistics ruler: Wilson interval, a difference interval, post-stratification, and a correction for many tests
- Measure BEFORE: the headline the team saw, then the same runs broken down by severity
- Simpson's paradox by hand: worse in both rows, better in the total
- Post-stratify: re-weight both runs to the production mix and get the honest answer
- Measure AFTER: one frozen eval, a cost-weighted score, and a pre-declared slice gate
- Three honest negatives: slices too small to decide, too many slices, and the slice nobody labelled
- Why this, not that - and when NOT to slice
- The way a pro does it: write the slice-gate policy down before the candidate arrives
- Ship it: re-run, break a constant on purpose, and clean up