Представьте. У вас SaaS продукт. Подписка 1000 рублей в месяц. В январе зарегистрировалось 100 новых пользователей. Вы думаете: отлично, +100 000 рублей в месяц!
Реальность: через месяц 40 пользователей ушли. Через два месяца ещё 20. Через три ещё 15. К концу года из 100 пользователей осталось 10.
Ваш реальный доход с этой когорты: не 1 200 000 рублей (100 пользователей × 12 месяцев × 1000₽), а примерно 350 000 рублей. Разница в 3.5 раза.
А что если бы вы знали заранее кто из 100 пользователей уйдёт? Что если бы могли предсказать что пользователь А принесёт 50 000 рублей за lifetime, а пользователь Б только 3 000?
Вы бы могли:
Вовремя спасти пользователя от ухода (персональное предложение, помощь)
Тратить маркетинговый бюджет правильно (платить за привлечение пользователя А до 40 000₽, а за пользователя Б не больше 2 000₽)
Приоритизировать фичи (делать то что удерживает высокоценных пользователей)
Это и есть предиктивная аналитика. Прогнозирование будущего поведения пользователей на основе данных.
Две ключевые метрики:
Churn (отток) - вероятность что пользователь уйдёт
LTV (Lifetime Value) - сколько денег принесёт пользователь за всё время
По данным исследований, снижение churn всего на 5% может увеличить прибыль на 25-95%. Компании которые эффективно используют LTV для сегментации увеличивают продажи на 81%.
В этой статье разбираемся как строить простые модели предсказания churn и LTV. Без сложной математики. С примерами кода на Python. Пошагово. Для начинающих.
1. Что такое churn и почему его нужно предсказывать
Определение churn (оттока)
Churn это когда клиент перестаёт пользоваться вашим продуктом. Существует два вида:
1. Voluntary churn (добровольный отток)
Пользователь сам решил уйти. Отменил подписку. Удалил приложение. Перестал заходить.
Причины:
Продукт не решает проблему
Нашёл лучшую альтернативу
Слишком дорого
Плохой UX
Не понял как пользоваться
2. Involuntary churn (вынужденный отток)
Платёж не прошёл. Карта заблокирована. Технические проблемы.
Обычно легче предотвратить чем voluntary churn (просто нужно повторить платёж или обновить данные карты).
Как измеряется churn
Churn Rate = (Количество ушедших пользователей / Общее количество пользователей в начале периода) × 100%
Пример: 1000 пользователей в начале месяца. 50 ушли. Churn Rate = 50/1000 × 100% = 5%.
Что считается хорошим churn rate
| Тип бизнеса | Хороший месячный churn | Плохой месячный churn |
|---|---|---|
| SaaS B2B | < 5% | > 10% |
| SaaS B2C | < 7% | > 15% |
| Мобильные игры | < 20% (первый месяц) | > 40% |
| E-commerce | < 10% | > 25% |
| Стриминг сервисы | < 5% | > 10% |
Почему важно предсказывать churn
Дешевле удержать чем привлечь нового. Привлечение нового клиента стоит в 5-25 раз дороже чем удержание существующего
Можно успеть спасти. Если знаешь что пользователь уйдёт через неделю, можешь предложить скидку, помощь, бонусы
Понимание причин. Модель показывает какие факторы влияют на отток (мало использует продукт, плохой onboarding, долго не заходит)
Приоритизация ресурсов. Не тратить время на всех, а фокусироваться на тех кто с высокой вероятностью уйдёт
2. Что такое LTV и как он связан с churn
Определение Customer Lifetime Value (LTV/CLV/CLTV)
LTV это прогноз общей прибыли которую принесёт клиент за всё время использования продукта.
Простая формула LTV:
LTV = Средний чек × Количество покупок в месяц × Среднее время жизни клиента (в месяцах)
Пример: SaaS продукт с подпиской 1000₽/месяц. Средний клиент живёт 24 месяца.
LTV = 1000₽ × 1 покупка/месяц × 24 месяца = 24 000₽
Более продвинутая формула с учётом маржинальности:
LTV = (Средний чек × Gross Margin × Количество покупок в месяц × Среднее время жизни) / Churn Rate
Связь LTV и Churn
Чем выше churn, тем ниже LTV. Если churn 10% в месяц, средний клиент живёт 10 месяцев (1/0.1). Если churn 5%, клиент живёт 20 месяцев.
Пример:
Churn 10% → Средняя жизнь 10 месяцев → LTV = 1000₽ × 10 = 10 000₽
Churn 5% → Средняя жизнь 20 месяцев → LTV = 1000₽ × 20 = 20 000₽
Снизили churn в 2 раза, LTV вырос в 2 раза!
Почему важно предсказывать LTV
Сколько можно тратить на привлечение. CAC (стоимость привлечения) должен быть меньше LTV. Обычно LTV/CAC = 3:1. Если LTV = 20 000₽, можно тратить до 6 600₽ на привлечение
Сегментация пользователей. Есть пользователи с LTV 50 000₽ и с LTV 2 000₽. К ним разный подход
Персонализация. Для высокоценных пользователей персональный менеджер, premium поддержка. Для низкоценных автоматизация
Приоритизация фич. Делать то что увеличивает LTV высокоценных сегментов
3. Какие данные нужны для предсказания
Типы данных для churn prediction
1. Демографические данные
Возраст
Пол
Город / страна
Тип компании (для B2B)
Размер компании
2. Поведенческие данные (самые важные!)
Частота использования продукта (логины в неделю)
Глубина использования (сколько функций использует)
Время в продукте (минут в день)
Паттерны активности (когда заходит, как часто)
Milestone events (прошёл onboarding, добавил команду, создал первый проект)
3. Транзакционные данные
Тип подписки (basic, pro, enterprise)
Цена
Длительность подписки
История платежей (были ли проблемы)
Upgrades / downgrades
4. Engagement данные
Email open rate
Click rate
Обращения в поддержку (количество, sentiment)
NPS score
Feature adoption (какие фичи использует)
5. Временные данные
Tenure (сколько времени с момента регистрации)
Recency (когда был последний логин)
Seasonality (сезонность)
Типы данных для LTV prediction
Для LTV нужны те же данные плюс:
Исторические транзакции: сколько тратил раньше, как часто, тренд
RFM метрики: Recency (как давно покупал), Frequency (как часто), Monetary (сколько тратит)
Product mix: какие продукты покупает, средний чек, категории
Пример датасета
Типичная структура данных для churn prediction в SaaS:
user_id | tenure_days | logins_last_30d | features_used | plan_type | monthly_spend | support_tickets | nps_score | days_since_last_login | churned
--------|-------------|-----------------|---------------|-----------|---------------|-----------------|-----------|----------------------|--------
001 | 365 | 22 | 8 | pro | 1000 | 2 | 8 | 1 | 0
002 | 90 | 3 | 2 | basic | 500 | 5 | 4 | 15 | 1
003 | 730 | 28 | 12 | enterprise| 5000 | 1 | 9 | 0 | 0Минимальный набор данных для начала
Можно начать даже с минимума:
Частота использования (логины за последние 30 дней)
Recency (дней с последнего использования)
Tenure (дней с момента регистрации)
Тип подписки
Churned (метка: ушёл или нет)
С этими 5 полями уже можно построить базовую модель!
4. Простая модель предсказания churn: пошагово
Шаг 1: Определяем что такое "churned"
Нужно чётко определить когда пользователь считается ушедшим:
SaaS с подпиской: отменил подписку
Freemium продукт: не заходил 30 дней
E-commerce: не покупал 90 дней
Мобильное приложение: не открывал 14 дней
Важно: определение churn зависит от вашего бизнеса!
Шаг 2: Собираем данные
import pandas as pd
import numpy as np
# Загружаем данные
df = pd.read_csv('users.csv')
# Смотрим структуру
print(df.head())
print(df.info())
# Проверяем баланс классов
print(df['churned'].value_counts())
# Output:
# 0 8500 (не ушли)
# 1 1500 (ушли)Шаг 3: Feature engineering (создание признаков)
# Создаём новые признаки на основе существующих
# Engagement score (насколько активен пользователь)
df['engagement_score'] = df['logins_last_30d'] / 30
# Adoption rate (сколько функций использует от общего числа)
df['feature_adoption_rate'] = df['features_used'] / 15 # если всего 15 функций
# Inactivity (как давно не заходил в днях)
df['inactivity_days'] = df['days_since_last_login']
# Value tier (сегмент по цене)
df['is_high_value'] = (df['monthly_spend'] > 2000).astype(int)
# Early stage (новый пользователь или нет)
df['is_early_stage'] = (df['tenure_days'] < 90).astype(int)Шаг 4: Готовим данные для модели
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# Выбираем признаки
features = ['tenure_days', 'logins_last_30d', 'features_used',
'monthly_spend', 'support_tickets', 'nps_score',
'days_since_last_login', 'engagement_score',
'feature_adoption_rate', 'is_high_value', 'is_early_stage']
X = df[features]
y = df['churned']
# Разделяем на train и test (80% / 20%)
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)Шаг 5: Обучаем модель (Random Forest)
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, roc_auc_score, confusion_matrix
# Создаём и обучаем модель
model = RandomForestClassifier(
n_estimators=100,
max_depth=10,
random_state=42,
class_weight='balanced' # важно для несбалансированных классов
)
model.fit(X_train_scaled, y_train)
# Предсказываем на тестовых данных
y_pred = model.predict(X_test_scaled)
y_pred_proba = model.predict_proba(X_test_scaled)[:, 1]
# Оцениваем качество
print("Confusion Matrix:")
print(confusion_matrix(y_test, y_pred))
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
print(f"\nROC-AUC Score: {roc_auc_score(y_test, y_pred_proba):.3f}")Шаг 6: Интерпретируем результаты
# Важность признаков
feature_importance = pd.DataFrame({
'feature': features,
'importance': model.feature_importances_
}).sort_values('importance', ascending=False)
print("Top 5 важных признаков:")
print(feature_importance.head())Интерпретация метрик:
Precision (точность): из тех кого модель предсказала как churned, сколько действительно ушли
Recall (полнота): из всех кто ушёл, сколько мы поймали
ROC-AUC: общее качество модели. > 0.7 хорошо, > 0.8 отлично, > 0.9 великолепно
Шаг 7: Используем модель для предсказаний
# Предсказываем вероятность churn для всех активных пользователей
active_users = pd.read_csv('active_users.csv')
active_users_features = active_users[features]
active_users_scaled = scaler.transform(active_users_features)
churn_probabilities = model.predict_proba(active_users_scaled)[:, 1]
# Добавляем вероятность в датафрейм
active_users['churn_probability'] = churn_probabilities
# Сортируем по вероятности (самые рискованные сверху)
at_risk_users = active_users.sort_values('churn_probability', ascending=False)
# Топ 100 пользователей с высоким риском
high_risk = at_risk_users.head(100)
print("Топ 10 пользователей с риском churn:")
print(high_risk[['user_id', 'churn_probability', 'monthly_spend']].head(10))5. Простая модель предсказания LTV: пошагово
Подход 1: RFM + простая формула
Для начала можно использовать RFM анализ:
# Вычисляем RFM метрики для каждого пользователя
# R (Recency) - как давно покупал (дней назад)
# F (Frequency) - как часто покупает (количество покупок за период)
# M (Monetary) - сколько тратит (средний чек)
import datetime
current_date = datetime.datetime.now()
rfm = df.groupby('user_id').agg({
'order_date': lambda x: (current_date - x.max()).days, # Recency
'order_id': 'count', # Frequency
'order_value': 'sum' # Monetary
}).reset_index()
rfm.columns = ['user_id', 'recency', 'frequency', 'monetary']
# Простая формула LTV
# Предполагаем что пользователь будет покупать с той же частотой ещё 12 месяцев
rfm['avg_order_value'] = rfm['monetary'] / rfm['frequency']
rfm['purchases_per_month'] = rfm['frequency'] / 12 # если данные за год
rfm['predicted_ltv_12m'] = rfm['avg_order_value'] * rfm['purchases_per_month'] * 12
print(rfm.head())Подход 2: Machine Learning модель
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error, r2_score
# Готовим данные
# Для LTV нам нужны пользователи у которых уже есть история
# Берём первые 6 месяцев как признаки, следующие 12 месяцев как target
# Признаки за первые 6 месяцев
features_ltv = [
'total_spend_6m', # сколько потратил за 6 месяцев
'num_orders_6m', # количество заказов
'avg_order_value_6m', # средний чек
'days_active_6m', # сколько дней был активен
'recency_6m', # как давно покупал
'tenure_days', # как давно зарегистрировался
'first_order_value', # размер первого заказа
'category_diversity' # в скольких категориях покупал
]
X_ltv = df[features_ltv]
y_ltv = df['ltv_next_12m'] # сколько потратил в следующие 12 месяцев
# Train / test split
X_train_ltv, X_test_ltv, y_train_ltv, y_test_ltv = train_test_split(
X_ltv, y_ltv, test_size=0.2, random_state=42
)
# Обучаем модель
ltv_model = RandomForestRegressor(
n_estimators=100,
max_depth=15,
random_state=42
)
ltv_model.fit(X_train_ltv, y_train_ltv)
# Предсказываем
y_pred_ltv = ltv_model.predict(X_test_ltv)
# Оцениваем
mae = mean_absolute_error(y_test_ltv, y_pred_ltv)
r2 = r2_score(y_test_ltv, y_pred_ltv)
print(f"Mean Absolute Error: {mae:.2f} руб")
print(f"R² Score: {r2:.3f}")
# Важность признаков
ltv_feature_importance = pd.DataFrame({
'feature': features_ltv,
'importance': ltv_model.feature_importances_
}).sort_values('importance', ascending=False)
print("\nВажность признаков для LTV:")
print(ltv_feature_importance)Подход 3: Probabilistic Model (BG/NBD + Gamma-Gamma)
Более продвинутый подход использует библиотеку lifetimes:
from lifetimes import BetaGeoFitter, GammaGammaFitter
# Подготовка данных в формате RFM
from lifetimes.utils import summary_data_from_transaction_data
rfm_data = summary_data_from_transaction_data(
transactions,
'user_id',
'order_date',
'order_value',
observation_period_end='2024-12-31'
)
# BG/NBD модель для предсказания частоты покупок
bgf = BetaGeoFitter(penalizer_coef=0.0)
bgf.fit(rfm_data['frequency'], rfm_data['recency'], rfm_data['T'])
# Gamma-Gamma модель для предсказания среднего чека
returning_customers = rfm_data[rfm_data['frequency'] > 0]
ggf = GammaGammaFitter(penalizer_coef=0.0)
ggf.fit(returning_customers['frequency'], returning_customers['monetary_value'])
# Предсказываем LTV на 12 месяцев вперёд
rfm_data['predicted_purchases_12m'] = bgf.predict(
12, # месяцев
rfm_data['frequency'],
rfm_data['recency'],
rfm_data['T']
)
# Предсказываем средний чек
rfm_data['predicted_avg_order_value'] = ggf.conditional_expected_average_profit(
rfm_data['frequency'],
rfm_data['monetary_value']
)
# LTV = количество покупок × средний чек
rfm_data['predicted_ltv_12m'] = (
rfm_data['predicted_purchases_12m'] *
rfm_data['predicted_avg_order_value']
)
print(rfm_data[['predicted_ltv_12m']].describe())6. Как применять предсказания на практике
Стратегия 1: Сегментация по риску churn
| Сегмент | Churn probability | Действия |
|---|---|---|
| Высокий риск | > 0.7 | Персональный outreach, спецпредложение, call от customer success |
| Средний риск | 0.3 - 0.7 | Автоматический email с бонусом, survey, напоминание о ценности |
| Низкий риск | < 0.3 | Стандартный nurturing, upsell предложения |
Стратегия 2: Персонализация по LTV
| Сегмент | Predicted LTV | Стратегия |
|---|---|---|
| VIP | > 50 000₽ | Персональный менеджер, premium support, ранний доступ к фичам |
| High value | 20 000 - 50 000₽ | Приоритетная поддержка, персональные рекомендации |
| Medium value | 5 000 - 20 000₽ | Автоматизированный nurturing, upsell кампании |
| Low value | < 5 000₽ | Self-service, минимальные затраты на retention |
Стратегия 3: Матрица Churn × LTV
Самая мощная стратегия: комбинируем обе метрики
| Сегмент | Описание | Приоритет | Действия |
|---|---|---|---|
| High LTV + High Churn Risk | Ценные клиенты на грани ухода | 🔴 Критично | Срочный call, персональное предложение, executive involvement |
| High LTV + Low Churn Risk | Лояльные ценные клиенты | 🟢 Развитие | Upsell, cross-sell, превращение в адвокатов |
| Low LTV + High Churn Risk | Неценные клиенты уходят | ⚪ Низкий | Автоматический win-back, минимальные вложения |
| Low LTV + Low Churn Risk | Стабильные недорогие | 🟡 Nurturing | Попытки увеличить engagement и LTV |
Пример автоматизации
# Скрипт который каждый день скорит пользователей и триггерит действия
import requests
# Загружаем модели
churn_model = load_model('churn_model.pkl')
ltv_model = load_model('ltv_model.pkl')
# Получаем активных пользователей
active_users = get_active_users()
# Скорим
active_users['churn_prob'] = churn_model.predict_proba(active_users[churn_features])[:, 1]
active_users['predicted_ltv'] = ltv_model.predict(active_users[ltv_features])
# Сегментируем
def segment_user(row):
if row['predicted_ltv'] > 50000:
ltv_segment = 'VIP'
elif row['predicted_ltv'] > 20000:
ltv_segment = 'High'
elif row['predicted_ltv'] > 5000:
ltv_segment = 'Medium'
else:
ltv_segment = 'Low'
if row['churn_prob'] > 0.7:
churn_segment = 'High Risk'
elif row['churn_prob'] > 0.3:
churn_segment = 'Medium Risk'
else:
churn_segment = 'Low Risk'
return f"{ltv_segment}_{churn_segment}"
active_users['segment'] = active_users.apply(segment_user, axis=1)
# Триггерим действия
for segment, users in active_users.groupby('segment'):
if segment == 'VIP_High Risk':
# Отправляем в CRM для персонального outreach
send_to_crm(users, priority='urgent')
elif segment == 'High_High Risk':
# Автоматический email с промокодом
send_retention_email(users, discount=20)
elif segment == 'VIP_Low Risk':
# Upsell кампания
send_upsell_offer(users)
# и так далее...7. Инструменты и библиотеки
Python библиотеки
scikit-learn: базовые ML алгоритмы (Random Forest, Logistic Regression, XGBoost)
lifetimes: специализированная библиотека для CLV (BG/NBD, Gamma-Gamma модели)
pandas: работа с данными
matplotlib / seaborn: визуализация
xgboost / lightgbm: продвинутые gradient boosting модели
# Установка
pip install scikit-learn lifetimes pandas matplotlib seaborn xgboostПлатформы для churn prediction
Mixpanel: встроенная churn prediction для продуктовой аналитики
Amplitude: behavioral cohorts и retention анализ
ChurnZero: B2B SaaS customer success платформа
Gainsight: enterprise customer success с ML
Pecan: automated predictive analytics
Когда использовать готовые платформы vs строить своё
Используйте готовую платформу если:
У вас нет data scientist в команде
Нужно быстро получить результат
Бюджет позволяет ($500-5000/месяц)
Хотите готовые интеграции с CRM/email
Стройте своё если:
Есть data scientist / аналитик который знает Python
Нужна кастомизация под специфику бизнеса
Большой объём данных (платформы дорожают)
Хотите контроль и гибкость
8. Типичные ошибки начинающих
Ошибка 1: Data leakage (утечка данных)
Использование информации из будущего для предсказания.
Плохо: Включить в признаки "количество support tickets за последний месяц перед churn". Проблема: это уже следствие того что пользователь недоволен.
Хорошо: Использовать только данные которые известны ДО момента когда нужно сделать предсказание.
Ошибка 2: Игнорирование несбалансированности классов
Если churned пользователей 10%, а не ушедших 90%, модель может просто всегда предсказывать "не уйдёт" и иметь 90% accuracy, но быть бесполезной.
Решение:
Используйте
class_weight='balanced'в моделиSMOTE (синтетическая генерация примеров minority класса)
Фокус на Precision/Recall вместо Accuracy
Ошибка 3: Обучение на всех данных без test set
Модель покажет отличные метрики на том же датасете на котором обучалась, но не будет работать на новых данных.
Решение: Всегда делайте train/test split или используйте cross-validation.
Ошибка 4: Забыть про временное разделение
При обучении модели churn нужно использовать исторические данные для обучения и более свежие для теста.
Плохо: Случайный split на train/test
Хорошо: Обучаем на данных 2024 года, тестируем на 2025
9. Чек-лист: с чего начать
Неделя 1: Подготовка
☐ Определите что такое churn для вашего продукта
☐ Соберите данные за последние 12 месяцев минимум
☐ Убедитесь что есть метка churned/not churned
☐ Выберите 5-10 ключевых признаков для начала
Неделя 2: Первая модель churn
☐ Загрузите данные в pandas
☐ Разделите на train/test (80/20)
☐ Обучите Random Forest модель
☐ Оцените на тестовых данных (ROC-AUC > 0.7 хорошо для начала)
☐ Посмотрите важность признаков
Неделя 3: Применение
☐ Скорите всех активных пользователей
☐ Выберите топ 100 с высоким риском
☐ Запустите пилотную retention кампанию
☐ Измерьте результаты через месяц
Неделя 4: LTV модель
☐ Соберите транзакционные данные
☐ Вычислите RFM метрики
☐ Постройте простую regression модель
☐ Сегментируйте пользователей по LTV
Месяц 2: Оптимизация
☐ Добавьте больше признаков
☐ Попробуйте другие алгоритмы (XGBoost, LightGBM)
☐ Настройте гиперпараметры
☐ Автоматизируйте скоринг (скрипт каждый день)
☐ Интегрируйте с CRM/email платформой
Месяц 3: Измерение эффекта
☐ Посчитайте сколько пользователей спасли от churn
☐ Измерьте ROI (сколько сэкономили vs затраты на retention)
☐ Оптимизируйте стратегии по сегментам
☐ Масштабируйте на всю базу
Заключение
Предиктивная аналитика для churn и LTV звучит сложно, но на практике можно начать с простых моделей и получить результат.
Ключевые выводы:
Churn prediction помогает спасти пользователей ДО того как они ушли. Снижение churn на 5% = рост прибыли на 25-95%
LTV prediction помогает правильно распределить ресурсы. Тратить больше на привлечение и retention высокоценных пользователей
Можно начать с минимума данных. Даже 5 признаков дадут работающую модель
Random Forest отличный старт. Простой в использовании, даёт хорошие результаты
Самое важное не модель, а действия. Лучшая модель бесполезна если не триггерит retention активности
С чего начать прямо сейчас:
Определите что такое churn для вашего продукта
Соберите данные за последний год
Выберите 5-10 признаков
Обучите первую модель (это займёт 2-3 часа с примерами из этой статьи)
Скорите пользователей и запустите пилот на топ 100 с риском churn
Через месяц вы увидите первые результаты. Через три месяца предиктивная аналитика станет стандартной частью вашего процесса.
В мире где привлечение клиента стоит всё дороже, умение предсказывать кто останется и сколько принесёт становится не конкурентным преимуществом, а необходимостью выживания.
А лучшие вакансии для системных, бизнес и дата аналитиков ищите на hirehi.ru