Что такое power analysis и для чего он используется в A/B тестировании?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Power Analysis в A/B тестировании
Power Analysis (анализ мощности) — это статистический метод, который определяет необходимый размер выборки для надежного обнаружения эффекта в A/B тесте. Другими словами, это ответ на вопрос: "Сколько пользователей мне нужно, чтобы уверенно обнаружить разницу?"
Ключевые компоненты Power Analysis
1. Размер эффекта (Effect Size)
Величина различия между контролем и тестом, которую ты хочешь обнаружить.
Примеры:
- Хочу обнаружить увеличение конверсии с 10% до 12% (относительное +20%)
- Хочу обнаружить увеличение LTV с $100 до $110 (абсолютное +$10)
# Расчет размера эффекта для пропорций (Cohen's h)
from math import asin, sqrt
p1 = 0.10 # baseline конверсия
p2 = 0.12 # ожидаемая конверсия в тесте
# Cohen's h
effect_size = 2 * (asin(sqrt(p2)) - asin(sqrt(p1)))
print(f"Effect size (Cohen's h): {effect_size:.4f}")
2. Уровень значимости (Significance Level, α)
Вероятность ошибки Type I (ложноположительный результат) — когда ты считаешь, что есть разница, а её нет.
Обычно α = 0.05 (5%), что означает 95% уверенность в результатах.
3. Статистическая мощность (Power, 1-β)
Вероятность обнаружения эффекта, если он действительно существует. Это вероятность того, что ты не допустишь ошибку Type II (не пропустишь реальный эффект).
Обычно выбирают power = 0.80 (80%), но для критичных решений используют 0.90.
4. Размер выборки (Sample Size)
Количество пользователей в каждом варианте теста.
Типы ошибок
| Результат | Контроль лучше | Тест лучше |
|---|---|---|
| Есть разница | Верно | Верно |
| Нет разницы | Type II (β) | Type I (α) |
- Type I (False Positive): Ты думаешь, что есть разница, а её нет (контролируется α)
- Type II (False Negative): Ты думаешь, что разницы нет, а она есть (контролируется β)
Формула Power Analysis
import numpy as np
from scipy import stats
from statsmodels.stats.power import proportions_ztest
# Параметры теста
alpha = 0.05 # Уровень значимости
power = 0.80 # Мощность теста
p1 = 0.10 # Базовая конверсия контроля
p2 = 0.12 # Ожидаемая конверсия теста
# Расчет размера выборки для каждой группы
sample_size = proportions_ztest(
count=[0, 0], # Временные значения
nobs=[1, 1], # Временные значения
alternative='two-sided',
value=0,
prop_var="unequal"
)
# Используем другой подход
from statsmodels.stats.proportion import proportions_ztest
# Эффективнее использовать готовую функцию
from statsmodels.stats.power import tt_ind_solve_power
effect_size = (p2 - p1) / np.sqrt((p1 * (1 - p1) + p2 * (1 - p2)) / 2)
sample_size = tt_ind_solve_power(
effect_size=effect_size,
nobs1=None,
alpha=alpha,
power=power,
ratio=1.0,
alternative='two-sided'
)
print(f"Требуемый размер выборки на каждую группу: {int(sample_size):,}")
print(f"Всего пользователей в тесте: {int(sample_size * 2):,}")
Практические примеры
Пример 1: Тест кнопки (увеличение конверсии)
import numpy as np
from scipy import stats
# Текущая конверсия: 5%
# Ожидаемая конверсия: 5.5% (увеличение на 10%)
# Хотим 95% уверенность (α = 0.05) и 80% мощность
p1 = 0.05
p2 = 0.055
alpha = 0.05
beta = 0.20 # 1 - power
# Z-значения
z_alpha = stats.norm.ppf(1 - alpha / 2) # ~1.96
z_beta = stats.norm.ppf(1 - beta) # ~0.84
# Размер выборки
p = (p1 + p2) / 2
n = ((z_alpha + z_beta) ** 2 * (p * (1 - p) * 2)) / ((p2 - p1) ** 2)
print(f"Требуется {int(n):,} пользователей в каждой группе")
print(f"Всего: {int(n * 2):,} пользователей")
Результат: для обнаружения увеличения конверсии на 10% нужно ~6,200 пользователей в каждой группе, всего ~12,400 пользователей.
Пример 2: Расчет для разных размеров эффекта
import pandas as pd
from statsmodels.stats.power import tt_ind_solve_power
# Сравнение требуемых размеров выборки для разных эффектов
effects = [0.2, 0.5, 0.8] # Малый, средний, большой эффект
results = []
for effect in effects:
sample_size = tt_ind_solve_power(
effect_size=effect,
nobs1=None,
alpha=0.05,
power=0.80,
ratio=1.0,
alternative='two-sided'
)
results.append({
'effect_size': ['small', 'medium', 'large'][effects.index(effect)],
'cohen_d': effect,
'sample_per_group': int(sample_size),
'total_sample': int(sample_size * 2)
})
df = pd.DataFrame(results)
print(df)
Результат:
- Малый эффект (d=0.2): 393 пользователя на группу
- Средний эффект (d=0.5): 64 пользователя на группу
- Большой эффект (d=0.8): 25 пользователей на группу
Как выбрать размер эффекта
1. Используй исторические данные
-- Посмотри на прошлые тесты
SELECT
test_id,
control_conversion,
test_conversion,
ROUND((test_conversion - control_conversion) / control_conversion * 100, 1) as effect_pct
FROM ab_test_results
WHERE completed_at >= NOW() - INTERVAL '1 year'
ORDER BY completed_at DESC;
2. Используй бизнес-требования
Диаговый вопрос: "Какое улучшение конверсии было бы значимым для бизнеса?"
Если текущая конверсия 10%, то:
- 11% увеличение = +1 п.п. (может быть не практически значимо)
- 12% увеличение = +2 п.п. (может быть практически значимо)
- 15% увеличение = +5 п.п. (явно значимо)
3. Калькулятор эффекта
def estimate_effect_size(baseline, expected, test_type='proportion'):
"""
Оцени размер эффекта
baseline: текущее значение
expected: ожидаемое значение
"""
if test_type == 'proportion':
# Для конверсии, CTR и т.д.
from math import asin, sqrt
effect = 2 * (asin(sqrt(expected)) - asin(sqrt(baseline)))
else:
# Для непрерывных метрик (LTV, AOV)
effect = (expected - baseline) / (baseline ** 0.5)
# Интерпретация Cohen's d/h
if abs(effect) < 0.2:
return effect, 'small'
elif abs(effect) < 0.5:
return effect, 'small-to-medium'
elif abs(effect) < 0.8:
return effect, 'medium'
else:
return effect, 'large'
# Примеры
effect, interpretation = estimate_effect_size(0.10, 0.12)
print(f"Увеличение конверсии 10%→12%: {effect:.4f} ({interpretation})")
effect, interpretation = estimate_effect_size(0.10, 0.11)
print(f"Увеличение конверсии 10%→11%: {effect:.4f} ({interpretation})")
Когда использовать Power Analysis
Перед запуском теста:
- Определи минимальный значимый эффект
- Рассчитай требуемый размер выборки
- Проверь, достаточно ли пользователей, чтобы достичь этого
- Определи период теста
# Пример расчета времени теста
monthly_users = 100000
users_per_day = monthly_users / 30 # ~3,300 в день
sample_size_needed = 12400 # из примера выше
test_duration_days = sample_size_needed / users_per_day
print(f"Нужно ~{test_duration_days:.1f} дней для теста")
Ошибки при использовании Power Analysis
- Пиковый риск: не меняй размер выборки после запуска теста
- Множественное тестирование: если тестируешь много вариантов, нужна коррекция
- Переоценка эффекта: не предполагай слишком большой эффект
- Игнорирование спилловера: если пользователи в контроле видят тест
Чек-лист перед A/B тестом
- Определен минимальный значимый эффект
- Рассчитан требуемый размер выборки
- Проверен период теста
- Есть достаточно трафика для теста
- Выбран правильный уровень значимости (α)
- Выбрана правильная мощность (обычно 0.80)
Power Analysis — это не вариант, а обязательная часть планирования любого A/B теста.