В этой статье я хотел немного написать про наш опыт A/B-тестирования на нашем проекте и немного о том, какое отношение математическая статистика имеет к A/B-тестированию, а также послушать опыт других коллег из продуктовых компаний.
Сперва небольшой пролог про нашу компанию и чем мы занимаемся: я — CTO Jiji, Николай Зорин. До основания компании я работал в ряде других проектов и потратил на электронную коммерцию более 10 лет жизни. Проект Jiji мы запустили с нуля 2,5 года назад. Первая наша команда состояла из
Самый частый вопрос, который мне задают на собеседовании: почему Нигерия? Мы проверяли: у людей есть ассоциации с джунглями, каннибализмом и жарким климатом. Но страна очень большая — 200 млн человек населения, ВВП очень быстро растет, количество интернет-пользователей больше, чем население Украины, а развитие всех интернет-ресурсов находится на уровне Украины
Это практически единственный крупный рынок в мире, где можно точно предугадать, каким будет интернет через 5, 10 и 15 лет. Для Генезисарынок Нигерии стратегически важен — это один из немногих рынков в мире, где все еще только начинается и можно поучаствовать в развитии сверхбыстроменяющейся индустрии для десятков миллионов человек.
На текущий момент мы построили уже довольно интересную историю, хотя работы впереди еще очень много. У нас
Как в любом продукте, у нас есть огромное количество самых разнообразных идей, которые можно тестировать и пробовать. Эти идеи следуют и из нашего (в основном, украинского) опыта электронной коммерции, и из анализа конкурентов — больше всего, мы смотрим на Индию. В голову постоянно приходят идеи невероятных улучшений, многие из которых не проходят первой критики или откладываются до лучших времен из-за недостатка ресурсов.
Но некоторые идеи попадают в спринт и воплощаются в жизнь.
Как мы пришли к идее A/B-тестов
Первые улучшения всегда давали нам очень значимые приросты (+20%), и мы видели и радовались, что изменения приносят пользу сайту и радость пользователям. Но со временем масштаб приростов сильно снижается, и одним из самых важных вопросов становится: как же оценить новое «улучшение»? Действительно ли это улучшение или лишь флуктуация, которая может в действительности огорчить пользователей и ухудшить показатели бизнеса?
Ниже — небольшая ретроспектива развития процесса апрува новой фичи в нашей команде.
1. «Стартап мода» — первые полгода
В самом начале развития проекта новые фичи принимались в том случае, если они нравились команде и работали без видимых ошибок. Мы не очень смотрели на конверсии — в целом они и так росли, все изменения на старте приводят к значимой обратной связи. Может быть, именно в этом вся прелесть стартапов — большинство вещей, которые ты делаешь, имеют сильную позитивную обратную связь.
Как только аудитория сайта начала расти, влияние каждой фичи упало, и пришло понимание, что новые фичи нужно оценивать с точки зрения бизнеса.
Тогда мы немного изменили наш подход:
2. «Сравнение с прошлой неделей»
После выкатки новой фичи, конверсии по ней за 3 дня сравнивались с конверсиями за те же дни на прошлой неделе. И фича одобрялась лишь в случае, если она не снижает (лучше, конечно, повышает) конверсии.
Немного спустя стало понятно, что показатели конверсий — штука нестабильная и может сильно колебаться в зависимости от национальных праздников, количества и источников привлекаемых пользователей и многих других факторов. На этом этапе мы внедрили:
3. Flag toggles, с чего и началось наше A/B-тестирование
Flag toggles — флаги которые позволяют включать функционал для определенной части аудитории. Это позволило нам избежать влияния колебаний трафика между разными днями и получить более ясное влияние фич: старая и новая версия тестируются одновременно, в одинаковых условиях.
Кроме проведения A/B-тестов, флаги можно использовать для временного включения функционала для определенных пользователей, например для админов или тестировщиков.
Также важно убедиться, что наши флаги делят аудиторию так, как мы ожидаем, то есть нет статистически значимых изменений конверсий в двух разных аудиториях, использующих один и тот же функционал (так называемый А/А-тест).
Первые шаги
Сперва наш процесс выглядел примерно так:
1. Делим аудиторию пополам.
2. Одна половина юзеров видит старую версию сайта, другая — новую.
3. Отправляем данные в GA.
4. Ждем, пока новая фича победит старую или безнадежно проиграет, и заканчиваем тест.
Такая версия A/B-теста применялась некоторое время и показывала хорошие результаты, до тех пор пока наша аудитория не была очень большой, а средний показатель улучшений конверсий новой фичей составлял
Но время шло, аудитория росла, и улучшения от новой фичи по конверсиям стали составлять
Мы осознали две проблемы:
— не ясно, как определить, реально ли создается улучшение на 1% или это лишь временные колебания;
— после того, как количество событий в GA перевалило за 500 тысяч, бесплатная версия GA стала делать семплирование, что со статистической точки зрения абсолютно скомпрометировало ее показатели для A/B-тестов.
Нужно было вспоминать статистику и решать что-то с хранилищем для результатов A/B-тестов. Проблема с хранилищем доставила нам меньше всего хлопот — мы использовали кластер elasticsearch, а хранение событий типа просмотров страниц и конверсий мало чем отличается от хранения логов. Поэтому мы естественным образом пришли к использованию elasticsearch.
Учитывая особенности elasticsearch, а именно его искривленное понимание операций удаления (link), сразу стоит создавать отдельный индекс под каждый месяц (pageview-YYYY-MM): только в этом случае получится безболезненно удалять старые данные.
Из курса статистики вспоминается доверительный интервал (link), который получает на вход конверсию и размер выборки, на которой проводился тест, и может сказать с заданной вероятностью, например 95%, что реальная конверсия лежит в некотором интервале.
Пример 1:мы провели тест, и в группу А попало 1,000 пользователей, 200 из них совершили конверсию. Итого фактическая конверсия — 20%. Если мы посчитаем доверительный интервал, то получим, что с вероятностью 95% реальная конверсия лежит в интервале от 17,52% до 22,48%.
Пример 2:в выборке Б у нас было 995 пользователей, и 230 из них совершили конверсию. Фактическая конверсия получается 23,1%, а реальная с вероятностью 95% лежит в пределах от 20,48% до 25,72%
Как мы видим, эти интервалы пересекаются, а значит, хотя фактически конверсия в группе Б выше на 15,5%, в действительности она может оказаться хуже, чем в выборке А.
Также стоит понимать, что хотя мы и берем точность доверительного интервала 95%, эксперимент может утверждать, что результаты одной выборки лучше, чем другой, с уверенностью .95 * .95, то есть 90,25%, так как погрешность может дать каждый из
Погрешности метода
Вооружившись новым хранилищем данных и чудо-инструментом подсчета доверительного интервала, мы вступили в новый поединок с A/B-тестами.
Приняв новым методом N-ое количество фич (и отклонив еще большее!), мы вдруг осознали, что этот подход довольно уязвим перед продакт-менеджерами, у которых есть KPI и которым нужно, чтобы новая фича «улучшила» показатели сайта.
Загвоздка крылась в самом определении доверительного интервала, которое грубо звучит так: с вероятностью X реальное значение конверсии лежит в пределах [a;b], из этого следует, что с вероятностью до
Если брать пример выше, то имея доверительный интервал 95% (а вероятность ошибки данного метода до (100 — 90,25) = 9,75%), мы получаем, что при каждом измерении результатов A/B-теста мы с вероятностью до 9,75% можем получить false positive вердикт, то есть принять фичу, которая не принесла улучшений или, наоборот, все ухудшила.
Допустим, мы можем увеличить точность доверительного интервала до 97,5%, чтобы получить погрешность метода не более 5%, и смириться с такой погрешностью.
Но это только на первый взгляд...
Рассмотрим следующий случай. Допустим, мы проводим A/B-тест в течении
Таким образом, только 2 фичи принесли реальные улучшения.
Но будь вы продакт-менеджером, у которого есть вагон тасок и которому нужно быстро принимать решении по таскам, будете ли вы ждать еще сутки, если уже на первый день доверительный интервал говорит, что изменения уже существенны с вероятностью 95%?
Рассмотрим действия нетерпеливого продакта:
Третий сценарий в первый день показался нам положительным. Хотя он и был замерен на малой выборке, но показал значительные улучшения в конверсиях — возможно, из-за каких-то отклонений
В результате мы ошибочно решили, что третий сценарий дает нам некое улучшение.
Таким образом, реальная вероятность ошибки уже выше заявленных 5%, и больше шансов ошибочно принять фичу, которая ухудшит конверсии.
Масштаб проблемы
Насколько же большая эта проблема? Например, чтобы получить реальную вероятность ошибки не выше 5%, если мы проверяем эксперимент 10 раз, нам нужно, чтобы вероятность ошибки каждого измерения была не выше 1%.
Таким образом, чем чаще продакты заглядывают в результаты тестирования, тем выше вероятность принять плохую фичу.
Объяснить им это — отдельная проблема, ведь довольно тяжело заставить людей понимать то, от незнания чего зависят их результаты.
Тут нужно было что-то решать. Понятно, что еще до начала эксперимента нужно как-то определить размер выборки, который будет репрезентативным, но как это сделать? На помощь пришел подход из статистики, который называется: two independent proportions power analysis.
Решение
Суть этого подхода заключается в том, что до начала эксперимента мы должны измерить текущую конверсию, сделать предположение о том, насколько наша фича может изменить конверсию, задать максимально приемлемую вероятность false positive и false negative. В результате мы получим размер выборки, на которой мы с заданной точностью можем принять решение.
Допустим, текущая конверсия составляет 20%. Мы предполагаем, что новая фича улучшит конверсию на 1%, тогда новая конверсия составит 20,2%. Мы можем принять вероятность ошибочного принятия фичи не более 5% и хотим быть на 80% уверены, что мы не приняли реальное улучшение за флуктуацию. Тогда размер выборки на каждой из групп будет составлять 630260.
Следовательно, нам нужно запустить A/B-тест, подождать, пока мы получим 630к сессий в каждой выборке, и если после этого конверсия в группе Б будет не менее чем на 1% выше конверсии в группе А, то мы можем считать эксперимент успешным.
Этот подход позволил нам решить проблему с повышением ошибки при повторных проверках при A/B-тесте. Также мы можем сделать более точные прогнозы по длительности A/B-тестов. Главное — мы избежали принятия фич, которые на коротком промежутке времени дают неоправданно высокий прирост в конверсиях.
Куда мы планируем развиваться
Через некоторое время данных о конверсиях у нас стало уже более чем достаточно, и мы могли использовать эти данные, чтобы провести байесово А/B-тестирование.
Исходя из имеющихся данных, можно построить функцию распределения вероятности (бета-распределение) для версии А. Получая новые данные и обновляя имеющееся распределение, мы получаем новое распределение.
Чем байесово тестирование лучше? Мы получаем распределение вероятностей, а не просто оценку достоверности. Наличие априорной функции распределения позволяет проводить повторные тесты и быстрее принимать решения при низком базовом уровне конверсий.
Elasticsearch как бэкэнд для событий — хорошо, но со временем потребности могут вырасти. Например, делать выборки с join в эластике — проблематично. В планах — попробовать Clickhouse — «столбцовая СУБД для OLAP», как называет её Яндекс. Из обещанного — линейная масштабируемость, очень быстрые запросы, статистические функции, бесплатность.
Выводы
A/B-тест — достаточно простой инструмент, но, в то же время, требующий понимания базовых статистических инструментов. Без аккуратного проведения он может привести к существенным затратам ресурсов на развитие бесполезного функционала или даже к снижению конверсий по сайту.
Буду рад ответить на вопросы в комментариях, а также приведу список интересной для меня литературы:
— Most winning A/B test results are illusory;
— Bayesian A/B Test Calculator;
— Elasticsearch for Analytics;
— A/B Testing Tech Note: determining sample size;
— Feature Toggles;
— How Not To Run An A/B Test;
— Bayesian A/B campaign testing (and design);
— ClickHouse;
— Inference for Proportions: Comparing Two Independent Samples.