
Modelli predittivi per LTV e churn
Costruire modelli predittivi per Customer Lifetime Value e churn probability nel marketing.
Cosa imparerai
- Comprendere il problema analitico e il contesto decisionale
- Applicare esempi, metriche e controlli a casi reali
Collegamenti
import joblib
Modelli predittivi per LTV e churn
Questa è una lezione tecnica, quindi il punto non è accumulare definizioni ma capire quale decisione commerciale cambia quando il modello diventa più affidabile. Un modello ordina i clienti per rischio di abbandono, ma il marketing può contattarne solo una parte e alcune offerte costano più del valore recuperato. Predire non basta: occorre sapere su chi intervenire, quando e con quale ritorno atteso.
Il problema reale
Un classificatore di churn produce una lista ordinata per rischio. Poi cominciano i vincoli veri. Il budget consente di contattare solo una frazione dei clienti, alcune offerte di retention costano più del valore che recuperano, e una parte dei clienti sarebbe rimasta comunque. Per questo la lezione collega tre cose che spesso restano separate: probabilità di abbandono, valore atteso del cliente e costo dell’azione commerciale.
Il problema vero non è conoscere il churn in astratto. È decidere cosa fare quando i dati sono incompleti, le metriche ambigue o i vincoli operativi rendono fragile la lettura. Una buona previsione va progettata come un intervento, non solo come un classificatore: deve rispettare timing, capacità operativa, margine e il rischio di trattare clienti che non sarebbero mai partiti.
Come impostare il ragionamento
Usa questa sequenza come mappa di lavoro. Ogni passaggio deve rendere più chiaro il costo di una decisione sbagliata.
| Passaggio | Domanda da fare | Output atteso |
|---|---|---|
| Decisione | Che cosa cambia se capiamo meglio il fenomeno? | Scelta esplicita |
| Segnale | Quale dato osservabile riduce l’incertezza? | Metrica o evento |
| Baseline | Rispetto a cosa interpretiamo il risultato? | Confronto credibile |
| Vincolo | Che cosa può falsare la lettura? | Assunzione da dichiarare |
| Azione | Quale passo operativo segue? | Raccomandazione controllabile |
Lo stesso schema regge anche il caso scomodo: il modello identifica clienti ad alto rischio, ma metà di loro ha LTV basso e non giustifica un’offerta costosa. Se non combini probabilità di abbandono, valore atteso e costo dell’intervento, finisci per salvare clienti non profittevoli.
Come formalizzare il problema
Formalizzare non serve a complicare. Serve a rendere visibili le assunzioni, così un altro analista può riprodurre la logica, criticarla e arrivare alla stessa decisione partendo dagli stessi dati.
| Elemento | Definizione operativa | Controllo minimo |
|---|---|---|
| Unità di analisi | Oggetto su cui misuri il fenomeno | Utente, account, evento, ordine o periodo |
| Variabile osservata | Segnale che rappresenta il comportamento | Definizione stabile e tracciabile |
| Baseline | Stato contro cui confronti il segnale | Periodo, segmento, controllo o benchmark |
| Soglia decisionale | Punto in cui cambia l’azione | Criterio scritto prima della lettura |
| Rischio residuo | Errore che può restare anche dopo l’analisi | Sensitivity check o revisione qualitativa |
Il rischio principale resta scambiare un numero disponibile per una prova sufficiente.
Le feature che predicono il churn
Le feature più predittive di churn, confermate su decine di implementazioni, seguono un ordine abbastanza stabile. Il singolo miglior predittore, quasi universalmente, è la recency, cioè i giorni dall’ultima azione significativa. Subito dopo viene il trend di utilizzo (attività recente rispetto a quella precedente), dove la direzione conta più del livello assoluto. Pesano poi gli eventi negativi come pagamenti falliti, ticket di supporto o downgrade di piano, l’engagement depth cioè quante feature core il cliente usa abitualmente, e infine la tenure: i clienti nuovi churnano più degli storici, un paradosso solo apparente.
df['recency'] = (df['today'] - df['last_active_date']).dt.days
df['usage_trend'] = df['active_days_last_14'] / df['active_days_prev_14'].clip(lower=1)
df['has_payment_failure'] = (df['failed_payments_30d'] > 0).astype(int)
df['engagement_depth'] = df[['feature_A', 'feature_B', 'feature_C', 'feature_D']].sum(axis=1)
df['tenure_months'] = (df['today'] - df['signup_date']).dt.days / 30.44
Attenzione a non valutare mai il modello con l’accuracy su dataset sbilanciati. Con un churn rate del 5%, un modello che dice sempre “no churn” raggiunge il 95% di accuracy ed è completamente inutile. Le metriche corrette sono AUC-ROC (sopra 0.80 è buono), precision@K, per esempio la precision nel top 20% dei clienti più a rischio, e il lift.
Due approcci per prevedere l’LTV
Per il retail e l’ecommerce con acquisti discreti e non a subscription, l’approccio probabilistico BG/NBD più Gamma-Gamma modella frequenza e valore come processi stocastici.
from lifetimes import BetaGeoFitter, GammaGammaFitter
# BG/NBD per frequenza acquisti futuri
bgf = BetaGeoFitter(penalizer_coef=0.01)
bgf.fit(df['frequency'], df['recency'], df['T'])
# Gamma-Gamma per valore medio per acquisto
ggf = GammaGammaFitter(penalizer_coef=0.01)
ggf.fit(df['frequency'], df['monetary_value'])
# LTV predetto a 12 mesi
ltv_12m = ggf.customer_lifetime_value(
bgf, df['frequency'], df['recency'], df['T'],
df['monetary_value'], time=12, discount_rate=0.01)
Il vantaggio è che resta interpretabile, robusto e basato su assunzioni esplicite. Il limite è che funziona solo con pattern di acquisto discreti, non con le subscription.
Per il SaaS, le subscription o i dati con molte feature comportamentali conviene un Gradient Boosting Regression.
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
model = HistGradientBoostingRegressor(
max_iter=200, max_depth=5, learning_rate=0.05,
early_stopping=True, validation_fraction=0.1, random_state=42)
# Feature: comportamento prime 4 settimane
features = ['w1_sessions', 'w2_sessions', 'w3_sessions', 'w4_sessions',
'features_used_w4', 'support_tickets_w4', 'plan_type',
'acquisition_source', 'country', 'device_type']
model.fit(X_train, y_train)
predicted_ltv = model.predict(X_test)
È flessibile, cattura relazioni non lineari e gestisce molte feature, ma è meno interpretabile e richiede più dati.
Mandare il modello in produzione
In produzione il modello vive dentro una pipeline di scoring batch che gira ogni giorno: carica il modello salvato, estrae le feature dal warehouse, calcola la probabilità di churn e scrive il risultato su una tabella di activation, segmentando già i clienti per azione.
# Pipeline di scoring batch (giornaliera)
# Carica modello
model = joblib.load('models/churn_model_v3.joblib')
# Estrai feature da warehouse
query = """
SELECT c.customer_id,
DATEDIFF('day', c.last_active, CURRENT_DATE) AS recency,
...
FROM customers c
LEFT JOIN activity a ON c.customer_id = a.customer_id
"""
df = pd.read_sql(query, warehouse_engine)
# Predici
df['churn_probability'] = model.predict_proba(df[feature_cols])[:, 1]
# Segmenta per azione
df['action'] = pd.cut(df['churn_probability'],
bins=[0, 0.3, 0.6, 0.8, 1.0],
labels=['low_risk', 'monitor', 'high_risk', 'critical'])
# Scrivi su tabella di activation
df[['customer_id', 'churn_probability', 'action']].to_sql(
'mrt_activation__churn_prediction', warehouse_engine,
if_exists='replace', index=False)
Monitorare il modello nel tempo
I modelli predittivi degradano perché il comportamento dei clienti cambia. Il controllo minimo verifica l’AUC sul periodo recente, misura il drift delle feature con un test di Kolmogorov-Smirnov e lancia un alert quando l’AUC scende sotto soglia.
def check_model_health(recent_data, actual_outcomes):
# Predici sul periodo recente
preds = model.predict_proba(recent_data[feature_cols])[:, 1]
auc = roc_auc_score(actual_outcomes['churned'], preds)
# Verifica feature drift
for col in feature_cols:
ks_stat = ks_2samp(
training_data[col].dropna(),
recent_data[col].dropna()
).statistic
if ks_stat > 0.15: # feature significativamente diversa dal training
print(f"WARNING: {col} distribution shifted (KS={ks_stat:.3f})")
# Alert se AUC scende sotto soglia
if auc < AUC_THRESHOLD_ALERT:
send_alert(f"Model AUC dropped to {auc:.3f}")
Un modello in produzione è un processo continuo, non un artefatto statico.
Controllo di qualità e interpretazione per segmenti
Prima di usare un modello di LTV o churn in una decisione, controlla sempre completezza, duplicati, timezone, definizioni cambiate e segmenti esclusi. Molte analisi apparentemente sofisticate falliscono perché il dato di partenza misura un comportamento diverso da quello che il team crede di osservare.
La media aggregata è solo il punto di partenza. Segmenta per canale, coorte, piano, paese, device e maturità dell’utente: se due segmenti si muovono in direzioni opposte, la media non rappresenta nessuno dei due e può portare a una scelta sbagliata. Ogni analisi deve chiudersi con una decisione possibile, che sia continuare, fermare, iterare, investire, rimuovere o approfondire. Se il modello non cambia una decisione, manca ancora il collegamento tra metrica e azione.
Lab ed esercizi
Comincia da una scheda di una pagina: decisione da supportare, metrica primaria, baseline, rischio principale e azione se il segnale è confermato. Al livello intermedio costruisci una tabella con tre segmenti o scenari, indicando per ciascuno cosa cambia, quale spiegazione alternativa è plausibile e quale controllo useresti prima di raccomandare un’azione. Al livello research-grade prepara un decision memo completo con ipotesi, dati richiesti, criteri di esclusione, controlli di qualità, soglia decisionale, rischio residuo e piano di monitoraggio. Se non hai dati reali, costruisci un dataset sintetico con almeno 200 righe, una dimensione temporale, una dimensione segmento e una metrica di outcome.
L’errore più comune è usare il modello come etichetta invece che come processo: un grafico senza decisione, una metrica senza baseline, una conclusione senza l’assunzione che potrebbe invalidarla. La domanda di controllo: se questo risultato fosse instabile, quale scelta sbaglierei?
Quiz e checkpoint
Per verificare di aver collegato analisi e azione, rispondi a cinque domande. Quale decisione concreta dovrebbe migliorare il modello? Quale unità di analisi rende il problema misurabile? Quale baseline useresti per evitare una lettura ingenua? Quale errore tipico potrebbe cambiare la conclusione? E quale output consegneresti a uno stakeholder non tecnico?
Riepilogo
Un modello di LTV o churn diventa utile quando produce una decisione più chiara, non quando aggiunge terminologia. La forma corretta del ragionamento resta sempre la stessa: decisione, segnale, baseline, rischio e azione, con probabilità, valore e costo dell’intervento tenuti insieme. Hai assimilato il metodo quando riesci a spiegarlo senza gergo, applicarlo a un caso piccolo ma realistico e difendere una raccomandazione includendo i limiti e i prossimi controlli. Categoria Tecnico, difficoltà advanced, tempo stimato 22 minuti.
Percorso collegato
Lezioni da leggere insieme
Questi collegamenti portano la lezione dentro il resto del corso: basi da riprendere, passaggi successivi e connessioni tematiche tra moduli.