Контрольная и экспериментальная группы в программном эксперименте: как сравнивать версии

Контрольная и экспериментальная группы в программном эксперименте: как сравнивать версии

Сравнить старую и новую версию программы можно по-разному. Самый очевидный вариант — сначала измерить систему, внести изменение, а затем повторить измерение. Но у такого подхода есть ограничение: между двумя замерами меняется не только код. Меняются нагрузка, пользователи, данные, соседние сервисы и другие внешние условия.

Контролируемый эксперимент решает задачу иначе. Вместо последовательности «до → после» две группы наблюдаются параллельно: контрольная группа получает исходный вариант, а экспериментальная — проверяемое изменение. Если распределение между группами организовано корректно, это помогает отделить эффект варианта от части изменений, происходящих просто со временем.

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

Что такое контрольная и экспериментальная группы

В типичном A/B-эксперименте существуют как минимум две вариации.

Группа Что получает Зачем нужна
Контрольная Исходную или выбранную базовую версию поведения Показывает, что происходило бы без проверяемого изменения
Экспериментальная Версию с проверяемым изменением Показывает состояние при наличии воздействия

Например, команда меняет алгоритм выбора результатов поиска внутри приложения.

Тогда контроль может продолжать использовать текущий алгоритм:

control → search_v1

а экспериментальная группа — новый:

treatment → search_v2

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

Это принципиально отличает параллельный контролируемый эксперимент от обычного сравнения двух последовательных состояний.

Почему «до и после» не равно control и treatment

Представим сервис, у которого в понедельник работала версия A, а во вторник появилась версия B.

После обновления среднее время выполнения операции изменилось.

Такой факт полезен, но сам по себе оставляет несколько объяснений:

  • изменилась версия приложения;
  • изменилась нагрузка;
  • пришёл другой состав пользователей;
  • обновилась зависимость;
  • изменились данные;
  • произошло инфраструктурное событие.

В параллельном эксперименте часть этих условий действует одновременно на обе группы.

один период наблюдения
        ↓
    аудитория
     ↙    ↘
control  treatment
   A         B

Это не уничтожает все альтернативные объяснения. Но дизайн становится сильнее, потому что сравнение уже не полностью привязано к двум разным моментам времени.

Другие факторы всё равно нужно учитывать отдельно. Для этого в существующем кластере есть материал о том, как изолировать изменение и работать с конфаундерами.

Сначала нужно выбрать единицу рандомизации

До разделения на две группы важно ответить на вопрос:

что именно будет получать только один вариант эксперимента?

Это и есть единица рандомизации.

Ею может быть:

  • пользователь;
  • аккаунт;
  • организация;
  • устройство;
  • сессия;
  • запрос;
  • другой объект, соответствующий архитектуре системы и проверяемой гипотезе.

Выбор зависит от поведения продукта.

Схема проверки A/B-эксперимента и выявления Sample Ratio Mismatch

Если проверяется новый интерфейс личного кабинета, естественной единицей часто становится пользователь.

Если несколько сотрудников одной компании работают с общим состоянием аккаунта, распределение отдельных сотрудников по разным версиям может создать странный результат: одна организация одновременно живёт в двух вариантах продукта. Тогда логичнее рассматривать организацию как единицу назначения.

Для некоторых низкоуровневых backend-проверок объектом распределения может стать запрос. Но такой вариант подходит только тогда, когда последовательные запросы одного пользователя действительно могут безопасно попадать в разные ветви.

Одна единица не должна незаметно прыгать между вариантами

После выбора единицы нужно обеспечить стабильное назначение.

Если пользователь сегодня попадает в control, через минуту в treatment, а затем снова в control, результаты начинают смешивать сразу несколько сценариев.

Особенно заметно это в интерфейсных и продуктовых экспериментах. Пользователь может:

  • увидеть две версии одного экрана;
  • начать процесс в варианте A и закончить в B;
  • получить состояние, созданное одной ветвью, а обработанное другой;
  • изменить своё поведение уже после знакомства с экспериментальным вариантом.

Поэтому experimentation-платформы обычно используют стабильное распределение: один идентификатор при одинаковой конфигурации эксперимента последовательно получает одну и ту же вариацию.

Feature flag часто используется как технический механизм такого переключения, но сам по себе флаг ещё не превращает rollout в эксперимент. Как устроено отделение развёртывания кода от включения поведения, отдельно разобрано в статье о feature flags.

Контроль и эксперимент не обязаны означать ровно 50/50

Для двух вариантов равное распределение часто удобно: при прочих равных оно эффективно использует доступную аудиторию для сравнения двух групп.

Но правило «A/B всегда означает 50/50» неверно.

Иногда treatment намеренно получает меньшую долю аудитории, например если:

  • новое поведение потенциально рискованнее;
  • эксперимент проводится на ограниченной части продукта;
  • есть операционные ограничения;
  • нужно оставить большую часть пользователей на текущей версии.

Важнее другое: ожидаемое распределение должно быть определено до запуска, а фактическое — проверяться после старта.

Иначе команда может анализировать эксперимент, в котором система распределяла аудиторию совсем не так, как предполагалось.

A/B-тест, A/A-тест, benchmark и canary — это разные процедуры

В инженерной практике несколько похожих механизмов легко смешать.

Подход Что сравнивается Главная задача
A/B experiment Контрольная и экспериментальная вариации Оценить различие при наличии проверяемого воздействия
A/A experiment Функционально одинаковые варианты Проверить распределение, сбор данных и работу экспериментальной системы
Benchmark Запуски программы в заданных условиях Получить воспроизводимое техническое сравнение
Canary deployment Стабильная и новая версии на разных долях трафика Ограничить масштаб риска во время rollout
Feature flag Разные ветви поведения приложения Управлять включением функциональности

Одни и те же технические механизмы могут участвовать сразу в нескольких сценариях.

Например, feature flag способен распределять пользователей между control и treatment. Но если команда просто включила новую функцию для 10% аудитории и наблюдает, не выросло ли число ошибок, это ещё не обязательно полноценный A/B-эксперимент.

Canary тоже использует несколько версий одновременно, однако его основная инженерная задача — безопаснее вводить изменение в production. Подробнее этот сценарий разобран в материале о canary deployment.

Benchmark, напротив, может вообще не использовать реальных пользователей. Там ключевыми становятся workload, окружение, прогрев и повторяемость процедуры. Для этого на сайте есть отдельный разбор воспроизводимого бенчмарка приложения.

Что должно быть сопоставимо между двумя группами

Control и treatment специально различаются проверяемым воздействием. Остальные различия желательно либо ограничивать, либо хотя бы делать видимыми.

Перед запуском полезно проверить несколько уровней.

Одна целевая аудитория

Нельзя незаметно отправить в control новых пользователей, а в treatment — только постоянных, а затем приписать различие версии продукта.

Если эксперимент проводится на сегменте, правила попадания в этот сегмент должны быть понятны до рандомизации.

Один период наблюдения

Параллельность — одно из преимуществ такого дизайна. Обе группы сталкиваются примерно с одним календарным контекстом, а не сравниваются через неделю или месяц.

Одинаковое определение метрик

Событие не должно означать одно в control и другое в treatment.

Если новая версия меняет сам способ отправки telemetry, сначала нужно проверить, что сравнение всё ещё измеряет один объект.

Одинаковая логика включения в анализ

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

Иначе часть аудитории может числиться в treatment, хотя экспериментальное поведение до неё фактически не дошло.

Особенно опасно смешивание вариантов

Представим корпоративный сервис.

Компания состоит из десяти сотрудников. Пять получают старую модель прав доступа, пять — новую. Но все десять работают с общими проектами и общей конфигурацией.

Формально эксперимент рандомизирован по пользователю.

Практически две вариации вмешиваются друг в друга через общий объект.

В таком сценарии стоит задать более фундаментальный вопрос: может быть, единицей эксперимента должна быть не отдельная учётная запись, а организация?

Похожая проблема возникает, если:

  • один пользователь входит с нескольких устройств под разными идентификаторами;
  • эксперимент меняет данные, которые затем видит control;
  • две версии одновременно изменяют общий кэш;
  • разные варианты взаимодействуют через очередь или shared state;
  • один и тот же объект попадает сразу в несколько пересекающихся экспериментов.

Это не означает, что эксперимент невозможен. Но схема «просто поделить пользователей пополам» уже недостаточна.

Sample Ratio Mismatch: когда группы распределились не так, как планировалось

Допустим, до запуска задано распределение:

control   50%
treatment 50%

После начала эксперимента оказывается, что наблюдаемая аудитория систематически распределена иначе.

Такое несоответствие называют Sample Ratio Mismatch, или SRM.

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

Причина может находиться в разных местах:

  • ошибка bucketing;
  • неверное targeting-правило;
  • разные условия попадания событий в аналитику;
  • ошибка идентификации пользователя;
  • одна версия чаще ломается до отправки события;
  • фильтрация данных удаляет группы несимметрично;
  • часть трафика проходит мимо экспериментального механизма.

SRM важен именно потому, что проблема может находиться не в статистическом анализе результатов, а гораздо раньше — в самой инфраструктуре эксперимента.

Поэтому при неожиданном распределении сначала стоит разобраться с assignment и данными, а не объяснять различие продуктовым эффектом.

Схема проверки A/B-эксперимента и выявления Sample Ratio Mismatch

A/A-тест помогает проверить систему до настоящего воздействия

В A/A-тесте участники также распределяются между двумя или несколькими вариациями, но фактическое поведение этих вариаций делают одинаковым.

Например:

control   → search_v1
variant B → search_v1

Такой запуск не отвечает на вопрос, лучше ли новая функция. Новой функции здесь вообще нет.

Зато он способен обнаружить проблемы инфраструктуры:

  • неожиданное распределение аудитории;
  • несогласованность метрик;
  • нестабильное назначение варианта;
  • ошибку аналитического пайплайна;
  • систематическое различие там, где вариации должны быть одинаковыми.

A/A — не обязательный ритуал перед каждым экспериментом. Это диагностический инструмент, полезный тогда, когда нужно проверить сам механизм experimentation.

Наблюдаемость нужно подготовить до запуска групп

Даже идеально распределённый эксперимент мало поможет, если после запуска невозможно понять, какой вариант получил конкретный объект и что происходило с системой.

Минимально полезно сохранять:

  • идентификатор эксперимента;
  • версию конфигурации эксперимента;
  • единицу рандомизации;
  • назначенную вариацию;
  • момент фактического exposure;
  • существенные события и ошибки;
  • определённые до запуска показатели.

Общая задача telemetry уже разобрана отдельно в статье о логах, метриках и трассировках перед экспериментом.

Здесь важно только одно: контрольная группа бесполезна, если после эксперимента невозможно надёжно установить, кто действительно находился в control, а кто получил treatment.

Простой порядок подготовки control/treatment эксперимента

  1. Сформулировать проверяемое изменение. Не «новая версия лучше», а конкретно указать, что отличается между вариантами.
  2. Определить аудиторию. Кто вообще может попасть в эксперимент.
  3. Выбрать единицу рандомизации. Пользователь, организация, устройство, запрос или другой объект.
  4. Определить control. Какая вариация является базовой для сравнения.
  5. Определить treatment. Какое поведение получает экспериментальная группа.
  6. Задать распределение. Зафиксировать ожидаемые доли до запуска.
  7. Обеспечить стабильный assignment. Одна единица не должна случайно менять вариант во время эксперимента.
  8. Проверить воздействие. Убедиться, что назначенная вариация действительно была получена.
  9. Проверить telemetry. События и определения показателей должны быть сопоставимы.
  10. После запуска проверить здоровье эксперимента. В том числе фактическое распределение групп и признаки SRM.

Статистический анализ результата начинается уже после того, как эта техническая основа признана пригодной для сравнения.

Контрольная группа не доказывает причинность автоматически

Фраза «у нас был control» иногда создаёт ложное чувство завершённости.

Но наличие двух колонок A и B ничего не гарантирует, если:

  • распределение было систематически смещено;
  • единицы переходили между вариантами;
  • группы получали разный внешний контекст;
  • экспериментальное воздействие дошло не до всех назначенных участников;
  • метрики считались по-разному;
  • варианты взаимодействовали друг с другом;
  • одновременно происходили другие изменения, способные объяснить результат.

Корректнее считать control/treatment дизайн одним из инструментов уменьшения неопределённости.

Он усиливает причинную интерпретацию, когда распределение, воздействие, измерение и анализ действительно соответствуют дизайну эксперимента. Если эти условия нарушены, само название «A/B-тест» не исправит данные.

Типичные ошибки при сравнении двух версий

Ошибка Почему мешает
Сравнить неделю A с неделей B и назвать это A/B-тестом Версия смешивается с изменением времени и внешних условий
Рандомизировать по пользователю, хотя поведение общее для организации Control и treatment начинают взаимодействовать через shared state
Позволить одному пользователю получать разные варианты Смешивается фактическое воздействие
Изменить правила аудитории после запуска Меняется сама популяция эксперимента
Игнорировать неожиданное соотношение групп Можно анализировать поломку assignment как продуктовый эффект
Считать feature flag доказательством наличия эксперимента Флаг управляет поведением, но не заменяет экспериментальный дизайн
Считать canary обычным A/B-тестом Безопасный rollout и причинное сравнение решают разные задачи

Итог

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

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

Поэтому до запуска важно определить:

  • кто участвует;
  • что является единицей рандомизации;
  • какая вариация считается control;
  • какая является treatment;
  • как фиксируется назначение;
  • как подтверждается фактическое воздействие;
  • какое распределение ожидалось;
  • не смешиваются ли варианты между собой.

Хороший control нужен не для красивой схемы A/B. Он нужен, чтобы у изменения появился осмысленный параллельный контекст для сравнения.

Источники

Источники проверены 4 сентября 2026 года.