AI Hints
Home›Data Science Tutorial›More Sharp Tools
Data Science · Lesson 67 of 101

Testing Many Things at Once

The hidden false alarms.

⏱ 2 min read▶ Video at 1:52:30🎓 Free
Watch this lesson in the Data Science courseWatch on YouTube ↗Full Data Science course

A proud analyst says the new app design lifted three metrics out of forty. It looks like a great result. But think about what a five percent false alarm rate really means. If you test forty things, how many alarms will go off, even if nothing happened?

Testing Many Things at Once
From the video: Testing Many Things at Once
  • Three metrics went up
  • Out of forty
  • How many by luck?

Forty metrics, no real effect

We simulate two groups, with forty metrics, and no real effect at all. Every metric is pure noise. We test each one, and count the results under point zero five. Then the Bonferroni rule, which simply divides that threshold by the number of tests. Next, we add a real effect to four of the metrics, and we compare three methods. Run it. With no real effect, three metrics still look significant. That's the proud analyst's result, from pure noise. Bonferroni correctly finds none. With four real effects, the plain test finds seven, so three of those are false. Bonferroni and Benjamini Hochberg both find exactly four.

many_tests.pypython
import numpy as np
from scipy import stats

rng = np.random.default_rng(1)
n_metrics, n_users = 40, 2000
a = rng.normal(0, 1, (n_users, n_metrics))
b = rng.normal(0, 1, (n_users, n_metrics))
p = stats.ttest_ind(a, b).pvalue
print("Metrics tested:", n_metrics, " True effects: 0")
print("Significant:", (p < 0.05).sum())
print("With Bonferroni:", (p < 0.05 / n_metrics).sum())

b[:, :4] += 0.15
p = stats.ttest_ind(a, b).pvalue
print("Now 4 real effects")
print("Plain test finds:", (p < 0.05).sum())
print("Bonferroni finds:", (p < 0.05 / n_metrics).sum())
print("Benjamini-Hochberg finds:", stats.false_discovery_control(p).__lt__(0.05).sum())
Output
Metrics tested: 40  True effects: 0
Significant: 3
With Bonferroni: 0
Now 4 real effects
Plain test finds: 7
Bonferroni finds: 4
Benjamini-Hochberg finds: 4

Two ways to correct

These two corrections answer different questions. Bonferroni protects you against even one false alarm. It's simple and strict, and with lots of tests, it can miss real effects. In this run, it didn't, but the effects were clear. Benjamini Hochberg controls what share of your discoveries are false. It's less strict, so it's the usual choice when you're exploring many metrics.

keyvalue
Bonferronino false alarms at all
Costcan miss real effects
Benjamini-Hochberglimits the false share
Best useexploring many metrics

The garden of forking paths

You don't need to run forty formal tests to get into trouble. Every time that you try a different filter, a different date range, or a different segment, you're running another test. Nobody sees all those paths, and that may include you. So write down your main metric before you begin. Treat everything else as a clue, and not as a result. Then confirm any surprising clue with a fresh test.

Every slice is a testeven informal ones
Pick one main metricbefore you start
Everything elseis only a clue
Confirmwith fresh data

A sensible way to report

When you've got many metrics, a simple structure helps. One primary metric decides the launch. A few guardrail metrics check that nothing's been damaged. Secondary metrics help you to explain what happened, and you label them as exploratory. Then report every metric that you tested, including the boring ones. Showing only the winners is how false results get into company decisions.

One primary metricmakes the decision
Guardrailsnothing damaged
Secondary metricsexplain, don't decide
Report everythingnot just the winners

Summary

Count your tests, correct for them, and treat surprises as clues. Next, let's turn six thousand customers into groups that you can act on.

Key takeaways
  • Forty tests give about two false alarms
  • Correct for many tests
  • Pre-register your main metric
Next up: Customer Segments — who to look after