Калькулятор значущості A/B тесту
Перевірте, чи результат вашого A/B тесту статистично значимий. Введіть відвідувачів і конверсії, щоб отримати p-значення, z-оцінку, довірчий інтервал і відносний підйом.
Калькулятор значущості A/B тесту
Введіть відвідувачів і конверсії для кожного варіанту, щоб перевірити, чи різниця реальна чи просто шум.
Результати
Статистично значимий
Різниця малоймовірна через випадок при вибраному рівні впевненості.
Chance this gap is just luck — lower is stronger.
How far apart the two rates are, in standard errors.
The likely range for the true difference.
Документація
A/B тестування за одну хвилину
Ви змінили кнопку, заголовок або процес оформлення. Версія A — це стара, версія B — нова. B виглядає краще — її конвертували 15% відвідувачів проти 10% для A. Але це може бути просто везіння, як коли кидати монету десять разів можна отримати сім орлів?
Цей калькулятор відповідає на це питання. Ви вводите, скільки людей бачило кожну версію та скільки їх конвертувало, і він показує вам ймовірність того, що різниця, яку ви виміряли, реальна, а не випадковий шум. Якщо ця ймовірність достатньо висока, у вас є переможець. Якщо ні, ви продовжуєте тест.
Одна цифра, на яку потрібно звернути увагу — це p-значення: ймовірність побачити розрив принаймні такий великий, якщо б дві версії були насправді однаковими. Невелике p-значення (скажімо, нижче 0,05) означає "це рідко траплялось би випадково, тому різниця, ймовірно, реальна".
Як це використовувати
- Відвідувачі — скільки унікальних людей було показано кожну версію.
- Конверсії — скільки з них зробили те, що вас цікавить (купили, зареєструвалися, клацнули).
- Рівень впевненості — наскільки впевнені ви, перш ніж оголосити переможця. 95% — це стандарт галузі.
- Гіпотеза — двостороння запитує "чи B відрізняється від A?" (безпечніше, за замовчуванням); односторонна запитує тільки "чи B краще за A?" (чутливіше, але ви повинні вирішити напрямок перед запуском тесту).
Результат оновлюється в реальному часі, а вхідні дані зберігаються в URL сторінки, тому ви можете додати результат до закладок або поділитися ним. Скидання очищує форму; Завантажити приклад даних заповнює виконаний приклад.
Виконаний приклад
| Відвідувачі | Конверсії | Коефіцієнт | |
|---|---|---|---|
| A (контроль) | 1 000 | 100 | 10,0% |
| B (варіація) | 1 000 | 150 | 15,0% |
Це 5 пунктів абсолютного підйому та +50% відносного підйому. Калькулятор повертає p-значення близько 0,0007 — менше 0,05 — тому при 95% впевненості результат статистично значимий. Грубо кажучи, якби дві версії були справді однаковими, ви бачили б розрив такого розміру менше одного разу з тисячі тестів.
Математика (двопропорційний z-тест)
Під капотом це стандартний двопропорційний z-тест, той самий тест, який викладається у вступних статистиках та використовується основними інструментами A/B.
-
Коефіцієнт конверсії кожної групи:
де — конверсії та — відвідувачі.
-
Об'єднаний коефіцієнт, припускаючи (для нульової гіпотези) обидві групи мають один справжній коефіцієнт:
-
Стандартна помилка різниці:
-
z-оцінка — скільки стандартних помилок розокремлюють два коефіцієнти:
-
p-значення походить від стандартного нормального розподілу . Двостороння: . Односторонна: .
-
Значимо, коли , де (тому 0,05 при 95%).
Калькулятор також повідомляє довірчий інтервал для різниці, обчислений з необ'єднаною стандартною помилкою : правдоподібний діапазон справжнього розриву. Якщо цей інтервал виключає 0, результат значимий.
При 95% впевненості z крім ±1,96 (затінені хвости, 5% площі) вважається значимим.
Чесно читати результат
- Статистична значущість — це не ділова значущість. Підйом на 0,1% може бути статистично реальним, але не варто його запускати.
- Не підглядайте й не зупиняйтеся рано. Перевірка p-значення кожного дня та зупинка в момент, коли воно впаде нижче 0,05, інфлює вашу хибно-позитивну частоту. Визначте розмір вибірки заздалегідь і дайте тесту закінчитися.
- Дотримуйтеся правила розміру вибірки. Звичайне наближення надійне, коли кожна група має принаймні ~10 конверсій і ~10 не-конверсій. З невеликими цифрами розглядайте результат тільки як напрям.
- Впевненість ≠ ймовірність того, що B краще. Рівень впевненості 95% означає, що процедура неправильна щонайбільше 5% часу в довгостроковій перспективі — це твердження частотників, а не "95% шанс того, що B виграє".
- Один тест, одна метрика. Тестування багатьох метрик або варіантів одночасно множить ймовірність помилки; компенсуйте це (наприклад, Bonferroni) або попередньо зареєструйте єдину метрику, яка визначає тест.
Обчисліть самостійно
Кожен уривок обчислює двосторонній p-значення для наведеного вище виконаного прикладу.
1=2*(1-NORM.S.DIST(
2 (B2/A2 - B1/A1) /
3 SQRT(((B1+B2)/(A1+A2))*(1-(B1+B2)/(A1+A2))*(1/A1+1/A2)),
4 TRUE))
5' A1,B1 = control visitors, conversions ; A2,B2 = variation visitors, conversions
61from math import sqrt, erf
2
3def ab_pvalue(n1, x1, n2, x2, two_sided=True):
4 p1, p2 = x1 / n1, x2 / n2
5 p = (x1 + x2) / (n1 + n2)
6 se = sqrt(p * (1 - p) * (1 / n1 + 1 / n2))
7 z = (p2 - p1) / se
8 phi = lambda v: 0.5 * (1 + erf(v / sqrt(2))) # standard normal CDF
9 return 2 * (1 - phi(abs(z))) if two_sided else 1 - phi(z)
10
11print(ab_pvalue(1000, 100, 1000, 150)) # ~0.00072
121// erf via Abramowitz & Stegun 7.1.26
2function erf(x) {
3 const s = x < 0 ? -1 : 1;
4 x = Math.abs(x);
5 const t = 1 / (1 + 0.3275911 * x);
6 const y = 1 - ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t
7 - 0.284496736) * t + 0.254829592) * t * Math.exp(-x * x);
8 return s * y;
9}
10const phi = z => 0.5 * (1 + erf(z / Math.SQRT2));
11
12function abPValue(n1, x1, n2, x2, twoSided = true) {
13 const p1 = x1 / n1, p2 = x2 / n2, p = (x1 + x2) / (n1 + n2);
14 const se = Math.sqrt(p * (1 - p) * (1 / n1 + 1 / n2));
15 const z = (p2 - p1) / se;
16 return twoSided ? 2 * (1 - phi(Math.abs(z))) : 1 - phi(z);
17}
18console.log(abPValue(1000, 100, 1000, 150)); // ~0.00072
191public static double abPValue(int n1, int x1, int n2, int x2) {
2 double p1 = (double) x1 / n1, p2 = (double) x2 / n2;
3 double p = (double) (x1 + x2) / (n1 + n2);
4 double se = Math.sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
5 double z = (p2 - p1) / se;
6 // Phi via the error function; erf approximated (A&S 7.1.26) separately.
7 double phi = 0.5 * (1 + erf(Math.abs(z) / Math.sqrt(2)));
8 return 2 * (1 - phi);
9}
101static double AbPValue(int n1, int x1, int n2, int x2) {
2 double p1 = (double)x1 / n1, p2 = (double)x2 / n2;
3 double p = (double)(x1 + x2) / (n1 + n2);
4 double se = Math.Sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
5 double z = (p2 - p1) / se;
6 double phi = 0.5 * (1 + Erf(Math.Abs(z) / Math.Sqrt(2)));
7 return 2 * (1 - phi);
8}
91#include <cmath>
2
3double ab_pvalue(int n1, int x1, int n2, int x2) {
4 double p1 = (double)x1 / n1, p2 = (double)x2 / n2;
5 double p = (double)(x1 + x2) / (n1 + n2);
6 double se = std::sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
7 double z = (p2 - p1) / se;
8 double phi = 0.5 * (1 + std::erf(std::fabs(z) / std::sqrt(2.0)));
9 return 2 * (1 - phi);
10}
111import "math"
2
3func abPValue(n1, x1, n2, x2 float64) float64 {
4 p1, p2 := x1/n1, x2/n2
5 p := (x1 + x2) / (n1 + n2)
6 se := math.Sqrt(p * (1 - p) * (1/n1 + 1/n2))
7 z := (p2 - p1) / se
8 phi := 0.5 * (1 + math.Erf(math.Abs(z)/math.Sqrt2))
9 return 2 * (1 - phi)
10}
111// erf from the `libm` crate; std has no erf.
2fn ab_pvalue(n1: f64, x1: f64, n2: f64, x2: f64) -> f64 {
3 let (p1, p2) = (x1 / n1, x2 / n2);
4 let p = (x1 + x2) / (n1 + n2);
5 let se = (p * (1.0 - p) * (1.0 / n1 + 1.0 / n2)).sqrt();
6 let z = (p2 - p1) / se;
7 let phi = 0.5 * (1.0 + libm::erf(z.abs() / 2f64.sqrt()));
8 2.0 * (1.0 - phi)
9}
101function ab_pvalue($n1, $x1, $n2, $x2) {
2 $p1 = $x1 / $n1; $p2 = $x2 / $n2;
3 $p = ($x1 + $x2) / ($n1 + $n2);
4 $se = sqrt($p * (1 - $p) * (1 / $n1 + 1 / $n2));
5 $z = ($p2 - $p1) / $se;
6 $phi = 0.5 * (1 + erf(abs($z) / sqrt(2)));
7 return 2 * (1 - $phi);
8}
91def ab_pvalue(n1, x1, n2, x2)
2 p1, p2 = x1.to_f / n1, x2.to_f / n2
3 p = (x1 + x2).to_f / (n1 + n2)
4 se = Math.sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2))
5 z = (p2 - p1) / se
6 phi = 0.5 * (1 + Math.erf(z.abs / Math.sqrt(2)))
7 2 * (1 - phi)
8end
91# R has this built in: prop.test does the whole thing.
2prop.test(c(100, 150), c(1000, 1000), correct = FALSE)$p.value # ~0.00072
3FAQ
Який розмір вибірки мені потрібен? Достатньо, щоб виміряний значимий підйом можна було виявити. Як мінімум, прагніть щонайменше кількох сотень конверсій на варіант; використовуйте спеціалізований калькулятор розміру вибірки з вашим базовим коефіцієнтом і найменшим підйомом, який варто виявити.
Двостороння чи односторонна? Використовуйте двосторонню, якщо у вас немає твердої, попередньої причини цікавитися тільки вдосконаленням. Односторонна подвоює вашу чутливість, але забороняє реагування на те, що B гірше.
Чому калькулятор показує довірчий інтервал? Він показує правдоподібний діапазон справжньої різниці, а не просто так/ні вердикт. Широкий інтервал, який охоплює 0, означає "недостатньо даних ще".
Це Баєсів? Ні — це частотськешний z-тест, найбільш широко викладаний та використовуваний метод. Баєсові A/B інструменти повідомляють "ймовірність того, що B переможе A" замість p-значення; обидва дійсні, вони відповідають на дещо різні питання.