Байесовский AB-тестирование с помощью Pyro

Байесовское AB-тестирование с использованием Pyro

Введение в байесовское мышление и AB-тестирование с использованием Pyro

Кредит: Free-Photos в Pixabay

Эта статья является введением в AB-тестирование с использованием языка программирования Python и вероятностного программирования (PPL) Pyro, альтернативы PyMC. Мотивацией к написанию этой статьи было расширение моего понимания байесовского статистического вывода с использованием фреймворка Pyro и помощь другим в этом процессе. Поэтому отзывы приветствуются и приветствуются.

Введение

Мой предыдущий опыт работы с байесовским моделированием в Python был связан с PyMC. Однако я столкнулся с проблемами при работе с некоторыми последними версиями. Поиск информации о других языках вероятностного программирования привел меня к открытию Pyro, универсального PPL, созданного Uber и поддерживаемого PyTorch на бэкэнде. Документация по Pyro и PyTorch приведена ниже.

Pyro

Глубокое универсальное вероятностное программирование

pyro.ai

Документация PyTorch – документация PyTorch 2.1

PyTorch – это оптимизированная библиотека тензоров для глубокого обучения с использованием графических процессоров и процессоров. Возможности, описанные в этой документации…

pytorch.org

Исследуя Pyro, я обнаружил, что мне сложно найти полностью развернутые учебники по AB-тестированию с использованием этого пакета. Эта статья направлена на заполнение этого пробела.

Статья состоит из пяти разделов. В первом разделе я дам введение в байесовское мышление, представление основанное на философии, которую методология отражает. Я кратко расскажу техническое представление о Pyro и байесовских методах, используемых для получения статистических выводов. Затем я проведу AB-тестирование с использованием Pyro и обсудим результаты. Затем я объясню причины проведения байесовского AB-тестирования в бизнес-среде. Заключительный раздел будет подводить итоги.

Введение в байесовское мышление

Байесовский процесс на высоком уровне относительно прост. Вначале у нас есть переменная, которая нас интересует. Мы указываем наше текущее представление об этой переменной, которое мы выражаем в виде распределения вероятностей (все в мире Байеса представляет собой распределение вероятностей). Это называется априорным распределением. Вероятность в байесовском выводе является эпистемической, то есть она возникает через нашу степень знания. Таким образом, распределение вероятности, которое мы указываем как наше априорное распределение, является как утверждением неопределенности, так и пониманием. Затем мы наблюдаем события из реального мира. Эти наблюдения затем используются для обновления нашего понимания переменной, которая нас интересует. Новое состояние нашего понимания называется апостериорным распределением. Мы также характеризуем апостериорное распределение с помощью распределения вероятности, вероятности переменной, которая нас интересует, при заданных нами данных. Этот процесс иллюстрируется на диаграмме ниже, где theta – это переменная, которая нас интересует, а data – результат событий, которые мы наблюдаем.

Байесовский процесс

Байесовский процесс на самом деле является циклическим, потому что мы повторяем этот процесс, начиная снова, но используя наши вновь полученные знания после наблюдения окружающего мира. Наше старое апостериорное распределение становится нашим новым априорным распределением, мы наблюдаем новые события и снова обновляем наше понимание, становясь “менее и менее неверными”, как это сказал Нэйт Сильвер в своей книге “Сигнал и шум”. Мы постоянно снижаем неопределенность относительно переменной, стремясь к состоянию уверенности (но мы никогда не можем быть уверены). Математически такое мышление описывается теоремой Байеса.

Теорема Байеса

Практически Bayes’ теорема быстро становится вычислительно неразрешимой для больших моделей в более высоких измерениях. Существует множество подходов для решения этой проблемы, но метод, который мы будем использовать сегодня, называется Markov Chain Monte Carlo, или MCMC. MCMC представляет собой класс алгоритмов (мы будем использовать один из них – Hamiltonian Monte Carlo), который интеллектуально извлекает выборки из вероятностного распределения. Эта статья не может подробно рассмотреть эту тему, но я предоставлю некоторые полезные ссылки в конце для дальнейшего чтения. На данный момент достаточно знать, что Bayes’ теорема слишком сложна для расчета, поэтому мы используем мощь продвинутых алгоритмов, таких как MCMC, чтобы помочь. Эта статья будет сосредоточена на использовании MCMC с помощью Pyro. Однако Pyro акцентирует внимание на использовании Стохастического Вариационного Введения (SVI), подхода на основе аппроксимации, который здесь не будет рассматриваться.

AB Тестирование с использованием Pyro

Представим себе компанию, которая разработала новую веб-страницу сайта и хочет понять, как это повлияет на конверсию, то есть, будут ли посетители продолжать сеанс на сайте после посадки на страницу? В тестовой группе А посетителям сайта будет показана текущая страница посадки. В тестовой группе В посетителям сайта будет показана новая страница посадки. В остальной части статьи я буду называть тестовую группу А контрольной группой, а группу В – лечебной группой. Бизнес сомневается в изменении и выбрал 80/20 распределение трафика сеансов. Общее количество посетителей и общее количество преобразований страниц для каждой тестовой группы подробно описаны ниже.

Test Observations

Нулевая гипотеза AB-теста заключается в том, что конверсия страницы не изменится для двух тестовых групп. В рамках частотного подхода это будет выражено следующим образом для двустороннего теста, где r_c и r_t – это радио конверсии страницы в контрольной и лечебной группах соответственно.

Null and Alternative Hypotheses

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

Давайте остановимся и опишем, что происходит во время нашего теста. Переменная, которая нас интересует, это радио конверсии страницы. Оно просто вычисляется путем взятия числа уникальных конвертированных посетителей и деления на общее количество посетителей. Событие, которое порождает это отношение, – это, будет ли посетитель нажимать на страницу. Здесь есть только два возможных результата для каждого посетителя: либо посетитель нажимает на страницу и конвертирует, либо нет. Некоторые из вас могут узнать, что для каждого уникального посетителя это пример испытания Бернулли; есть одно испытание и два возможных исхода. Теперь, когда мы собираем набор этих испытаний Бернулли, у нас есть биномиальное распределение. Когда случайная величина X имеет биномиальное распределение, мы даем ему следующее обозначение:

Binomial Distribution Notation

Где n – это количество посетителей (или количество испытаний Бернулли), а p – это вероятность события при каждом испытании. Здесь нас интересует p, мы хотим понять, какова вероятность, что посетитель будет конвертировать страницу в каждой тестовой группе. Мы наблюдали некоторые данные, но, как уже упоминалось в предыдущем разделе, сначала нам нужно определить нашу априорную вероятность. Как всегда в байесовой статистике, мы должны определить эту априорную вероятность в качестве вероятностного распределения. Как уже упоминалось ранее, такое вероятностное распределение является характеристикой нашей неопределенности. Бета-распределения часто используются для моделирования вероятностей, так как они определены в интервале от [0,1]. Более того, использование бета-распределения как нашего априорного для биномиальной функции правдоподобия дает нам полезное свойство – сопряженность, что означает, что наш постериорный будет сгенерирован из того же распределения, что и наш априорный. Мы говорим, что бета-распределение является сопряженным априорным. Бета-распределение определяется двумя параметрами – альфа и, запутанно, бета.

Обозначение бета-распределения

Имея доступ к историческим данным, мы можем определить обоснованный априорный прогноз. Нам не обязательно нужны исторические данные, мы можем использовать свою интуицию для формирования понимания, но пока предположим, что у нас нет ни того, ни другого (позже в этом руководстве мы будем использовать информированные априорные вероятности, но для демонстрации влияния начнем с неинформированных). Допустим, у нас нет понимания коэффициента конверсии на сайте компании, и поэтому мы определяем наш априорный прогноз как Beta(1,1). Это называется равномерным априорным распределением. График функции плотности вероятности этого распределения выглядит так же, как график равномерного распределения на интервале [0,1]. Определяя априорный прогноз Beta(1,1), мы утверждаем, что все возможные значения показателя конверсии страницы равновероятны.

Автор: Автор

Теперь у нас есть все необходимые данные – априорные прогнозы и данные. Давайте перейдем к коду. В данном коде будет представлен каркас для начала A/B-тестирования с использованием Pyro; поэтому будут опущены некоторые функции пакета. Чтобы оптимизировать код и полностью использовать возможности Pyro, рекомендуется обратиться к официальной документации.

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

import pyroimport pyro.distributions as distfrom pyro.infer import NUTS, MCMCimport torchfrom torch import tensorimport matplotlib.pyplot as pltimport seaborn as snsfrom functools import partialimport pandas as pdpyro.clear_param_store()

Модели в Pyro определяются как обычные функции Python. Это полезно, потому что это легко понять.

def model(beta_alpha, beta_beta):    def _model_(traffic: tensor, number_of_conversions: tensor):        # Определение случайных примитивов        prior_c = pyro.sample('prior_c', dist.Beta(beta_alpha, beta_beta))        prior_t = pyro.sample('prior_t', dist.Beta(beta_alpha, beta_beta))        priors = torch.stack([prior_c, prior_t])        # Определение наблюдаемых случайных примитивов        with pyro.plate('data'):            observations = pyro.sample('obs', dist.Binomial(traffic, priors),\                             obs = number_of_conversions)    return partial(_model_)

Важные моменты, которые нужно разобрать. Во-первых, у нас есть функция, обернутая внутри внешней функции, которая возвращает частичную функцию внутренней функции. Это позволяет нам изменять наши априорные прогнозы, не изменяя код. Я назвал переменные, определенные во внутренней функции, примитивами – думайте о примитивах как о переменных в модели. В модели у нас два типа примитивов – случайные и наблюдаемые случайные. В Pyro нам не нужно явно определять разницу между ними, мы просто добавляем аргумент obs к методу sample, когда это наблюдаемый примитив, и Pyro интерпретирует его соответствующим образом. Наблюдаемые примитивы находятся в контекстном менеджере pyro.plate(), что является хорошей практикой и делает наш код более читабельным. Наши случайные примитивы – это два априорных прогноза, характеризующиеся бета-распределением с параметрами альфа и бета, которые мы передаем из внешней функции. Как уже упоминалось, мы утверждаем нулевую гипотезу, определив их как равные. Затем мы объединяем эти два примитива с помощью tensor.stack(), который выполняет операцию аналогично конкатенации массива Numpy. Это вернет тензор – структуру данных, необходимую для вывода в Pyro. Мы определили нашу модель, теперь перейдем к этапу вывода.

Как уже было упомянуто, в данном руководстве будет использоваться MCMC. Функция ниже принимает модель, которую мы определили выше, и количество выборок, которые мы хотим использовать для генерации нашего апостериорного распределения. Мы также передаем наши данные в функцию, как мы сделали для модели.

def run_infernce(model, number_of_samples, traffic, number_of_conversions):    kernel = NUTS(model)    mcmc = MCMC(kernel, num_samples = number_of_samples, warmup_steps = 200)    mcmc.run(traffic, number_of_conversions)    return mcmc

Первая строка внутри этой функции определяет нашу ядро. Мы используем класс NUTS для определения нашего ядра, который расшифровывается как No-U-Turn Sampler, автонастраиваемая версия Hamiltonian Monte Carlo. Это говорит Pyro, как выбирать образцы из пространства апостериорной вероятности. Опять же, глубокое погружение в эту тему выходит за рамки данной статьи, но на данный момент достаточно знать, что NUTS позволяет умно выбирать образцы из пространства вероятностей. Затем ядро используется для инициализации класса MCMC на второй строке, указывая, что оно использует NUTS. Мы передаем аргумент number_of_samples в класс MCMC, который является количеством образцов, используемых для генерации апостериорного распределения. Мы присваиваем переменной mcmc инициализированный класс MCMC и вызываем метод run(), передавая наши данные в качестве параметров. Функция возвращает переменную mcmc.

Это все, что нам нужно; следующий код определяет наши данные и вызывает только что созданные функции с использованием априорного распределения Beta(1,1).

traffic = torch.tensor([5523., 1379.])conversions =torch.tensor([2926., 759.])inference = run_infernce(model(1,1), number_of_samples = 1000, \               traffic = traffic, number_of_conversions = conversions)

Первый элемент тензоров traffic и conversions – это количество для контрольной группы, а второй элемент в каждом тензоре – количество для группы испытуемых. Мы передаем функцию модели с параметрами для определения нашего априорного распределения, а также определенные нами тензоры. Запуск этого кода генерирует наши апостериорные образцы. Мы запускаем следующий код, чтобы извлечь апостериорные образцы и передать их в dataframe Pandas.

posterior_samples = inference.get_samples()posterior_samples_df = pd.DataFrame(posterior_samples)

Обратите внимание, что имена столбцов этого dataframe являются строками, которые мы передали при определении наших примитивов в функции модели. Каждая строка в нашем dataframe содержит образцы, полученные из апостериорного распределения, и каждый из этих образцов представляет собой оценку коэффициента конверсии страницы, вероятностное значение p, определяющее наше биномиальное распределение. Теперь, когда мы вернули образцы, мы можем построить наши апостериорные распределения.

Результаты

Полезный способ визуализации результатов AB-теста с двумя тестовыми группами – это совместная графиковая плотность ядра. Он позволяет визуализировать плотность образцов в пространстве вероятности по обеим распределениям. График ниже может быть построен на основе только что построенного нами dataframe.

Авторский кредит

Вероятностное пространство, изображенное на графике выше, можно разделить по диагонали, все, что находится выше линии, указывает на области, где оценка коэффициента конверсии выше в группе испытуемых, чем в контрольной группе, и наоборот. Как показано на графике, образцы, полученные из апостериорного распределения, плотно расположены в области, что указывает на более высокий коэффициент конверсии в группе испытуемых. Важно отметить, что апостериорное распределение для группы испытуемых шире, чем для контрольной группы, что отражает большую степень неопределенности. Это результат наблюдения за меньшим количеством данных в группе испытуемых. Тем не менее, график однозначно указывает, что группа испытуемых превосходит контрольную группу. Собирая массив образцов из апостериорного распределения и вычисляя их поэлементную разницу, можно сказать, что вероятность того, что группа испытуемых превосходит контрольную группу, составляет 90,4%. Эта цифра указывает, что 90,4% образцов, полученных из апостериорного распределения, будут находиться выше диагонали на совместном графике плотности.

Эти результаты были достигнуты с использованием плоского (непросвещенного) априорного распределения. Использование осведомленного априорного распределения может помочь улучшить модель, особенно когда доступ к наблюдаемым данным ограничен. Полезным упражнением будет исследование эффектов использования различных априорных распределений. На графике ниже показана функция плотности вероятности Beta(2,2) и совместный график, который она создает при повторном запуске модели. Мы видим, что использование априорного распределения Beta(2,2) дает очень похожее апостериорное распределение для обеих тестовых групп.

Авторский кредит

Образцы, полученные из апостериорного распределения, показывают, что с вероятностью 91,5% группа испытуемых работает лучше контроля. Поэтому мы с большей уверенностью можем утверждать, что группа испытуемых лучше контрольной, по сравнению с использованием плоского априорного распределения. Однако в этом примере разница незначительна.

Есть еще одна вещь, на которую я хотел бы обратить внимание в этих результатах. При проведении рассуждений мы сказали Pyro сгенерировать 1000 выборок из апостериорного распределения. Это произвольное число, выбрав другое число выборок, можно изменить результаты. Чтобы подчеркнуть эффект увеличения числа выборок, я провел АБ-тест, где наблюдения из контрольной и экспериментальной групп были одинаковыми, каждая с общей конверсией 50%. Использование априорного распределения Beta(2,2) порождает следующие апостериорные распределения, когда мы увеличиваем число выборок постепенно.

Автор: Автор

Когда мы проводим наше рассуждение всего с 10 выборками, апостериорное распределение для контрольной и экспериментальной групп относительно широкое и принимает разные формы. С увеличением числа выборок, распределения сходятся, в конечном итоге порождая практически идентичные распределения. Кроме того, мы наблюдаем два свойства статистических распределений: центральную предельную теорему и закон больших чисел. Центральная предельная теорема утверждает, что распределение выборочных средних сходится к нормальному распределению с увеличением числа выборок, и мы видим это на графике выше. Кроме того, закон больших чисел утверждает, что по мере роста размера выборки выборочное среднее сходится к среднему значению генеральной совокупности. Мы видим, что среднее значения в распределениях в правом нижнем углу примерно равно 0.5, что соответствует конверсионной ставке, наблюдаемой в каждой из тестовых выборок.

Бизнес-пример для байесовского АБ-тестирования

Байесовское АБ-тестирование может помочь повысить культуру тестирования и обучения в бизнесе. Байесовское статистическое вывода позволяет быстро обнаружить небольшие увеличения в тесте, так как оно не полагается на вероятности в долгосрочной перспективе для принятия выводов. Заключения из тестов могут быть получены быстрее, и тем самым скорость обучения увеличивается. Байесовское АБ-тестирование также позволяет раннюю остановку теста, если результаты, полученные путем “выглядывания” (peeking), указывают на то, что тестовые группы проявляют значительно более плохую производительность, чем контрольная группа. Таким образом, возможные затраты на тестирование могут быть существенно снижены. Это является главным преимуществом байесовского АБ-тестирования; результаты могут быть постоянно контролируемыми, и наши апостериорные распределения постоянно обновляются. Напротив, раннее обнаружение роста в тестируемых субъектах может помочь бизнесу внедрить изменения быстрее, сокращая латентность реализации изменений, способных увеличить выручку.Компании, взаимодействующие с клиентами, должны иметь возможность быстро внедрять и анализировать результаты тестирования, что облегчается байесовской АБ-тестированием.

Выводы

В этой статье мы ознакомились с основами байесовского подхода и исследовали результаты байесовского АБ-тестирования с использованием Pyro. Надеюсь, вы найдете эту статью информативной. Как упоминалось во введении, мы приветствуем и поддерживаем обратную связь. Как и обещали, ниже приведены ссылки на дополнительные материалы для чтения.

Рекомендуемые материалы

Следующие книги дадут хорошее представление о байесовском выводе:

  • The Signal and the Noise: The Art and Science of Prediction — Nate Silver
  • The Book of Why: The New Science of Cause and Effect — Judea Pearl and Dana Mackenzie. Хотя эта книга в основном фокусируется на причинности, глава 3 стоит прочитать о Байесе.
  • Bayesian Methods for Hackers: Probabilistic Programming and Bayesian Inference — Cameron Davidson-Pilon. Эта книга также доступна на Git, я привел ее ссылку ниже.

GitHub — CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers: aka “Bayesian…

aka “Bayesian Methods for Hackers”: Введение в байесовские методы + вероятностное программирование с…

github.com

Эти статьи VoAGI предоставляют подробные объяснения MCMC.

Monte Carlo Markov Chain (MCMC) объясняется

Методы MCMC – это семейство алгоритмов, которые используют марковские цепи для выполнения оценки Монте-Карло.

towardsdatascience.com

Байесовское статистическое выводение, MCMC и вариационный вывод

Обзор байесовской проблемы статистического вывода

towardsdatascience.com