← Назад к вопросам
Как перевести отток пассажиров в денежные метрики?
2.0 Middle🔥 111 комментариев
#Метрики и оценка моделей
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Перевод оттока пассажиров в денежные метрики
Перевод бизнес-метрик (как отток пассажиров) в денежные единицы (Revenue Impact) — это критическая задача для обоснования инвестиций в ML проекты. Это показывает реальный ROI модели.
1. Основная формула: от оттока к доходу
import pandas as pd
import numpy as np
# Сценарий: Авиакомпания теряет пассажиров
# Базовые данные
total_passengers = 1_000_000 # пассажиров в месяц
churn_rate = 0.05 # 5% оттока в месяц
churned_passengers = total_passengers * churn_rate # 50,000 пассажиров
# Финансовые данные
avg_ticket_price = 150 # USD средняя цена билета
avg_trips_per_churned_customer = 12 # в год
lifetime_value_per_customer = avg_ticket_price * avg_trips_per_churned_customer
print(f"Количество потерянных пассажиров: {churned_passengers:,.0f}")
print(f"Lifetime value одного пассажира: ${lifetime_value_per_customer:,.0f}")
# Общий ущерб от оттока в месяц
monthly_revenue_loss = churned_passengers * avg_ticket_price
yearly_revenue_loss = monthly_revenue_loss * 12
print(f"Ежемесячная потеря выручки: ${monthly_revenue_loss:,.0f}")
print(f"Годовая потеря выручки: ${yearly_revenue_loss:,.0f}")
2. Прогноз оттока и его денежный эквивалент
# Пример: ML модель предсказывает отток
# Данные по пассажирам
passengers_df = pd.DataFrame({
'passenger_id': range(1, 100001),
'annual_trips': np.random.randint(1, 30, 100000),
'avg_ticket_price': np.random.normal(150, 50, 100000),
'loyalty_score': np.random.uniform(0, 100, 100000),
'churn_probability': np.random.uniform(0, 1, 100000) # предсказание модели
})
# Классифицируем по риску оттока
passengers_df['risk_segment'] = pd.cut(
passengers_df['churn_probability'],
bins=[0, 0.3, 0.6, 1.0],
labels=['Low Risk', 'Medium Risk', 'High Risk']
)
# Расчёт потенциального ущерба
passengers_df['annual_revenue_value'] = (
passengers_df['annual_trips'] * passengers_df['avg_ticket_price']
)
passengers_df['potential_loss'] = (
passengers_df['annual_revenue_value'] * passengers_df['churn_probability']
)
# Группировка по сегментам
risk_analysis = passengers_df.groupby('risk_segment').agg({
'passenger_id': 'count',
'potential_loss': 'sum',
'churn_probability': 'mean'
}).rename(columns={'passenger_id': 'count'})
print("\nРиск-анализ по сегментам:")
print(risk_analysis)
print(f"\nОбщий потенциальный убыток: ${passengers_df['potential_loss'].sum():,.0f}")
3. ROI модели удержания пассажиров
class ChurnInterventionROI:
def __init__(self,
high_risk_customers,
intervention_cost_per_customer,
success_rate,
avg_customer_value):
"""
high_risk_customers: количество пассажиров с высоким риском оттока
intervention_cost_per_customer: стоимость мероприятия (скидка, оффер)
success_rate: вероятность, что мероприятие удержит пассажира
avg_customer_value: среднегодовой доход от пассажира
"""
self.high_risk_customers = high_risk_customers
self.intervention_cost = intervention_cost_per_customer
self.success_rate = success_rate
self.customer_value = avg_customer_value
def calculate_roi(self):
# Общая стоимость интервенций
total_intervention_cost = self.high_risk_customers * self.intervention_cost
# Количество удержанных пассажиров
retained_customers = self.high_risk_customers * self.success_rate
# Выручка от удержания
revenue_from_retention = retained_customers * self.customer_value
# Чистая прибыль
net_profit = revenue_from_retention - total_intervention_cost
# ROI
roi = (net_profit / total_intervention_cost) * 100 if total_intervention_cost > 0 else 0
return {
'total_intervention_cost': total_intervention_cost,
'retained_customers': retained_customers,
'revenue_from_retention': revenue_from_retention,
'net_profit': net_profit,
'roi_percent': roi,
'payback_months': 12 / (roi / 100 + 1) if roi >= 0 else float('inf')
}
# Пример
roi_model = ChurnInterventionROI(
high_risk_customers=5000,
intervention_cost_per_customer=30, # $30 скидка на следующий билет
success_rate=0.4, # 40% удержания благодаря интервенции
avg_customer_value=1800 # $1800 в год
)
results = roi_model.calculate_roi()
print("ROI Analysis for Churn Intervention:")
for key, value in results.items():
if 'cost' in key or 'revenue' in key or 'profit' in key:
print(f"{key}: ${value:,.0f}")
elif 'percent' in key:
print(f"{key}: {value:.1f}%")
elif 'months' in key:
print(f"{key}: {value:.1f}")
else:
print(f"{key}: {value:,.0f}")
4. Сложный расчёт: долгосрочный LTV (Lifetime Value)
def calculate_customer_ltv(initial_annual_value,
retention_rate,
years=5,
discount_rate=0.1,
cost_of_service=0.3):
"""
Расчёт долгосрочной стоимости пассажира
LTV = Сумма по годам: (Annual Value * Margin) / (1 + Discount Rate)^year
"""
ltv = 0
margin = 1 - cost_of_service # 70% прибыли
for year in range(years):
# Вероятность остаться = retention_rate ^ year
survival_probability = retention_rate ** year
# Дисконтированная стоимость
annual_profit = initial_annual_value * margin
discounted_value = (annual_profit * survival_probability) / ((1 + discount_rate) ** year)
ltv += discounted_value
print(f"Year {year+1}: Prob={survival_probability:.2%}, Discounted Value=${discounted_value:,.0f}")
return ltv
# Сценарии
print("Сценарий 1: Текущий retention 95% (без intervention):")
ltv_current = calculate_customer_ltv(
initial_annual_value=1800,
retention_rate=0.95,
years=5,
discount_rate=0.1
)
print(f"LTV: ${ltv_current:,.0f}\n")
print("Сценарий 2: После intervention retention 97% (улучшение на 2%):")
ltv_improved = calculate_customer_ltv(
initial_annual_value=1800,
retention_rate=0.97,
years=5,
discount_rate=0.1
)
print(f"LTV: ${ltv_improved:,.0f}\n")
print(f"Дополнительная стоимость per customer: ${ltv_improved - ltv_current:,.0f}")
print(f"На 100k пассажиров: ${(ltv_improved - ltv_current) * 100000:,.0f}")
5. Практический пример: Metro система
# Реальный случай: мобильное приложение для заказа билетов в метро
class MetroChurnAnalysis:
def __init__(self):
# Данные о пассажирах
self.monthly_active_users = 500_000
self.churn_rate_monthly = 0.08 # 8% в месяц
self.avg_trips_per_user = 20 # в месяц
self.price_per_trip = 1.50 # USD
# Опционально: платная подписка
self.premium_subscriber_rate = 0.1 # 10% платят за подписку
self.premium_price = 30 # USD в месяц
def calculate_monthly_revenue(self):
# Доход от billets
active_users = self.monthly_active_users
trips_revenue = active_users * self.avg_trips_per_user * self.price_per_trip
# Доход от подписок
premium_users = active_users * self.premium_subscriber_rate
subscription_revenue = premium_users * self.premium_price
total_monthly_revenue = trips_revenue + subscription_revenue
return {
'trips_revenue': trips_revenue,
'subscription_revenue': subscription_revenue,
'total_monthly': total_monthly_revenue,
'total_yearly': total_monthly_revenue * 12
}
def impact_of_churn_reduction(self, churn_reduction_percent):
"""
Показывает, как изменятся доходы если снизить отток
"""
# Текущий отток
churned_monthly = self.monthly_active_users * self.churn_rate_monthly
# Отток после улучшения
new_churn_rate = self.churn_rate_monthly * (1 - churn_reduction_percent / 100)
saved_users = self.monthly_active_users * (self.churn_rate_monthly - new_churn_rate)
# Эффект на доход
saved_trips_revenue = saved_users * self.avg_trips_per_user * self.price_per_trip * 12
saved_subscription_revenue = saved_users * 0.1 * self.premium_price * 12
total_impact = saved_trips_revenue + saved_subscription_revenue
return {
'saved_users_annually': saved_users * 12,
'saved_trips_revenue_yearly': saved_trips_revenue,
'saved_subscription_revenue_yearly': saved_subscription_revenue,
'total_yearly_impact': total_impact
}
metro = MetroChurnAnalysis()
print("Текущие доходы:")
current_revenue = metro.calculate_monthly_revenue()
for key, value in current_revenue.items():
print(f" {key}: ${value:,.0f}")
print("\nВлияние 20% снижения оттока на годовой доход:")
impact = metro.impact_of_churn_reduction(churn_reduction_percent=20)
for key, value in impact.items():
print(f" {key}: ${value:,.0f}")
6. Более сложный расчёт с сегментацией
# Разные сегменты пассажиров имеют разную стоимость
segments = pd.DataFrame({
'segment': ['Casual', 'Regular', 'Premium', 'VIP'],
'monthly_users': [300_000, 150_000, 40_000, 10_000],
'churn_rate': [0.10, 0.08, 0.05, 0.02],
'avg_annual_value': [200, 600, 1500, 5000]
})
# Потенциальные потери от оттока
segments['annual_churned_users'] = segments['monthly_users'] * segments['churn_rate'] * 12
segments['annual_revenue_loss'] = segments['annual_churned_users'] * segments['avg_annual_value']
print("\nПотери по сегментам:")
print(segments[['segment', 'annual_churned_users', 'annual_revenue_loss']])
print(f"\nОбщие годовые потери: ${segments['annual_revenue_loss'].sum():,.0f}")
# Стоимость интервенций по сегментам
segments['intervention_cost'] = [5, 10, 20, 50] # USD per customer
segments['intervention_budget'] = segments['annual_churned_users'] * segments['intervention_cost']
segments['success_rate'] = [0.3, 0.4, 0.5, 0.7]
segments['retained_users'] = segments['annual_churned_users'] * segments['success_rate']
segments['revenue_recovered'] = segments['retained_users'] * segments['avg_annual_value']
segments['net_profit'] = segments['revenue_recovered'] - segments['intervention_budget']
print("\nROI по сегментам:")
print(segments[['segment', 'intervention_budget', 'revenue_recovered', 'net_profit']])
7. Критические метрики для обоснования инвестиции
class ChurnModelROI:
def __init__(self, model_annual_cost=50_000):
self.model_cost = model_annual_cost
def evaluate_model(self, impact_on_churn_reduction):
"""
impact_on_churn_reduction: процент на который модель улучшает retention
"""
# Допустим базовая потеря от оттока $2млн в год
base_churn_loss = 2_000_000
# Спасённый доход
saved_revenue = base_churn_loss * impact_on_churn_reduction / 100
# Чистая прибыль
net_benefit = saved_revenue - self.model_cost
# ROI модели
model_roi = (net_benefit / self.model_cost) * 100
# Payback period
payback_months = 12 * self.model_cost / saved_revenue if saved_revenue > 0 else float('inf')
return {
'saved_revenue': saved_revenue,
'model_cost': self.model_cost,
'net_benefit': net_benefit,
'roi_percent': model_roi,
'payback_months': payback_months
}
model_roi = ChurnModelROI(model_annual_cost=100_000)
for impact in [5, 10, 15, 20]:
results = model_roi.evaluate_model(impact)
print(f"\nЕсли модель улучшает retention на {impact}%:")
print(f" Спасённый доход: ${results['saved_revenue']:,.0f}")
print(f" ROI модели: {results['roi_percent']:.0f}%")
print(f" Окупаемость: {results['payback_months']:.1f} месяцев")
Заключение
Ключевые шаги по переводу оттока в денежные метрики:
- Identify churned customers: Определи, кто уходит
- Calculate individual value: Считай доход каждого пассажира (Annual/Lifetime value)
- Aggregate impact: Общая потеря = Churned Customers × Customer Value
- Intervention cost: Стоимость удержания (скидки, оффер, техподдержка)
- Success rate: Какой % пассажиров удерживаешь интервенцией
- Calculate ROI: (Revenue Saved - Intervention Cost) / Intervention Cost × 100%
- Payback period: Когда окупится инвестиция
Для обоснования ML модели:
- Baseline churn loss (текущий ущерб)
- Model-improved retention (насколько улучшит модель)
- Model cost (разработка + содержание)
- Expected ROI (должен быть >200-300% в год)
Это даёт чёткий бизнес-кейс для инвестиции в ML проект удержания пассажиров.