Условие
Среднее время до отписки 60 дней. Как смоделировать время до churn?
Решение
Exponential(λ)
- Time between events с постоянным rate.
- Memoryless: P(T > s+t | T > s) = P(T > t). «Сколько ждал — не важно».
- E[T] = 1/λ.
- Var[T] = 1/λ².
from scipy.stats import expon
expon.rvs(scale=60, size=1000) # mean=60 днейCDF: вероятность отписаться за t
P(T ≤ t) = 1 - exp(-λt) = 1 - exp(-t/60)
Для t=30: P = 1 - exp(-0.5) = 0.39 (39% отписки за 30 дней при mean 60). Для t=60: P = 1 - exp(-1) = 0.63. Для t=120: P = 1 - exp(-2) = 0.86.
Связь с Poisson
Если события Poisson(rate λ), интервалы между ними — Exponential(λ).
Hazard rate
h(t) = f(t) / S(t) = λ (constant)
«Шанс отписаться сегодня» не зависит от того, сколько уже подписан. Это и значит memoryless.
Когда не exponential
Если hazard меняется со временем — Weibull / Gompertz / Log-logistic. Типично:
- Memberships в первые 30 дней — высокий hazard (новичек уйдёт быстрее).
- Дальше — стабилизируется.
→ Weibull с shape k. Для k<1 — hazard падает (новички уходят сильнее), для k>1 — растёт (старение).
Censored data — Kaplan-Meier
Часть юзеров ещё не отписались (right-censored). Простой mean занижает истинное среднее время до churn.
from lifelines import KaplanMeierFitter, ExponentialFitter, WeibullFitter
ef = ExponentialFitter()
ef.fit(durations, event_observed)
print(ef.lambda_) # rate
# Сравнить с Weibull
wf = WeibullFitter()
wf.fit(durations, event_observed)
# Если k далеко от 1 — exponential не подходитПрименение в продукте
- Time-to-purchase моделирование.
- Time-to-churn для subscription.
- Inter-event timing (между сессиями).
Подводные камни
- Memoryless = очень сильное предположение. Часто нарушается (новичек уходит быстрее).
- На censored data нельзя считать
mean(times)— нужен Kaplan-Meier или parametric fit. - Exponential близко к Geometric (дискретный аналог) — для дискретных дней годится.
- Mean ≠ median: median = ln(2)/λ ≈ 0.693/λ. Для mean=60 дней median = 41.6.
- Heavy tails: exp на 5× от mean — низкая вероятность, на 10× — практически 0.
Эталонный ответ
Exponential(λ) с E[T] = 1/λ для time-to-event при постоянном hazard. Memoryless: P(T>s+t|T>s) = P(T>t). При непостоянном hazard → Weibull. Censored data — Kaplan-Meier.