tgoop.com/zasql_python/419
Last Update:
Симуляция A/A тестов и зачем это нужно
A/A тест — это эксперимент, где обе группы одинаковы. Он нужен, чтобы проверить: работает ли наша система экспериментов честно и не выдумывает эффекты там, где их нет.
Самое главное, для чего мы проводим синтетический A/A тест (на большом количестве итераций) — это контроль ошибки первого рода. Ошибка первого рода (False Positive Rate) — это вероятность найти изменения там, где их нет. То есть мы заранее знаем, какой процент экспериментов ложно прокрасится (обычно, это очень маленькие вероятности в районе 0.01, 0.05, иногда 0.1, но достаточно редко).
Зачастую это нужно для проверки сплитовалке на определенном срезе пользователей / с кастомными метриками (которые будут участвовать в эксперименте).
В некоторых компаниях есть команда A/B платформы, которая занимается валидацией метрик, применением критериев к различным выборкам / метрикам.
В компании важно уметь пересчитывать ошибки I и II рода на разных срезах. Без этого мы не можем быть уверены, что группы изначально одинаковые. Если этого не будет, то утверждать о том, что изначально выборки были одинаковые (предположение для A/B теста) сказать нельзя. Метрики на предпериоде до эксперимента могут разъезжаться.
В каких случаях стоит запускать проверки?
1. Когда в компании уже есть процесс пересчёта метрик и нужно убедиться, что он работает корректно.
2. Когда появляется новая поверхность или метрика. Важно проверить, что группы не расходятся случайно.
3. Когда есть риск выбросов: несколько объектов могут сильно влиять на результат и завышать вероятность ложных срабатываний.
Я видел историю, когда был запущен эксперимент одним аналитиком, но при подведении итогов на определенном срезе покупателей (кто фактически видел эту фичу), получили ошибку первого рода 0.15 на целевой метрике (по которой мы принимаем решением), хотя ожидалось 0.05, то есть ошибку первого рода мы не контролируем => эксперимент невалиден. Затем я посмотрел, что происходило с группами на предпериоде, целевая метрика по группам разъехалась очень сильно, а это нарушает ключевое предположение A/B теста.
Как запустить синтетическую проверку?
Давайте запустим симуляцию: 10 000 A/A тестов на случайных группах и посмотрим, как ведут себя p-value
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
data = np.random.normal(loc=100, scale=10, size=10_000)
alpha = 0.05
p_values = []
for _ in range(10_000):
idx = np.random.permutation(len(data))
a_idx, b_idx = np.array_split(idx, 2)
a, b = data[a_idx], data[b_idx]
_, p = stats.ttest_ind(a, b)
p_values.append(p)
print('Ошибка первого рода:', np.mean(np.array(p_values) < alpha)) # в идеале здесь будет значение в районе 0.05
plt.hist(p_values, bins=50, edgecolor="black")
plt.xlabel("p-value")
plt.title("Распределение p-value в A/A тесте (10000 симуляций)")
plt.show()
Что мы ожидаем увидеть в ходе синтетического A/A теста?
Равномерное распределение p-value, которое говорит нам о том, что все хорошо, нет проблем. Это значит, что система работает корректно: ложные срабатывания происходят ровно с той частотой, которую мы задали. Можно думать про это как про честную монетку (предположим, что мы подкидываем ее 100 раз, а затем проводим 10 000 симуляций): иногда выпадет значимо, но ровно с той частотой, которую мы сами задали (например, 5% при alpha=0.05).
A/A тесты — это краш-тест для платформы экспериментов. Если они честные, бизнес может доверять результатам A/B.
Понравился пост? Ставьте