CUPED простыми словами

Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.

Зачем это знать

CUPED — один из самых мощных инструментов в современных A/B-тестах. Microsoft, Netflix, Booking используют. Снижает variance на 30-70% → нужно в 2-3 раза меньше выборки для того же effect detection.

На middle+ собесах в FAANG спрашивают CUPED. Без знания — минус очки.

Короткое объяснение

CUPED (Controlled-experiment Using Pre-Experiment Data) использует pre-experiment behavior юзеров, чтобы уменьшить шум в метрике.

Идея: если user был heavy user до эксперимента, он и в эксперименте будет. Учитываем это — variance падает.

Формула

Y_CUPED = Y - θ × (X - mean(X))

Где:

  • Y — метрика в эксперименте
  • X — та же метрика в pre-experiment period (covariate)
  • θ — коэффициент: Cov(Y, X) / Var(X) (OLS slope)

Интерпретация: «очистить» Y от variance, объяснённой X.

Пример

Метрика: revenue per user за эксперимент (2 недели).

Covariate: revenue per user за предыдущие 4 недели.

Сильная корреляция → θ высокий → большая reduction variance.

Reduction variance

Var(Y_CUPED) = Var(Y) × (1 - ρ²)

Где ρ — корреляция Y и X.

Если ρ = 0.7 → variance падает на 49%. Если ρ = 0.9 → на 81%.

Когда CUPED эффективен

  • User-level метрики с pre-experiment data
  • Стабильные users (revenue, sessions, time-on-site)
  • Не new users — нет pre-experiment history

Когда НЕ работает

  • Новые пользователи (нет pre-experiment data)
  • Новые features (нет аналога в прошлом)
  • Discrete метрики вроде conversion — меньше gain

Как реализовать в SQL

WITH user_data AS (
    SELECT
        user_id,
        SUM(CASE WHEN DATE BETWEEN '2026-04-01' AND '2026-04-14' THEN revenue END) AS y,
        SUM(CASE WHEN DATE BETWEEN '2026-03-01' AND '2026-03-31' THEN revenue END) AS x
    FROM transactions
    GROUP BY user_id
),
theta AS (
    SELECT covar_pop(y, x) / NULLIF(var_pop(x), 0) AS theta, avg(x) AS mean_x
    FROM user_data
)
SELECT
    u.user_id,
    u.y - t.theta * (u.x - t.mean_x) AS y_cuped
FROM user_data u, theta t;

Потом t-test на y_cuped между группами.

В Python

import numpy as np

def cuped(y, x):
    theta = np.cov(y, x)[0, 1] / np.var(x)
    return y - theta * (x - np.mean(x))

y_adjusted = cuped(y, x_pre_experiment)
# t-test на y_adjusted вместо y

Важные детали

Рассчитывать θ на всей выборке

НЕ отдельно по control и treatment. Иначе bias.

Random assignment

CUPED работает только с randomized treatment (обычный A/B).

Check balance

Pre-experiment X должен быть balanced между группами (ожидаем, т.к. random assignment).

Gains в выборке

Если variance упал в 2 раза → можно в 2 раза меньше выборки для той же statistical power. Или сократить тест вдвое по времени.

В компаниях со многими экспериментами — огромный выигрыш.

Альтернативы

  • Stratification: разделить на страты, агрегировать
  • Regression adjustment: линейная модель с features
  • Double machine learning: для complex covariates

CUPED — простейший, часто работает хорошо.

На собесе

«Что такое CUPED?» Метод уменьшения variance через pre-experiment covariate.

«Почему работает?» Убирает шум, объяснённый covariate.

«Какое условие?» Correlation между Y и X должна быть.

«Gain в практике?» 30-70% reduction variance для revenue-like метрик.

Частые ошибки

Считать θ отдельно по группам

Bias. Только на общей выборке.

Применять на новых users

Pre-experiment data нет → X = 0 → no gain и potentially misleading.

Correlation с treatment

Если X коррелирует с assignment (что не должно быть при random) — результат biased.

Связанные темы

FAQ

Работает на conversion?

Да, но gain меньше, чем на continuous.

Нужна регрессия?

CUPED — простейшая form of regression adjustment.

Сложно внедрить?

Нет, пара строк кода. Требует только pre-experiment data.


Тренируйте A/B — откройте тренажёр с 1500+ вопросами для собесов.