← Назад к вопросам

Как перевести отток пассажиров в денежные метрики?

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} месяцев")

Заключение

Ключевые шаги по переводу оттока в денежные метрики:

  1. Identify churned customers: Определи, кто уходит
  2. Calculate individual value: Считай доход каждого пассажира (Annual/Lifetime value)
  3. Aggregate impact: Общая потеря = Churned Customers × Customer Value
  4. Intervention cost: Стоимость удержания (скидки, оффер, техподдержка)
  5. Success rate: Какой % пассажиров удерживаешь интервенцией
  6. Calculate ROI: (Revenue Saved - Intervention Cost) / Intervention Cost × 100%
  7. Payback period: Когда окупится инвестиция

Для обоснования ML модели:

  • Baseline churn loss (текущий ущерб)
  • Model-improved retention (насколько улучшит модель)
  • Model cost (разработка + содержание)
  • Expected ROI (должен быть >200-300% в год)

Это даёт чёткий бизнес-кейс для инвестиции в ML проект удержания пассажиров.