A/B testo reikšmingumo skaičiuotuvas
Patikrinkite, ar jūsų A/B testo rezultatas yra statistiškai reikšmingas. Įveskite lankytojus ir konversijas, kad gautumėte p-reikšmę, z-skaičių, pasitikėjimo intervalą ir santykinį padidėjimą.
A/B testo reikšmingumo skaičiuotuvas
Įveskite lankytojus ir konversijas kiekvienam variantui, kad patikrintumėte, ar skirtumas yra tikras, ar tik triukšmas.
Rezultatai
Statistiškai reikšminga
Skirtumas mažai tikėtinas atsitiktinai, atsižvelgiant į jūsų pasirinktą pasitikėjimo lygį.
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.
Dokumentacija
A/B testavimas per minutę
Pakeitėte mygtuką, antraštę ar mokėjimo srautą. Versija A yra senoji, versija B yra naujoji. B atrodo geriau — ji konvertavo 15% lankytojų, o A - 10%. Tačiau ar tas skirtumas gali būti tik sėkmė, kaip ir metant monetą dešimt kartų, galima gauti septynis herbus?
Šis skaičiuotuvas atsakys tiksliai į tai. Jūs įvedate, kiek žmonių pamatė kiekvieną versiją ir kiek jų konvertavo, ir jis jums pasakys tikimybę, kad išmatuotas skirtumas yra tikras, o ne atsitiktinis triukšmas. Jei ši tikimybė yra pakankamai didelė, turite nugalėtoją. Jei ne, tęsite testą.
Svarbiausias skaičius yra p-reikšmė: tikimybė pamatyti tokį skirtumą, jei abi versijos iš tikrųjų būtų identiškos. Maža p-reikšmė (pvz., žemiau 0,05) reiškia „tai retai nutiktų atsitiktinai, todėl skirtumas tikriausiai tikras".
Kaip jį naudoti
- Lankytojai — kiek unikalių žmonių matė kiekvieną versiją.
- Konversijos — kiek jų padarė tai, kas jums rūpi (pirko, užsiregistravo, spustelėjo).
- Pasitikėjimo lygis — kiek tikras norite būti prieš priskirdami nugalėtoją. 95% yra industrijoje priimtas standartas.
- Hipotezė — dvipusė klausia „ar B skiriasi nuo A?" (saugesne, numatytoji); vienpusė klausia tik „ar B geriau nei A?" (jautresnė, tačiau turite iš anksto nuspręsti kryptį).
Rezultatas atsinaujina iš karto, o įvestys saugomos puslapio URL, todėl galite pasidėti žymę arba pasidalinti rezultatu. Atstatyti išvalo formą; Įkelti pavyzdinius duomenis užpildo išsaugotą pavyzdį.
Praktinis pavyzdys
| Lankytojai | Konversijos | Norma | |
|---|---|---|---|
| A (kontrolė) | 1 000 | 100 | 10,0% |
| B (variantas) | 1 000 | 150 | 15,0% |
Tai yra 5 procentinių punktų absoliutus padidėjimas ir +50% santykinis padidėjimas. Skaičiuotuvas grąžina p-reikšmę apie 0,0007 — žemiau 0,05 — todėl su 95% pasitikėjimo rezultatas yra statistiškai reikšmingas. Maždaug tariant, jei abi versijos iš tikrųjų būtų tapačios, tokį skirtumą pamatytumėte mažiau nei kartą iš tūkstančio testų.
Matematika (dviejų proporcijų z-testas)
Iš esmės tai yra standartinis dviejų proporcijų z-testas, tas pats testas, kuris mokomasi įvadinėje statistikoje ir kurį naudoja pagrindiniai A/B testų įrankiai.
-
Konversijos norma kiekvienai grupei:
kur yra konversijos ir yra lankytojai.
-
Sujungta norma, darant prielaidą (nulinio pagrindo hipotezei), kad abi grupės turi vieną tikrąją normą:
-
Standartinė skirtumo paklaida:
-
Z-skaičius — kiek standartinių paklaidų atskirtos abi normos:
-
P-reikšmė gaunama iš standartinio normalaus pasiskirstymo . Dvipusė: . Vienpusė: .
-
Reikšminga kai , kur (todėl 0,05 esant 95%).
Skaičiuotuvas taip pat ataskaito pasitikėjimo intervalą skirtumui, apskaičiuotą naudojant nesujungtą standartinę paklaidą : tikimo tikrojo skirtumo diapazonas. Jei šis intervalas neapima 0, rezultatas yra reikšmingas.
Esant 95% pasitikėjimui, z, viršijantis ±1,96 (šešėlinti žarnos, 5% ploto), laikomas reikšmingu.
Rezultato sąžininga interpretacija
- Statistinė reikšmė nėra verslo reikšmė. 0,1% padidėjimas gali būti statistiškai tikras, tačiau nepablogina vertės jį pristatyti.
- Nežiūrėkite ir sustabdykite anksčiau. Kasdien tikrinant p-reikšmę ir sustabdant ją, kai ji nukrenta žemiau 0,05, didina klaidingai teigiamų rezultatų dažnį. Nuspręskite imties dydį iš anksto ir leiskite testui baigis.
- Stebėkite imties dydžio nykščio taisyklę. Normalus aproksimavimas yra patikimas, kai kiekviena grupė turi bent maždaug ~10 konversijų ir ~10 ne-konversijų. Su mažais skaičiais, rezultatą traktuokite tik kaip orientacinį.
- Pasitikėjimas ≠ tikimybė B yra geriau. 95% pasitikėjimo lygis reiškia, kad procedūra yra neteisinga daugiausia 5% laiko ilgalaikėje perspektyvoje — tai dažninis teiginys, o ne „95% šansa B laimės".
- Vienas testas, viena metrika. Vienu metu tikrinant daug metrikų arba variantų padaugina šansą, kad atsitiktinai; taissykite tai (pvz. Bonferroni) arba iš anksto registruokite vienintelę metriką, kuri nusprendžia testą.
Apskaičiuokite patys
Kiekvienas nuotrauka apskaičiuoja dvipusę p-reikšmę aukščiau pateiktam praktiniam pavyzdziui.
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
3DUK
Koks imties dydis man reikalingas? Toks, kuriame būtų galima aptikti prasmingą padidėjimą. Kaip minimalus tikslas, siekite bent kelių šimtų konversijų kiekvienam variantui; naudokite dedikuotą imties dydžio skaičiuotuvą su savo baziniu greičiu ir mažiausiu vertėtu aptikti padidėjimu.
Dvipusė ar vienpusė? Naudokite dvipusę, nebent turite tvirтą, iš anksto patvirtintą priežastį rūpintis tik pagerintu. Vienpusė dvigubai padidina jautrumą, bet draudžia reaguoti į B būtiną blogiau.
Kodėl skaičiuotuvas rodo pasitikėjimo intervalą? Jis rodo tikimo tikrojo skirtumo diapazoną, ne tik taip/ne verdiktą. Platus intervalas, kuris kerta 0, reiškia „dar nepakanka duomenų".
Ar tai Bayesian? Ne — tai dažninis z-testas, labiausiai mokomasis ir naudojamas metodas. Bayesian A/B įrankiai ataskaito „tikimybę B laimės A" vietoj p-reikšmės; abu yra galiojantys, jie atsako į šiek tiek skirtingus klausimus.