Посмотрел. Пуассоновский бутсрап не решает проблему вычислительных мощностей для повторного отбора (по крайней мере на одной машине), в статье такого тезиса просто нет. Там с помощью пуассоновского бутстрапа решается проблема как сгенерировать бутстрапированные выборки, не вынимая всю выборку припараллельных вычислениях, когда размер выборки n заранее не известен, а данные хранятся распределено.
Проверил разные реализации на одной машина на Python по самым затратным операциям — генерациям подвыборок. Пуассоновский бутстрап по времени оказывался не быстрее отбора с повторением, а иногда и медленнее.
import numpy as np
import pandas as pd
# df = pd.read_csv('file_name.csv')
data = df.n_bnr_clkd.values
n_trial = 5_000
print(n_trial, len(data)) # 5000, 449417
# Итерации отбора с повторением
%%time
for _ in range(n_trial):
_ = np.random.choice(data, size=len(data))
# Wall time: 11.8 s
# Итерации Пуассона
%%time
for _ in range(n_trial):
_ = np.random.poisson (1, size=len(data))
# Wall time: 58.7 s
# Генерация матрицы отбора с повторением
%%time
_ = np.random.choice(data, size=(n_trial, len(data)))
# Wall time: 59.7 s
# Генерация матрицы Пуассона
%%time
_ = np.random.poisson(1, size=(n_trial, len(data)))
# Wall time: 1min 8s
О, хороший пример, на самом деле имхо тут вопрос интерпретации метрики и всех преобразований которые применяешь к юзерам. Условно ты можешь попробовать посчитать adv_revenue per adv_gmv (т.е. только по тому gmv >0 и где была рек выручка) и ответить на вопрос, а стала ли реклама "отъедать" больше gmv где она была. Но думая в таком ключе можно продолжить и сказать что и твоя метрика adv_revenue per gmv интерпритируется также, что реклама могла "съесть" весть gmv, т.е. он будет 0.
Это по сути та же ratio-метрика, где ты имеешь у отдельного юзера adv_revenue и gmv . При линеаризации будет два случая когда gmv == 0 и gmv > 0 , тогда для юзера будет соответственно: 1) adv_revenue - CONTROL_RATIO * 0 = adv_revenue 2) adv_revenue - CONTROL_RATIO * gmv = lin_value И всегда adv_revenue будет больше чем lin_value , т.е. у одного юзера вклад в метрику как бы только за счет рекламной выручки (съеден весь gmv), а у другого получился какой-то вклад в метрику меньше чем его рекламная выручка (он принес какой-то gmv). Так что я бы попробовал на самом деле и с нулями. Только не стоит забывать, что обычно ratio-метрики еще парадоксу Симпсона подвержены, т.е. надо отдельно смотреть на суммарную рекламную выручку и суммарный gmv, чтобы понимать за счет чего произошло изменение, чтоб подстраховаться.
Знаю, на практике такой пример как у тебя считают бакетным методом на самом деле, но для него желательно иметь оооочень много наблюдений. Да, когда нет уверенности, бутстрап всегда можно применять и для ratio-метрик в том числе.
Привет, да, в табличке я осознано на это пошел, чтобы указать на общую поюзерную структуру в экспе, где у нас единица рандомизации и единица анализа совпадают. Но когда у нас единица анализа non-user, например, чек, чтобы посчитать его среднее значение, то надо оставлять только тех юзеров, у которых сигналы знаменателя больше 0, так как если пользователь "не сделал" чек, то и не участвует в определении ratio-метрики. Соответственно линеаризация сигналов и статоценка линеаризованных сигналов происходит только по тем, где сигнал знаменателя больше 0.
Вообще, если пойти в рассуждениях дальше, то можно понять, что любая метрика определяется как "оставь только те сигналы, где знаменатель больше нуля". Например, в статье я указываю ARPU, но если захочется ARPPU, то тебе в числителе и знаменателе надо оставить только тех пользователей, кто сконвертился в покупку, т.е. знаменатель по сигналам "совершил ли покупку" больше 0. Это может быть критично для некоторых метрик, числитель которых напрямую не зависит от знаменателя, например, какое-нибудь среднее число кликов по рекламному баннеру по платящим пользователям.
В Python определение любой метрики в таком случае будет следующим:
# num and denom are numpy arrays with user signals
numerator = numerator[denominator>0]
denominator = denominator[denominator>0]
metric = numerator.sum() / denominator.sum()
Да, действительно все так, в бутстрапе заложена такая идея. Помимо бутстрапа есть еще перестановочные тесты, там элементы не возвращаются в исходную выборку. В таких тестах мы две выборки объединяем в одну и потом опять делим рандомно на 2 и так много раз. Можно сделать исчерпывающий перестановочный тест, т.е. перебрать все имеющиеся сочетания, но их будет очень мноооого, а можно приблизительный, ограничив константой, это будет уже больше похоже на монте-карло)
Потому что это непараметрический метод, он ничего "не знает" об исходных данных и ему не нужны предпосылки или предположения об их природе, в отличие от ЦПТ. Бутстрап просто на основе имеющихся данных путем многих вычислений дает возможность построить эмпирическое распределение интересующей статистики и из этого распределения поотвечать на имеющиеся вопросы.
Посмотрел. Пуассоновский бутсрап не решает проблему вычислительных мощностей для повторного отбора (по крайней мере на одной машине), в статье такого тезиса просто нет. Там с помощью пуассоновского бутстрапа решается проблема как сгенерировать бутстрапированные выборки, не вынимая всю выборку при параллельных вычислениях, когда размер выборки n заранее не известен, а данные хранятся распределено.
Проверил разные реализации на одной машина на Python по самым затратным операциям — генерациям подвыборок. Пуассоновский бутстрап по времени оказывался не быстрее отбора с повторением, а иногда и медленнее.
О, хороший пример, на самом деле имхо тут вопрос интерпретации метрики и всех преобразований которые применяешь к юзерам.
Условно ты можешь попробовать посчитать
adv_revenue per adv_gmv
(т.е. только по тому gmv >0 и где была рек выручка) и ответить на вопрос, а стала ли реклама "отъедать" больше gmv где она была. Но думая в таком ключе можно продолжить и сказать что и твоя метрикаadv_revenue per gmv
интерпритируется также, что реклама могла "съесть" весть gmv, т.е. он будет 0.Это по сути та же ratio-метрика, где ты имеешь у отдельного юзера
adv_revenue
иgmv
. При линеаризации будет два случая когдаgmv == 0
иgmv > 0
, тогда для юзера будет соответственно:1)
adv_revenue - CONTROL_RATIO * 0 = adv_revenue
2)
adv_revenue - CONTROL_RATIO * gmv = lin_value
И всегда
adv_revenue
будет больше чемlin_value
, т.е. у одного юзера вклад в метрику как бы только за счет рекламной выручки (съеден весь gmv), а у другого получился какой-то вклад в метрику меньше чем его рекламная выручка (он принес какой-то gmv). Так что я бы попробовал на самом деле и с нулями.Только не стоит забывать, что обычно ratio-метрики еще парадоксу Симпсона подвержены, т.е. надо отдельно смотреть на суммарную рекламную выручку и суммарный gmv, чтобы понимать за счет чего произошло изменение, чтоб подстраховаться.
Знаю, на практике такой пример как у тебя считают бакетным методом на самом деле, но для него желательно иметь оооочень много наблюдений.
Да, когда нет уверенности, бутстрап всегда можно применять и для ratio-метрик в том числе.
Привет, да, в табличке я осознано на это пошел, чтобы указать на общую поюзерную структуру в экспе, где у нас единица рандомизации и единица анализа совпадают. Но когда у нас единица анализа non-user, например, чек, чтобы посчитать его среднее значение, то надо оставлять только тех юзеров, у которых сигналы знаменателя больше 0, так как если пользователь "не сделал" чек, то и не участвует в определении ratio-метрики. Соответственно линеаризация сигналов и статоценка линеаризованных сигналов происходит только по тем, где сигнал знаменателя больше 0.
Вообще, если пойти в рассуждениях дальше, то можно понять, что любая метрика определяется как "оставь только те сигналы, где знаменатель больше нуля". Например, в статье я указываю ARPU, но если захочется ARPPU, то тебе в числителе и знаменателе надо оставить только тех пользователей, кто сконвертился в покупку, т.е. знаменатель по сигналам "совершил ли покупку" больше 0. Это может быть критично для некоторых метрик, числитель которых напрямую не зависит от знаменателя, например, какое-нибудь среднее число кликов по рекламному баннеру по платящим пользователям.
В Python определение любой метрики в таком случае будет следующим:
Да, действительно все так, в бутстрапе заложена такая идея.
Помимо бутстрапа есть еще перестановочные тесты, там элементы не возвращаются в исходную выборку. В таких тестах мы две выборки объединяем в одну и потом опять делим рандомно на 2 и так много раз.
Можно сделать исчерпывающий перестановочный тест, т.е. перебрать все имеющиеся сочетания, но их будет очень мноооого, а можно приблизительный, ограничив константой, это будет уже больше похоже на монте-карло)
Потому что это непараметрический метод, он ничего "не знает" об исходных данных и ему не нужны предпосылки или предположения об их природе, в отличие от ЦПТ. Бутстрап просто на основе имеющихся данных путем многих вычислений дает возможность построить эмпирическое распределение интересующей статистики и из этого распределения поотвечать на имеющиеся вопросы.