Привет, Хабр! Меня зовут Федор Тюрин, я руководитель команды продуктовой аналитики в Учи.ру. Мы проводим очень много А/Б-тестов (десятки запусков в неделю и сотни в течение года). В таких условиях очень важна автоматизация процесса анализа и подведения итогов теста.
В нашей компании была платформа для анализа А/Б-тестов (А/Б-тестер), который со временем перестал справляться с объемом и сложностью запросов. Это осложняло анализ данных: добавление нового функционала и метрик занимало очень много времени и порождало костыли в коде, платформа не умела учитывать сетевые эффекты, команда аналитиков тратила много времени на ручной анализ тестов. Чтобы решить эти проблемы и улучшить методологию А/Б-тестирования, мы решили создать новую платформу для А/Б-тестов. Рассказываю, как мы это сделали.
Проблемы старого А/Б-тестера
Старая платформа для анализа тестов появилась, когда Учи.ру была небольшой компанией. Это был весьма простой скрипт, который в моменте закрывал основные потребности в анализе тестов. C ростом компании появилось много команд, которым требовалось одновременно запускать тесты и анализировать их. Это привело к тому, что старая платформа постепенно перестала отвечать нашим запросам и аналитика становилась фрагментированной. Почему так произошло?
Проблема 1. У каждой продуктовой команды свой подход к аналитике
Разные команды, запуская А/Б-тесты, использовали свой подход к их подсчетам и интерпретации. Они самостоятельно определяли метрики, на основе которых принималось решение об успешности или не успешности теста, и сами критерии этой успешности.
Из-за этого мы получали фрагментированную аналитику. В ней было сложно разобраться сотруднику, который не принимал участия при запуске одного из множества А/Б-тестов в другой команде. Например, новый аналитик вряд ли бы понял, какой подход к анализу данных использовался при анализе старых А/Б-тестов.
Проблема 2. Проблемы с масштабируемостью
Добавить что-то новое в код платформы— например, кастомную функцию — было сложно. Приходилось делать «костыли», которые со временем стало тяжело поддерживать. Тогда команды начали писать собственные А/Б-тестеры — как правило, не всегда хорошие и понятные. Это только увеличивало количество плохих инструментов. А нам важно было прийти к централизованной аналитике.
Проблема 3. Не учитывались сетевые эффекты
А/В-тест можно считать валидным, если для него выполняется «stable unit treatment value assumption (SUTVA)». Это предположение о том, что отклик пользователя зависит только от изменений, которые были направлены именно на него, а не от изменений, направленных на пользователей вокруг него.
На Учи.ру школьники занимаются вместе со своими одноклассниками. Некоторые механики мы тестируем для всего класса (например, соревнования), а внутри класса поведение одного ребенка зависит от поведения других детей. При этом, нам все еще интересны метрики на уровне ученика (конверсия, среднее время на платформе и т.д.)
Поэтому в тестировании рандомизация на уровне ученика нам не подходила, а по классам, где процент влияния других факторов сведен к минимуму, требовалось внедрение более сложных подсчетов статистической значимости, которые трудно было интегрировать в платформу.
Проблема 4. Нельзя быстро посчитать кумулятивные метрики
Считать кумулятивные метрики на каждый день эксперимента – вычислительно сложная задача, которая средствами стандартных баз данных (Postgres) легко не решается, а в Python подобные вычисления с помощью циклов занимают много времени. Но отказываться от кумулятивных метрик нам не хотелось, как и не хотелось тратить кучу времени на их расчеты.
Проблема 5. Продакты использовали платформу для подтверждения своих гипотез
Многие продакты подвержены так называемой предвзятости подтверждения (confirmation bias) – предвзятому поиску подтверждения своих гипотез, ведь они как никто иной заинтересованы в их успехе. Существовавшая платформа для анализа тестов никак не ограничивала такое поведение, из-за чего некоторые тесты закрывались с некорректными выводами.
Продолжать работать с платформой в таком виде дальше было нельзя, поэтому мы стали искать решение, которое нас полностью устроит.
Решение — сделали новую платформу на ClickHouse
ClickHouse — это колоночная система управления базами данных для онлайн-обработки аналитических запросов. На ее основе мы сделали кастомизированную А/Б-платформу. Поскольку мы стремились к автоматизации, ускорению и изменению методологии в процессе анализа тестов, использование ClickHouse стало для нас неоспоримым решением.
Главные плюсы:
Скорость. База данных позволяет проводить практически любые расчеты внутри ее, не прибегая к использованию Python.
Колоночно-ориентированная база. Колоночная архитектура намного лучше подходит для работы с тяжелыми аналитическими запросами. Более того, при работе с широкими таблицами, используются только те колонки, которые явно указаны в запросе, а не вся таблица, что также преимущество, когда метрик много, а для каждого конкретного кейса нужна только подвыборка из них.
Богатый функционал, сильно выходящий за рамки стандартного диалекта SQL. Например, ClickHouse позволяет хранить промежуточные состояния агрегирующих функций без финализации результатов, чтобы потом их можно было использовать в дальнейших расчетах. Очень полезными также оказались модификаторы агрегирующих функций, функционал для работы с массивами и внешние словари.
Архитектура платформы
Сначала пользователь попадает в user interface, где задает параметры для расчета теста. Сюда входит выбор метрик, фильтрация сегментов и установка уровня значимости.
Далее эти параметры попадают в бэкенд на Python, где генерируется один большой SQL-запрос, который выгружает все нужные данные. На этапе сборки запроса происходит большая работа с метриками: зная метрику, мы можем определить, какой статистический критерий применить для расчета значимости. Зная этот критерий — становится понятным, что должен отдать запрос.
Потом запрос отправляется в ClickHouse. Там происходят самые тяжелые расчеты, так как их перенос в Python приводит к серьезной деградации скорости системы. Запрос всегда обращается к одной широкой таблице с данными по метрикам, это нужно, чтобы добавление новых метрик не влекло за собой смысловое изменение запроса (добавление новых подзапросов, джойнов и т.д.). Все нужные фильтры и сегменты подтягиваются из закэшированных внешних словарей.
Результат запроса — это компактная таблица на уровне группы теста — которая обратно возвращается в бэкенд на Python, где происходит финализация полученных данных. То есть именно в ClickHouse происходит радикальное уменьшение размерности — от сотен миллионов строк сырых ивентов до десятков строк агрегированных результатов.
И, наконец, полученные данные обратно отдаются в user interface, где происходит отображение результатов.
Как принимаем решения на основе данных
До запуска А/Б определяем срок теста. Для этого используем самописный калькулятор для расчета MDE — минимального детектируемого эффекта. На практике же, мы наблюдаем за стабильностью эффекта: для этого мы мониторим три графика — кумулятивное значение метрики, uplift во времени и кумулятивное p-value.
Мы хотим увидеть график p-value, который пробил уровень значимости и там закрепился, чтобы исключить ошибку из-за разовых прокрасов. Ниже примеры А/Б тестов, которые мы считаем значимыми и не значимыми.
Как платформа помогает продакт-менеджерам прийти к верному решению
Наша ключевая идея — не навязывать, а подталкивать пользователей А/Б-платформы к более корректному принятию решений и интерпретации статистики. Для этого мы добавили несколько хаков:
по-умолчанию для А/Б-теста не выбрана ни одна метрика — их нужно вручную накликивать из списка. Таким образом, мы побуждаем продактов задумываться о том, какие метрики им интересны, а не считать результаты по всем доступным (так как это увеличивает вероятность ошибки первого рода);
при выборе нескольких групп, нескольких метрик или нескольких сегментов, платформа автоматически применяет поправку на множественное тестирование, тем самым контролируя приемлемую вероятность ошибки первого рода;
дополнительно мы показываем долю А/Б-теста в общей выручке. Это позволяет в определенных моментах корректировать большой uplift, полученный на маленьком сегменте и в итоге слабо влияющим на общие показатели компании.
Вывод и оставшиеся задачи
Мы построили удобную платформу для А/Б-тестов, которая улучшила процесс анализа тестов для продуктовых и аналитических команд. Нам не приходится писать большой код, чтобы провести сложные расчеты и получить значения кумулятивных метрик. Мы видим объективную картину по итогам А/Б-теста: при расчетах учитываются сетевые эффекты, а финальный результат зависит от нескольких показателей. Но самое главное — мы повысили уровень аналитической культуры команд, так как подталкиваем их самостоятельно принимать верные решения.
Какие челленджи нам еще осталось решить?
Дельта-метод (как и линеаризация) на симуляциях показывают весьма низкую мощность в сравнении с бутстрапом. Последний для нас неприемлем из-за вычислительной сложности, поэтому мы ищем способы улучшить текущие методы.
Есть желание сократить время расчетов больших и средних А/Б-тестов, приблизив к моментальному получению результата — сейчас средний тест считается примерно 2–3 минуты.
Хотим сделать текущее хранилище метрик полноценной библиотекой метрик, где помимо технической информации о метриках будет расширенное описание для команд: определения всех метрик, их сильные и слабые стороны, формулы расчетов.
Если ты разделяешь наш подход к аналитике, присоединяйся, чтобы вместе с нами развивать школьный EdTech.
Какие технические решения используете вы для проведения А/Б-тестов? Делитесь в комментариях.
uchitel
Если честно, создается очень странное впечатление. Например, почему вы не используете последовательный анализ если хотите быть быстрее? Ну или быть точнее в оценках при той же скорости? Как будто критерий Вальда до сих пор засекречен.