В идеале мы всегда хотели бы запустить аккуратный A/B-тест: случайная рандомизация, чистое разделение трафика, прозрачное сравнение метрик. Но реальность часто ломает этот сценарий. Бывают ситуации, когда провести классический эксперимент невозможно — по этическим, организационным или техническим причинам.
В медицине, финансовых продуктах, страховании и ряде социально значимых сервисов рандомизация может быть просто неприемлемой. Вы не можете случайно «не дать» потенциально полезное лечение части пациентов только ради эксперимента, или случайно навесить повышенную комиссию на часть клиентов банка, чтобы проверить гипотезу про доходность.
Регуляторы, этические комитеты и репутационные риски часто делают RCT (randomized controlled trial) невозможным. В таких кейсах приходится опираться на наблюдательные данные и строить квази-эксперименты, которые пытаются приблизиться к силе A/B, но без рандомизации.
Классический пример: CEO влюбился в новый дизайн и решил выкатить его на всех сразу. Никаких holdout-групп, никаких «давайте подождём две недели». Или регулятор обязывает всех игроков рынка внедрить новую схему тарифов одновременно, без поэтапного теста.
В таких ситуациях вы узнаёте о запуске задним числом, уже после rollout-а. Формального контроля нет, но есть данные до и после изменения и, возможно, данные по похожим продуктам или регионам. Именно здесь появляются DiD, synthetic control и прочие методы.
Иногда фича настолько глубоко вмешивается в инфраструктуру, что разделить трафик просто нельзя. Например:
Технически возможен только «big bang»-запуск. При этом бизнес всё равно хочет понять эффект: стало лучше или хуже, насколько сильно.
Бывают ситуации, где экспериментировать формально можно, но единиц слишком мало для полноценной рандомизации. Например:
Делить такое N ещё и на тест/контроль часто бессмысленно: мощность станет нулевой. Тогда приходится работать с наблюдательными данными и «строить контроль» постфактум.
В продуктах с network effects (маркетплейсы, соцсети, мессенджеры) user-level рандомизация часто теряет смысл. Если вы включили новую механику только части пользователей, их поведение меняет окружение всех остальных: друзей, подписчиков, продавцов и покупателей.
В пределе вы получаете ситуацию, где почти каждый пользователь «смешан» с тестовыми и контрольными соседями, и интерпретация эффекта становится очень сложной. Иногда проще анализировать естественный rollout, чем пытаться соорудить идеальный A/B.
Ключевая мысль: квази-эксперименты — это не замена A/B, а план Б. Они дают более слабые каузальные утверждения, требуют дополнительных допущений и проверки устойчивости. Но в мире, где идеальный эксперимент часто невозможен, именно они позволяют сказать что-то осмысленное вместо «ничего не знаем».
Difference-in-Differences (DiD) — один из самых популярных квази-экспериментальных методов. Интуитивно он сравнивает изменение метрики во времени в группе, где произошло вмешательство, с изменением той же метрики в похожей группе, где ничего не меняли.
Представьте, что у вас есть две группы: treatment (Москва) и control (Санкт-Петербург). Меряем выручку до и после запуска новой цены доставки в Москве:
То есть мы берём приращение метрики в treated-группе и «вычитаем» естественное изменение в control-группе. Это естественное изменение служит оценкой того, что произошло бы в treated-группе без вмешательства.
Сердце DiD — предположение о параллельных трендах: если бы не было вмешательства, то обе группы продолжили бы двигаться примерно параллельно во времени. То есть gap между ними оставался бы примерно постоянным (или предсказуемым).
Если это допущение нарушено (например, Москва и так росла быстрее СПб до эксперимента), DiD будет путать естественный рост с эффектом фичи.
Практический шаг №1 в любом DiD — нарисовать график метрик по времени до вмешательства для treatment и control. Если кривые до момента изменения:
Полезная практика — прогнать «placebo DiD» с ложной датой вмешательства в pre-period. Если уже там вы «находите эффект», значит параллельных трендов нет.
Компания меняет схему цен на доставку только в Москве. В остальных городах тарификация прежняя. У вас есть помесячная выручка по городам за 6 месяцев до и 3 месяца после изменения.
Вы строите модель DiD: Москва = treatment, похожие крупные города (СПб, Екатеринбург, Казань) = control. Сравниваете изменение выручки в Москве с изменением в control-группе. Если в control-городах тренд остался прежним, а в Москве произошёл скачок — это сигнал в пользу эффекта новой схемы.
Важно также иметь достаточно длинный pre-period (часто 4–8 недель минимум), чтобы увидеть стабильный тренд, а не шум из пары точек.
Второй крупный класс методов — matching и reweighting. Идея проста: мы пытаемся сконструировать контрольную группу, максимально похожую на treated-пользователей по наблюдаемым характеристикам.
Пропенсити-скор (propensity score) — это вероятность попасть в treatment при заданных признаках пользователя: активности, устройстве, регионе, источнике трафика и т.д. Мы обучаем модель, которая предсказывает treatment-статус по этим признакам, и затем:
Интуиция: если два пользователя имеют одинаковый пропенсити-скор, но один получил treatment, а другой нет, то разница в их исходах ближе всего к «локальному эксперименту».
IPW (Inverse Probability Weighting) идёт другим путём: вместо того чтобы отбрасывать часть наблюдений, он перевзвешивает контроль так, чтобы его распределение признаков напоминало treatment-группу.
Наблюдения, которые «редки» среди контролей, но типичны для treated-пользователей, получают больший вес. В результате мы получаем «синтетическую контрольную группу», похожую на treatment по наблюдаемым факторам.
Все matching/reweighting-методы опираются на предположение, что все важные конфаундеры измерены. То есть, условно говоря, если два пользователя совпадают по всем учтённым признакам, вероятность treatment для них одинакова, и дальше разница только из-за фичи.
Если есть сильные неизмеренные факторы, влияющие и на treatment, и на исход (например, внутренняя мотивация, альфа-пользователь, скрытый сегмент), matching не спасёт — смещение останется.
Команда вручную включила премиум только пользователям с > 50 заказов. Теперь вы хотите оценить эффект премиума на удержание. Рандомизации нет, но есть полная история активности.
Вы можете подобрать для каждого treated-пользователя похожего не-treated по числу заказов, давности регистрации, устройству, региону, источнику трафика и другим pre-treatment признакам. Если matching удачный, распределения этих признаков в группах совпадут.
Synthetic control — метод для ситуаций, где у вас очень мало treated-единиц, иногда всего одна: одна страна, один регион, один склад. Вместо того чтобы делать DiD с «средним контролем», мы строим взвешенную комбинацию контролей, которая максимально точно воспроизводит поведение treated-единицы до вмешательства.
Пусть у нас есть Германия (treated) и множество других стран без изменения (доноры). Мы подбираем веса для этих стран так, чтобы их взвешенная комбинация:
Получаем «синтетическую Германию», которая служит контрфактуалом: что было бы, если бы фичу не запускали. После даты вмешательства сравниваем фактическую Германию с synthetic Germany.
Главный sanity check — насколько хорошо synthetic control повторяет treated-единицу до вмешательства. Если ошибка в pre-period большая, то мы не можем доверять постпериодным различиям: эффект в 5% при pre-period RMSE 15% мало что значит.
Regression Discontinuity Design (RDD) опирается на то, что treatment назначается по формальному порогу непрерывной переменной. Классический пример: пользователи с баллом > 100 получают премиум, с баллом ≤ 100 — нет.
Пользователи с баллами 99 и 101, скорее всего, очень похожи по всем характеристикам. Разница в пару баллов часто случайна. Если assignment строго следует правилу порога и никто им не манипулирует, то около cutoff-а мы получаем почти рандомизированное сравнение.
В обоих случаях мы оцениваем «скачок» метрики в окрестности порога, моделируя зависимость исхода от running variable слева и справа от cutoff-а.
Практически обязательно:
Interrupted Time Series (ITS) — самый простой квази-эксперимент: у вас есть длинный временной ряд метрики, и в какой-то момент вы вносите изменение (маркетинговая кампания, редизайн, миграция платформы). Вопрос: насколько изменилась траектория ряда относительно того, что можно было бы ожидать без вмешательства.
Мы строим модель, которая пытается описать поведение ряда до интервенции (тренд, сезонность, авторегрессии, влияние контрольных рядов), и затем экстраполируем её в постпериод. Разница между фактической траекторией и прогнозом = оценка эффекта.
Google CausalImpact — популярная реализация подхода через Bayesian Structural Time Series. Она:
Представьте, что 1 марта вы запускаете крупную маркетинговую кампанию и хотите оценить её влияние на DAU. У вас есть помесячный или подневный DAU за год до кампании и несколько контрольных рядов (например, DAU в странах, где кампанию не запускали).
CausalImpact строит модель по данным до 1 марта, предсказывает, каким был бы DAU в марте–апреле без кампании, и сравнивает с фактическими значениями. Если фактические DAU стабильно выше верхней границы доверительного интервала контрфактуала, это сигнал эффекта.
ITS особенно полезен, когда контрольной группы вообще нет (весь продукт поменяли одновременно), но есть длинная и относительно стабильная история метрики.
С квази-экспериментами легко «увидеть то, что хочется». Поэтому критически важно закладывать в анализ проверки, которые помогут отличить реальный эффект от артефакта модели или нарушения допущений.
Идея проста: примените ваш метод там, где вы знаете, что эффекта быть не должно. Если метод всё равно «находит» значимый uplift, он, скорее всего, ловит структуру шума или трендов, а не реальное влияние фичи.
Для DiD и synthetic control это обязательный шаг: до вмешательства кривые treated и control (или treated и synthetic) должны вести себя согласованно. Любой систематический разъезд до интервенции — красный флаг.
Хорошая практика — поиграть с настройками и проверить, насколько стабильна оценка:
Если эффект «исчезает» при небольшом изменении спецификации, доверять ему сложно.
Для matching и IPW полезны количественные оценки того, насколько сильным должен быть неизмеренный конфаундер, чтобы объяснить наблюдаемый эффект (подходы типа Rosenbaum bounds). Даже если вы не считаете их формально, важно в отчёте явно обсудить, какие скрытые факторы могут ломать каузальную интерпретацию.
Правило: квази-эксперименты дают суггестивные доказательства, а не железобетонные. В коммуникации с бизнесом всегда оставляйте место для сомнения: «результаты согласованы с гипотезой эффекта, но опираются на допущения X, Y, Z».
Сведём основные квази-экспериментальные методы в одну таблицу, чтобы вам было проще выбирать инструмент под задачу.
| Метод | Когда применять | Ключевое допущение | Главный риск |
|---|---|---|---|
| DiD | Два и более региона/группы, есть данные до и после вмешательства | Параллельные тренды: без treatment группы шли бы одинаково | Нарушение тренда из-за локальных шоков или плохого контроля |
| Matching | Выбор в treatment идёт по наблюдаемым характеристикам | Selection on observables: все важные конфаундеры измерены | Сильные скрытые факторы (unobserved confounders), смещающие оценку |
| Synthetic control | Одна treated-единица, много донорских контролей и длинный pre-period | Существует линейная комбинация доноров, хорошо описывающая pre-period | Мало доноров, плохой fit до интервенции, структурные сдвиги в постпериод |
| RDD | Treatment назначается по порогу непрерывной переменной | Отсутствие манипуляции около порога, локальная гладкость связи «метрика–running variable» | Манипуляция и бучинг у cutoff-а, мало наблюдений в окрестности порога |
| ITS / Causal Impact | Нет контрольной группы, но есть длинный временной ряд до интервенции | Модель временного ряда адекватно описывает контрфактуальное поведение | Одновременные события, плохое моделирование сезонности и внешних шоков |