Customer churn: most of your customers have not left yet
Difficulty
★★★☆☆
Time
3-4 hours
Data
IBM Telco churn sample: 7,043 customers with tenure, churn flag, contract and billing details
Skills
Right-censoring with pm.Censored · accelerated-failure-time regression with coords/dims and index variables · designing a posterior predictive check for censored data · Kaplan-Meier · LOO across survival families · conditional survival · turning a posterior into a targeting decision
The retention team of a telecom company has budget for a retention offer and two
questions:
How long do our customers last?
Which of our current customers should get the offer?
A colleague has already answered the first one on a slide: "churned customers stayed 18
months on average". You suspect that number is badly wrong, because three quarters of the
customers in the file have not churned at all - and they are not missing data, they are the
customers who last longest.
One row per customer, taken at a single snapshot date. tenure is the number of months the
customer has been (or was) with the company, Churn says whether they have left. The other
columns describe the contract, the services booked and how the customer pays.
telco: Tenure (months), churn flag and contract details for 7043 customers.
source: IBM sample data, Telco customer churn.
url: https://raw.githubusercontent.com/IBM/telco-customer-churn-on-icp4d/master/data/Telco-Customer-Churn.csv
A clean analysis table. Two things need a decision you can defend in one sentence each:
TotalCharges does not parse as a number, and some customers have tenure == 0.
The framing: what is the "event", what is the "time", which rows are censored and at
what value? What share of customers is censored - overall and per contract type?
Kaplan-Meier survival curves per contract type in one figure. What do they tell you
beyond "customers on long contracts churn less"? How far out can each curve be trusted?
"Churned customers stayed 18 months on average, so a customer lasts about a year and a half."
Deliver
Reproduce the number. Then give the approach its best shot: fit an intercept-only
Weibull model to the churned customers alone and report the median customer lifetime
and the probability that a new customer is still there after 24 months.
The same model and the same two numbers, fitted to all customers with the censoring
handled properly.
Both survival curves on top of the overall Kaplan-Meier estimate. By what factor is the
naive median off? And of your two "correct" numbers, which one rests on data and which
is an extrapolation?
Build an accelerated-failure-time model for tenure: a censored Weibull whose log-scale is
linear in contract type, internet service, payment method and monthly charges, with a
single shape parameter.
MonthlyCharges is largely determined by the internet service (check this). Enter it as
the deviation from the average charge for the customer's internet service type, in units
of $20, so that its coefficient reads "paying more than others with the same service".
Deliver
The model with named dimensions and index variables (no dummy matrices). Think about
how to keep three categorical predictors identified.
Priors you can defend, with a prior predictive check on the scale that matters:
survival curves.
Clean diagnostics and a table of time ratios with 94% intervals: one-year and
two-year contracts relative to month-to-month, plus the other covariates.
One sentence: do you believe the two-year time ratio?
az.plot_ppc_dist on tenure is close to meaningless here (why?). Design a posterior
predictive check that respects the censoring and looks at the model by contract type.
Deliver
The figure, with posterior uncertainty.
A verdict per contract type: where, in which direction and by how much does the model
miss?
The model's predicted 12-month survival for the customers on one-year contracts, next to
the model-free estimate.
The retention team cannot act on customers who already left. For every active customer
they need the probability of churning within the next 6 months, given that the customer
has stayed until today.
Deliver
The formula, and its posterior for every active customer under your final model.
The average 6-month churn probability per contract type.
A figure of this risk against current tenure, by contract type, for the final model and
for the shared-shape model of Task 2. What did the fix change about who looks risky?
A sanity check of this very quantity against the data: Kaplan-Meier can estimate
"churn within 6 months given survival to $t$" too. Use it to decide which of your
Task 4 contenders to carry into the decision.
The offer on the table, with the retention team's working assumptions:
OFFER_COST=40.0# dollars per customer who receives the offerOFFER_EFFECT=0.30# assumed: the offer cuts the 6-month churn probability by 30% (relative)VALUE_MONTHS=12# a customer saved from churning is worth 12 months of their MonthlyCharges
Deliver
The posterior of the expected net value of making the offer, for every active customer.
A ranked top-10 list with the uncertainty a manager needs to see.
A targeting rule, the number of customers it selects, and the total expected profit with
an interval. Compare it with the blanket policy "offer it to every month-to-month customer".
Robustness: how much does the target list change under the runner-up model from Task 4?
And which assumption would you most want to test before spending real money?
Month-to-month churn is a bathtub: a spike in month one, a long quiet period, and a
rise again after four years. Neither family here can express that. Try a piecewise-constant
hazard (a piecewise exponential model is a Poisson regression in disguise) and rerun the
Task 5 check.
tenure is recorded in whole months, so a "churn at 1" is really a churn somewhere in
(0, 1]. Treat events as interval-censored - pm.Censored will not do it, but a
pm.Potential or pm.CustomDist on $S(t-1) - S(t)$ will. Does the first-month spike look
different?
The offer's effect was assumed. Put a prior on it (say, a Beta centred on 0.3), push it
through the decision, and work out how large a randomised pilot would have to be before
the target list stops changing.
The file is a snapshot taken on one date, not a cohort followed from sign-up. What would
you need to know about how customers entered the file to rule out left-truncation,
and how would it enter the likelihood if you knew each customer's sign-up date?
h.progress()
C04: 0/21 hints used, 15/15 checks passed.
Reference solution
A complete, executed solution with commentary on every task — including the ways the obvious model fails. Try the hint ladder first.