tgoop.com/zasql_python/301
Last Update:
Анализ экспериментов с Ratio-метриками
Проводя эксперименты, обычно, мы используем базовые методы: t-test, z-test, bootstrap (если данных не так много). Это для одних метрик, но, предположим, мы работаем с метриками-отношения (представляют из себя деление суммы случайной величины X на сумму случайной величины Y).
В этом случае в группе A и группе B у нас нет дисперсии. В самом деле, рассмотрим средний чек - метрика отношения (сумма GMV / количество заказов), CTR (сумма кликов / количество показов). Получаем некоторую метрику Za и Zb для которой мы знаем значение, но дисперсии метрики не знаем.
Отсюда выход:
а) провести бутстрап, чтобы найти распределение этой метрики и узнать распределение статистики
б) бакетировать (меньше по ресурсам, чем бутстрап).
в) применять другие методы (например, линеаризацию или дельта-метод).
г*) что-то другое...
Бутстрап
Для оценки распределения метрики можем использовать выборочные значения в группе A и группе B и найти разницу, таким образом, мы получим «разницу средних». Из минусов: MDE не рассчитать (при дизайне эксперимента), очень долгий расчет при больших выборках, ресурсов может не хватить.
Расчет для конкретной выборки, можно разницу средних потом посчитать
def bootstrap_ratio(data, nominator, denominator, group_column, group_value, n_iter=10000):
group_data = data[data[group_column] == group_value]
boot_ratios = []
for _ in range(n_iter):
sample = group_data.sample(len(group_data), replace=True)
ratio = sample[nominator].sum() / sample[denominator].sum()
boot_ratios.append(ratio)
return np.array(boot_ratios)
Бакетизация
Делим также пользователей по бакетам (с их GMV и количеством заказов), распределение метрики будет нормальным, главное, чтобы в бакетах было достаточное количество наблюдений. Мы делаем n-подвыборок (где n - это количество бакетов). Из минусов: сложность работать с маленькими выборками, зависимость от количества бакетов (тонкая настройка).
def bucketize(data, nominator, denominator, n_buckets=50, random_state=42):
data = data.sample(frac=1, random_state=random_state).reset_index(drop=True)
buckets = np.array_split(data, n_buckets)
bucket_ratios = [bucket[nominator].sum() / bucket[denominator].sum() for bucket in buckets]
return bucket_ratios
Пару слов про дельта-метод и линеаризацию.
В общем-то это об одном и том же. Мы хотим найти дисперсию метрики для того, чтобы применить классические методы (например, t-test). В дельта-методе мы корректируем дисперсию на корреляцию двух случайных величин (числителя и знаменателя). Только есть разница: дельта-метод вычисляет дисперсию на уровне выборки сразу, а линеаризация позволяет Ratio-метрику превратить в поюзерную. Результаты сонаправлены.
Дельта-метод
def calculate_ratio_variance(values_numerator, values_denominator):
mean_num = np.mean(values_numerator)
mean_denom = np.mean(values_denominator)
variance_num = np.var(values_numerator, ddof=1)
variance_denom = np.var(values_denominator, ddof=1)
covariance_num_denom = np.cov(values_numerator, values_denominator)[0, 1]
ratio_variance = (
(variance_num / mean_denom ** 2)
- (2 * (mean_num / mean_denom ** 3) * covariance_num_denom)
+ ((mean_num ** 2 / mean_denom ** 4) * variance_denom)
)
return ratio_variance
Линеаризация
# ratio_control - ratio-метрика в контрольной группе (для теста также рассчитывается)
def calculate_ratio_control(numerator_control, denominator_control):
return sum(numerator_control) / sum(denominator_control)
ratio_control = calculate_ratio_control(numerator_control, denominator_control)
def linearization(numerator, denominator, ratio_control):
return numerator - ratio_control * denominator
Дополнительные материалы для ознакомления: первый, второй, третий, четвертый, пятый
Понравился пост? Давайте наберем 150 🐳🐳🐳, если хотите продолжение, пишите в комментариях, часто ли используете подобные методы?
BY Заскуль питона (Data Science)
Share with your friend now:
tgoop.com/zasql_python/301