Go to main content
Modelli predittivi per LTV e churn - immagine ufficiale della lezione su GinnyTech, creata da AD

Predictive models for LTV and churn

Build predictive models for Customer Lifetime Value and churn probability in marketing.

AD
Created byAndrii Dyshkantiuk
Lesson 87 / 236Level: AdvancedDuration: 22 minPrerequisites: 1

What you will learn

  • Understand the analytical problem and the decision-making context
  • Apply examples, metrics, and controls to real cases

import joblib

Predictive models for LTV and 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.

StepQuestion to askExpected output
DecisionChe cosa cambia se capiamo meglio il fenomeno?Scelta esplicita
SignalQuale dato osservabile riduce l’incertezza?Metrica o evento
BaselineRispetto a cosa interpretiamo il risultato?Credible comparison
VincoloChe cosa può falsare la lettura?Assunzione da dichiarare
ActionQuale 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.

ElementOperational DefinitionControllo minimo
Unit of analysisOggetto su cui misuri il fenomenoUtente, account, evento, ordine o periodo
Variabile osservataSegnale che rappresenta il comportamentoDefinizione stabile e tracciabile
BaselineStato contro cui confronti il segnalePeriodo, segmento, controllo o benchmark
Soglia decisionalePunto in cui cambia l’azioneCriterio scritto prima della lettura
Rischio residuoErrore che può restare anche dopo l’analisiSensitivity 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)

# Features: behavior first 4 weeks
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):
    # Predict on recent period
    preds = model.predict_proba(recent_data[feature_cols])[:, 1]
    auc = roc_auc_score(actual_outcomes['churned'], preds)
    
    # Check 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 significantly different from training
            print(f"WARNING: {col} distribution shifted (KS={ks_stat:.3f})")
    
    # Alert if AUC drops below threshold
    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?

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.