Предсказание оттока — Churn Prediction для аналитика

Что такое Churn и зачем его предсказывать

Churn — отток пользователей, которые перестали пользоваться продуктом. Подробнее о разнице между Retention и Churn — в отдельной статье. Здесь фокус на предсказании: как заранее определить, кто уйдёт, чтобы успеть вмешаться.

Зачем это нужно:

  • Удержание дешевле привлечения. Привлечь нового пользователя стоит в 5–7 раз дороже, чем удержать существующего.
  • Таргетированные действия. Вместо скидки для всех — скидка для тех, кто вот-вот уйдёт. Экономия бюджета и точечный эффект.
  • Прогноз выручки. Если вы знаете, сколько пользователей уйдёт в следующем месяце, можете точнее планировать финансы.
  • Понимание причин. Модель показывает, какие факторы влияют на отток — это сигнал для продуктовых изменений.

На собеседованиях churn prediction — одна из самых популярных тем на стыке аналитики и ML. Спрашивают подход, выбор признаков, метрики и что делать с результатами.

Определение churned-пользователя

Перед построением модели нужно чётко определить, кого считать ушедшим. Это не так просто, как кажется.

Подписочные продукты: пользователь отменил подписку или не продлил. Чёткий сигнал.

Бесплатные продукты: пользователь не заходил N дней. Но какое N? 7 дней? 30? 90? Зависит от частоты использования продукта.

Подход: постройте распределение интервалов между сессиями. Если 90% пользователей возвращаются в течение 14 дней, то отсутствие 14+ дней — разумный порог.

-- Распределение интервалов между сессиями
WITH user_sessions AS (
    SELECT user_id,
           created_at,
           LAG(created_at) OVER (
               PARTITION BY user_id ORDER BY created_at
           ) AS prev_session
    FROM events
    WHERE event_name = 'session_start'
),
gaps AS (
    SELECT user_id,
           EXTRACT(DAY FROM created_at - prev_session) AS days_gap
    FROM user_sessions
    WHERE prev_session IS NOT NULL
)
SELECT days_gap,
       COUNT(*) AS frequency,
       ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) AS pct
FROM gaps
GROUP BY days_gap
ORDER BY days_gap;

Признаки для модели оттока

Качество модели на 80% определяется признаками (features). Вот категории, которые обычно работают.

Активность

  • Число сессий за последние 7/14/30 дней
  • Частота визитов (сессий в неделю)
  • Время в продукте за период
  • Число целевых действий (покупок, ответов, публикаций)
  • Тренд активности: растёт, стабильна, падает

Динамика

  • Изменение активности: сравнение последней недели с предыдущей
  • Дни с последнего визита (recency)
  • Максимальный gap между сессиями

Профиль пользователя

  • Время жизни (дней с регистрации)
  • Канал привлечения
  • Устройство / платформа
  • Был ли на онбординге
  • Подписка (тип, срок)

Вовлечённость

  • Число использованных фич
  • Глубина сессий (сколько экранов/действий за визит)
  • Использование ключевых фич (тех, что коррелируют с Retention)
  • Социальные взаимодействия (если есть)

Монетизация

  • Потратил ли деньги
  • Сумма покупок
  • Дней с последней покупки

Простой подход: правила (rules-based)

Не всегда нужна ML-модель. Для начала можно построить систему на правилах.

import pandas as pd

def churn_risk_score(user):
    """Простая скоринговая модель на правилах."""
    score = 0

    # Давно не заходил
    if user['days_since_last_visit'] > 14:
        score += 3
    elif user['days_since_last_visit'] > 7:
        score += 2
    elif user['days_since_last_visit'] > 3:
        score += 1

    # Активность падает
    if user['sessions_last_7d'] < user['sessions_prev_7d'] * 0.5:
        score += 2

    # Мало использует фичи
    if user['features_used'] < 3:
        score += 1

    # Никогда не платил
    if user['total_purchases'] == 0:
        score += 1

    return score  # 0-7: чем больше, тем выше риск

Плюсы: прозрачно, быстро внедрить, не нужен ML. Минусы: субъективные пороги, не учитывает взаимосвязи между факторами.

ML-подход

Когда данных достаточно, модель найдёт паттерны лучше ручных правил.

Подготовка данных

Задача — бинарная классификация: churned (1) vs active (0).

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# Формируем датасет
# Каждая строка — пользователь, таргет — churned (0/1)
df = pd.read_csv('user_features.csv')

features = [
    'days_since_last_visit', 'sessions_last_7d', 'sessions_last_30d',
    'activity_trend', 'features_used', 'session_depth_avg',
    'days_since_registration', 'total_purchases', 'is_premium'
]

X = df[features]
y = df['churned']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

Логистическая регрессия

Хороший baseline. Интерпретируемая, быстрая, устойчивая.

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, roc_auc_score

model_lr = LogisticRegression(random_state=42, class_weight='balanced')
model_lr.fit(X_train_scaled, y_train)

y_pred = model_lr.predict(X_test_scaled)
y_prob = model_lr.predict_proba(X_test_scaled)[:, 1]

print(classification_report(y_test, y_pred))
print(f"ROC AUC: {roc_auc_score(y_test, y_prob):.3f}")

class_weight='balanced' важен — обычно churned-пользователей меньше, чем активных, и модель без балансировки будет предсказывать «не уйдёт» для всех.

Random Forest

Ловит нелинейные зависимости, не требует масштабирования, показывает важность признаков.

from sklearn.ensemble import RandomForestClassifier

model_rf = RandomForestClassifier(
    n_estimators=200,
    max_depth=10,
    class_weight='balanced',
    random_state=42
)
model_rf.fit(X_train, y_train)

# Важность признаков
importance = pd.DataFrame({
    'feature': features,
    'importance': model_rf.feature_importances_
}).sort_values('importance', ascending=False)

print(importance)

Типичный топ-3 важных признаков: days_since_last_visit, activity_trend, sessions_last_7d. Если у вашей модели так — всё логично.

Метрики качества

Для churn prediction важны:

Метрика Что показывает Когда критична
ROC AUC Общая способность разделять классы Всегда (baseline метрика)
Precision Из предсказанных churned — сколько реально ушли Когда действие дорогое (звонок менеджера)
Recall Из реально ушедших — скольких поймали Когда потеря клиента дорога
F1 Баланс Precision и Recall Когда нужен компромисс

На практике чаще смотрят Precision@K: если вы можете позвонить 100 пользователям в день — какой процент из топ-100 по скору реально уйдёт?

Что делать с предсказаниями

Модель выдала вероятность оттока для каждого пользователя. Дальше:

1. Сегментируйте по риску.

  • Высокий (>0.7): агрессивные действия — персональное предложение, звонок
  • Средний (0.4–0.7): лёгкие nudge — пуш, email, скидка
  • Низкий (<0.4): ничего не делать (не тратить ресурсы)

2. Выберите действие. Зависит от продукта:

  • Скидка или бонус
  • Персональная рекомендация контента
  • Push-уведомление с ценным контентом
  • Звонок менеджера (для B2B)
  • Email-цепочка реактивации

3. Измерьте эффект. Запустите A/B-тест: группа с интервенцией vs. контрольная группа. Сравните churn rate. Без теста вы не узнаете, помогло ли действие или пользователи остались бы и без него.

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

Подводные камни

Утечка данных (data leakage). Если в признаках есть информация из будущего — модель будет идеально работать на тесте и бесполезна в продакшене. Пример: «пользователь удалил аккаунт» — это следствие churn, а не причина.

Дисбаланс классов. Если churned = 5% выборки, модель предскажет «не уйдёт» для всех и получит 95% accuracy. Используйте class_weight='balanced', oversampling (SMOTE) или оптимизируйте по AUC/F1.

Неправильный горизонт. Предсказывать churn через 30 дней на основе данных за 7 — рискованно. Чем дальше горизонт, тем ниже точность. Начните с 7–14 дней.

Подробнее о когортном анализе и линейной регрессии — в отдельных статьях.

Вопросы с собеседований

Как бы вы подошли к задаче предсказания оттока? — Определил бы churned-пользователя (порог неактивности). Собрал признаки: активность, динамика, профиль, монетизация. Начал с логрегрессии как baseline, потом попробовал Random Forest. Оценил по ROC AUC и Precision@K. По результатам — сегментация и A/B-тест интервенций.

Какие признаки самые важные для churn prediction? — Обычно: days since last visit (recency), тренд активности (падает/растёт), частота сессий за последние 7 дней. Это фичи, связанные с недавним поведением — они сильнее предсказывают отток, чем статичные характеристики типа канала привлечения.

Почему accuracy — плохая метрика для churn? — Из-за дисбаланса классов. Если ушли 5% пользователей, модель «никто не уйдёт» даёт 95% accuracy. Но она бесполезна. Нужны ROC AUC, Precision, Recall, F1.

Что такое data leakage и как его избежать? — Утечка — когда в признаках есть информация из будущего или напрямую связанная с таргетом. Избежать: строить признаки только из данных до момента предсказания, не включать следствия оттока (удаление аккаунта, отмена подписки) в фичи.

Как оценить бизнес-эффект модели? — A/B-тест: группе с высоким скором отправляем интервенцию, контрольной — нет. Сравниваем churn rate. Считаем ROI: сколько сохранили пользователей × LTV − стоимость интервенции.

FAQ

Нужен ли ML для предсказания оттока или хватит правил?

Зависит от масштаба. Для MVP или маленького продукта правила работают отлично: «не заходил 14 дней + активность падала» — уже полезный сигнал. ML оправдан, когда у вас тысячи пользователей, десятки признаков и нужна точная приоритизация.

Как часто переобучать модель?

Раз в квартал — хороший ритм. Чаще — если у продукта быстро меняется аудитория или функциональность. Обязательно мониторьте метрики модели в продакшене: если ROC AUC падает — пора переобучать.

Какую модель выбрать — логрегрессию или Random Forest?

Начните с логистической регрессии — она быстрее, интерпретируемее, и часто даёт сравнимое качество. Random Forest попробуйте вторым шагом — если он даёт значимый прирост AUC (>0.02–0.03), используйте его. Для собеседования важнее объяснить выбор, чем угадать «правильную» модель.


Потренируйте вопросы по предсказанию оттока на реальных задачах — откройте тренажёр. 1500+ вопросов, которые спрашивают на собеседованиях аналитика. Бесплатно.