websitelytics

Menu

A/B тесты — почему статистический критерий, это только одна сторона монеты

Опубликовано: 29 окт 2023

Хороший, проверенный временем, быстрый в расчетах статистический критерий — это то, к чему стремятся наверное все платформы a/b тестирования, когда разрабатывают свои статистические движки. Достаточно часто на сайтах таких платформ можно видеть в качестве описания преимуществ именно рассказ про то, какие продвинутые методы используются в определении результатов a/b тестов.

С этим нельзя спорить в теории, но практика и здесь может внести свои неожиданные поправки. Рассмотрим стандартный случай, когда наш эксперимент проведен корректно, результаты аккуратно собраны, но при их оценке мы видим, что из-за большой дисперсии нашей метрики MDE получился заметно больше наблюдаемого эффекта и наша оцениваемая метрика не прокрашивается. Поскольку мы видим, что есть намек, на то, что эффект в действительности может присутствовать, не удивительно, если возникнет мысль, что здесь можно попробовать применить какие-то продвинутые методы снижения дисперсии: CUPED, стратификация и т. п.

Однако, так ли все сразу очевидно? Что если наша большая дисперсия — это результат шума в данных, который в нашем случае не имеет прямого отношения к тестируемой фиче и замеряемой нами метрике? Т.е. другими словами, некие "левые" выбросы, экстремальные значения влияют на результат эксперимента и не дают нам его точно посчитать. В чем же смысл применять продвинутые методы снижения дисперсии к этому шуму? Мне кажется очевидным, что вначале нужно попробовать разобраться с этими выбросами. Возможно потом и не придется применять сложные дополнительные методы.

Итак, если все изобразить в виде простой схемки, то две стороны процесса оценки результатов эксперимента могут выглядеть так:

Ключевое слово здесь во второй части — "эффективное". Для пояснения рассмотрим простой пример. Сгенерируем данные с очевидными выбросами, которые затем найдем с помощью стандартных методов.

import numpy as np

# Set a random seed for reproducibility
np.random.seed(11)

# Generate synthetic data with outliers
data = np.concatenate([
    np.random.normal(0, 1, 50),  # Inlier data
    np.random.normal(10, 2, 5),  # Outliers
])

Мы видим, что boxplot показывает нам наличие выбросов слева и справа, но в действительности то, слева их как бы нет, мы добавили их только справа. И ситуация может быть еще более неоднозначной в случае, если наши данные не одномерные, а двумерные, как например, при оценке CTR или любой другой ratio-метрики.

Поэтому в данной статье мы выделили методику обнаружения выбросов, как дополнительную часть к статистическому критерию.