Как определить необходимый размер выборки для A/B-теста?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Определение размера выборки для A/B-теста
Размер выборки в A/B-тестировании — критический параметр, определяющий статистическую мощность теста. Неправильный расчёт может привести к неверным выводам или излишним затратам времени и ресурсов.
Основные концепции
Статистическая мощность (Power) — вероятность обнаружить эффект, если он действительно существует. Обычно используется значение 0.80 или 0.90.
Уровень значимости (Alpha) — вероятность ошибки первого рода (false positive). Стандартное значение α = 0.05.
Размер эффекта (Effect Size) — минимальное изменение метрики, которое мы хотим обнаружить. Например, увеличение conversion rate на 2%.
Формула для пропорций
Для тестирования пропорций (conversion rate):
from scipy import stats
import math
def sample_size_proportion(baseline, effect_size, alpha=0.05, power=0.80):
p1 = baseline
p2 = baseline + effect_size
z_alpha = stats.norm.ppf(1 - alpha/2)
z_beta = stats.norm.ppf(power)
numerator = (z_alpha + z_beta) ** 2
variance = p1 * (1 - p1) + p2 * (1 - p2)
n = 2 * numerator * variance / (p2 - p1) ** 2
return math.ceil(n)
# Базовая конверсия 10%, хотим обнаружить +2%
baseline_conversion = 0.10
desired_effect = 0.02
n = sample_size_proportion(baseline_conversion, desired_effect)
print(f"Размер выборки (на группу): {n:,}")
Таблица критических значений
| Power | Alpha=0.05 | Описание |
|---|---|---|
| 0.80 | 2.80 | Стандартный выбор |
| 0.90 | 3.24 | Более консервативный |
Расчёт времени тестирования
def test_duration_days(daily_traffic, sample_size_per_group):
total_sample = sample_size_per_group * 2
days = total_sample / daily_traffic
return days
traffic = 100_000
sample = 1_000_000
days = test_duration_days(traffic, sample)
print(f"Длительность теста: {days:.1f} дней")
Последовательное тестирование
Вместо фиксированного размера, останавливаем тест при достаточной статистической уверенности:
from scipy.stats import chi2_contingency
def sequential_test(control_conv, control_trials, treat_conv, treat_trials):
table = [[control_conv, control_trials - control_conv],
[treat_conv, treat_trials - treat_conv]]
chi2, p_value, dof, expected = chi2_contingency(table)
return p_value < 0.05
Полный калькулятор
class ABTestCalculator:
def __init__(self, baseline, min_effect, alpha=0.05, power=0.80):
self.baseline = baseline
self.min_effect = min_effect
self.alpha = alpha
self.power = power
def calculate_sample_size(self):
z_alpha = stats.norm.ppf(1 - self.alpha/2)
z_beta = stats.norm.ppf(self.power)
p1 = self.baseline
p2 = self.baseline + self.min_effect
numerator = (z_alpha + z_beta) ** 2
variance = p1 * (1 - p1) + p2 * (1 - p2)
n = 2 * numerator * variance / (p2 - p1) ** 2
return math.ceil(n)
def calculate_test_duration(self, daily_traffic):
n = self.calculate_sample_size()
return n / daily_traffic
def report(self, daily_traffic):
n = self.calculate_sample_size()
days = self.calculate_test_duration(daily_traffic)
print(f"На группу: {n:,}")
print(f"Всего: {n*2:,}")
print(f"Дней при {daily_traffic:,}/день: {days:.1f}")
calc = ABTestCalculator(baseline=0.10, min_effect=0.02)
calc.report(daily_traffic=100_000)
Практические рекомендации
Определение минимального эффекта:
- E-commerce: базовая конверсия 3%, эффект +0.1%
- Subscription: baseline churn 5%, минимум -1%
Типичные ошибки:
- Игнорирование сезонности и временных факторов
- Множественные тесты без коррекции
- Остановка теста при благоприятных результатах
- Неправильная оценка базовой метрики
Заключение
Размер выборки зависит от силы эффекта, требуемой мощности и уровня значимости. Правильный расчёт гарантирует, что тест имеет достаточно данных для принятия обоснованного решения.