← Назад к вопросам

Что такое power analysis и для чего он используется в A/B тестировании?

2.3 Middle🔥 131 комментариев
#A/B тестирование#Статистика и математика

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

Перед запуском теста:

  1. Определи минимальный значимый эффект
  2. Рассчитай требуемый размер выборки
  3. Проверь, достаточно ли пользователей, чтобы достичь этого
  4. Определи период теста
# Пример расчета времени теста
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

  1. Пиковый риск: не меняй размер выборки после запуска теста
  2. Множественное тестирование: если тестируешь много вариантов, нужна коррекция
  3. Переоценка эффекта: не предполагай слишком большой эффект
  4. Игнорирование спилловера: если пользователи в контроле видят тест

Чек-лист перед A/B тестом

  • Определен минимальный значимый эффект
  • Рассчитан требуемый размер выборки
  • Проверен период теста
  • Есть достаточно трафика для теста
  • Выбран правильный уровень значимости (α)
  • Выбрана правильная мощность (обычно 0.80)

Power Analysis — это не вариант, а обязательная часть планирования любого A/B теста.