Формулы стандартной ошибки есть для среднего и доли. А для медианы, 95-го перцентиля, отношения выручки к числу сессий? Тут выручают методы ресэмплинга: бутстреп и перестановочный тест. На собесе их любят, потому что по ответу сразу видно, понимает ли человек идею выборочного распределения.
Идея бутстрепа
Мы хотим знать, как гуляла бы статистика (например, медиана), если бы мы много раз собирали новую выборку из генеральной совокупности. Новых выборок нет, поэтому подменяем генеральную совокупность самой выборкой:
- Из выборки размера n вытаскиваем n наблюдений с возвращением.
- Считаем на этой псевдовыборке статистику.
- Повторяем B раз (обычно 1 000 - 10 000).
- Разброс полученных B значений оценивает выборочное распределение статистики.
import random
from statistics import median
def bootstrap_medians(data, b=2000, seed=1):
rnd = random.Random(seed)
n = len(data)
return [median(rnd.choices(data, k=n)) for _ in range(b)]
Перцентильный интервал
Самый простой доверительный интервал: отсортировать бутстреп-значения и взять 2.5-й и 97.5-й перцентили. Для разницы двух групп бутстрепят каждую группу отдельно, считают разницу статистик на каждой итерации и смотрят, накрывает ли интервал разницы ноль.
Есть и более точные варианты: базовый (reverse percentile), BCa с поправкой на смещение и асимметрию, студентизированный. Для собеса достаточно знать, что перцентильный интервал бывает неточным при скошенных распределениях и маленьких выборках, а BCa это исправляет.
Важные детали
- Ресэмплить надо единицы рандомизации. Если в тесте делили пользователей, а метрика это CTR по показам, то вытаскивают пользователей целиком со всеми их показами, а не отдельные показы. Иначе зависимость внутри пользователя игнорируется, и интервал получается слишком узким. Так же считают ratio-метрики: бутстреп пользователей, затем отношение сумм.
- Бутстреп не создаёт информацию. На 15 наблюдениях он даст интервал, но этот интервал может сильно врать.
- Плохо работает для экстремальных статистик: максимум, минимум, очень высокие перцентили при малой выборке. Максимум бутстреп-выборки никогда не превысит максимум исходной.
- Тяжёлые хвосты (выручка с китами) делают интервал среднего нестабильным: всё решает, сколько раз попал самый крупный покупатель.
- Затраты. 10 000 итераций на миллионах пользователей дорого. Помогает пуассоновский бутстреп (каждому наблюдению вес из Пуассона(1), легко параллелится) или бакеты: пользователей делят на, например, 100 групп, считают метрику по бакетам и работают с ними.
Перестановочный тест
Проверяет гипотезу «метки групп ничего не значат»:
- Считаем наблюдаемую разницу метрики между B и A.
- Перемешиваем метки групп между всеми наблюдениями, сохраняя размеры групп.
- Считаем разницу на перемешанных данных. Повторяем много раз.
- p-value это доля перестановок, где разница по модулю не меньше наблюдаемой.
Отличие от бутстрепа: бутстреп в первую очередь даёт интервал (неопределённость оценки), перестановка даёт p-value при H0 «распределения одинаковы». Перестановочный тест точен при обмениваемости наблюдений, но проверяет равенство распределений, а не только средних.
Когда что брать
- Среднее или доля, большая выборка: t-тест или z-тест, быстрее и не хуже.
- Медиана, квантиль, сложная метрика: бутстреп.
- Маленькая выборка и нужен честный p-value: перестановочный тест.
- Ratio-метрика: дельта-метод или бутстреп по пользователям.
Частые ошибки
- Ресэмплинг событий вместо пользователей.
- Бутстреп как «волшебство» на крошечных выборках.
- Интервал для максимума или 99.9-го перцентиля по бутстрепу.
- Разные random seed и малое B: результат «прыгает» между запусками.
Что спросят на собесе
- Объясните идею бутстрепа простыми словами.
- Как построить доверительный интервал для медианы?
- Что ресэмплить, если метрика считается по показам, а рандомизация по пользователям?
- Чем перестановочный тест отличается от бутстрепа?
- Когда бутстреп не работает?