Previsione del lifetime value cliente con AI Platform: addestramento dei modelli

Questo articolo è la seconda parte di una serie in quattro parti che illustra come prevedere il lifetime value cliente (CLV) utilizzando AI Platform (AI Platform) su Google Cloud.

Gli articoli di questa serie includono:

  • Parte 1: introduzione. Introduce il CLV e due tecniche di modellazione per prevedere il CLV.
  • Parte 2: addestrare il modello (questo articolo). Illustra come preparare i dati e addestrare i modelli.
  • Parte 3: deployment in produzione. Descrive come eseguire il deployment dei modelli illustrati nella Parte 2 in un sistema di produzione.
  • Parte 4: utilizzo di AutoML Tables. Mostra come utilizzare AutoML Tables per creare un modello ed eseguirne il deployment.

Il codice per implementare questo sistema si trova in un repository di GitHub. Questa serie descrive lo scopo e il modo in cui viene utilizzato il codice.

Introduzione

Questo articolo segue la Parte 1, in cui hai imparato a conoscere due diversi modelli per prevedere il lifetime value cliente (CLV):

  • Modelli probabilistici
  • Modelli DNN (Deep Neural Network), un tipo di modello di machine learning

Come indicato nella Parte 1, uno degli obiettivi di questa serie è confrontare questi modelli per prevedere il CLV. Questa parte della serie descrive come preparare i dati, nonché creare e addestrare entrambi i tipi di modello per prevedere il CLV, oltre a fornire alcune informazioni di confronto.

Installazione del codice

Se vuoi seguire la procedura descritta in questo articolo, devi installare il codice campione da GitHub.

  1. Se hai installato gcloud CLI, apri una finestra del terminale sul computer per eseguire questi comandi. Se non hai installato gcloud CLI, apri un'istanza di Cloud Shell.

    VAI A Cloud Shell

  2. Clona il repository del codice campione:

    git clone
    https://github.com/GoogleCloudPlatform/tensorflow-lifetime-value
    
  3. Segui le istruzioni di installazione nella sezione Installa del file README per configurare il tuo ambiente.

Preparazione dei dati

Questa sezione descrive come recuperare i dati e pulirli.

Recupero e pulizia del set di dati di origine

Prima di poter calcolare il CLV, devi assicurarti che i dati di origine contengano almeno quanto segue:

  • Un ID cliente utilizzato per differenziare i singoli clienti.
  • Un importo di acquisto per cliente che mostra quanto ha speso un cliente in un momento specifico.
  • Una data per ogni acquisto.

In questo articolo, parleremo di come addestrare i modelli utilizzando i dati di vendita storici dal set di dati sulla vendita al dettaglio online disponibile pubblicamente dall'UCI Machine Learning Repository.[1]

Il primo passaggio consiste nel copiare il set di dati come file CSV in Cloud Storage. Utilizzando uno degli strumenti di caricamento per BigQuery, puoi quindi creare una tabella denominata data_source. Questo nome è arbitrario, ma il codice nel repository GitHub utilizza questo nome. Il set di dati è disponibile in un bucket pubblico associato a questa serie ed è già stato convertito in formato CSV.

  1. Sul computer o in Cloud Shell, esegui i comandi documentati nella sezione Configurazione del file README nel repository GitHub.

Il set di dati di esempio contiene i campi elencati nella seguente tabella. Per l'approccio descritto in questo articolo, utilizzi solo i campi in cui la colonna Used è impostata su Yes. Alcuni campi non vengono utilizzati direttamente, ma aiutano a crearne di nuovi, ad esempio UnitPrice e Quantity creano order_value.

Utilizzata Campo Tipo Descrizione
No InvoiceNo STRING Nominale. Un numero integrale a 6 cifre assegnato in modo univoco a ogni transazione. Se questo codice inizia con la lettera c, indica un annullamento.
No StockCode STRING Codice del prodotto (articolo). Nominale, un numero integrale a 5 cifre assegnato in modo univoco a ciascun prodotto distinto.
No Description STRING Nome del prodotto (elemento). Nominale.
Quantity INTEGER Le quantità di ciascun prodotto (articolo) per transazione. Valore numerico.
InvoiceDate STRING Data e ora della fattura in formato mm/gg/aa hh:mm. Il giorno e l'ora in cui è stata generata ogni transazione.
UnitPrice FLOAT Prezzo unitario. Valore numerico. Il prezzo del prodotto per unità in sterline.
CustomerID STRING Numero cliente. Nominale. Un numero integrale a 5 cifre assegnato in modo univoco a ciascun cliente.
No Country STRING Nome del paese. Nominale. Il nome del paese in cui risiede ciascun cliente.

Pulizia dei dati

Indipendentemente dal modello utilizzato, devi eseguire un insieme di passaggi di preparazione e pulizia comuni a tutti i modelli. Per ottenere una serie di campi e record utilizzabili, sono necessarie le seguenti operazioni:

  1. Raggruppa gli ordini per giorno anziché utilizzare InvoiceNo, perché l'unità di tempo minima utilizzata dai modelli probabilistici in questa soluzione è di un giorno.
  2. Conserva solo i campi che sono utili per i modelli probabilistici.
  3. Conserva solo i record con quantità degli ordini e valori monetari positivi, come gli acquisti.
  4. Conserva solo i record con quantità degli ordini negative, come i resi.
  5. Conserva solo i record con un ID cliente.
  6. Conserva solo i clienti che hanno effettuato un acquisto negli ultimi 90 giorni.
  7. Conserva solo i clienti che hanno effettuato almeno due acquisti nel periodo di tempo utilizzato per creare le funzionalità.

Puoi eseguire tutte queste operazioni utilizzando la seguente query BigQuery. Come per i comandi precedenti, esegui questo codice ovunque tu abbia clonato il repository GitHub. Poiché i dati sono vecchi, la data 12 dicembre 2011 è considerata la data odierna ai fini di questo articolo.

WHERE
  -- Bought in the past 3 months
  DATE_DIFF(DATE('{{ dag_run.conf['predict_end'] }}'), latest_order, DAY) <= 90
  -- Make sure returns are consistent.
  AND (
    (order_qty_articles > 0 and order_Value > 0) OR
    (order_qty_articles < 0 and order_Value < 0)
  )

Questa query esegue due attività. Primo, se il set di dati in uso è grande, la query lo riduce. (Il set di dati funzionante per questa soluzione è piuttosto piccolo, ma questa query può ridurre un set di dati estremamente grande di due ordini di grandezza in pochi secondi.)

In secondo luogo, la query crea un set di dati di base su cui lavorare simile al seguente:

customer_id order_date order_value order_qty_articles
16915 2011-08-04 173,7 6
15349 2011-07-04 107,7 77
14794 2011-03-30 -33,9 -2

Il set di dati ripulito contiene anche il campo order_qty_articles. Questo campo è incluso solo per l'utilizzo dalla rete neurale profonda (DNN) descritta nella prossima sezione.

Definizione degli intervalli di addestramento e target

Per prepararti all'addestramento dei modelli, devi scegliere una data di soglia. Questa data separa gli ordini in due partizioni:

  • Gli ordini precedenti alla data della soglia vengono utilizzati per addestrare il modello.
  • Gli ordini successivi alla data della soglia vengono utilizzati per calcolare il valore target.

Cronologia delle vendite per 4 clienti che mostrano una data di soglia

La libreria Durata include metodi per la pre-elaborazione dei dati. Tuttavia, i set di dati utilizzati per il CLV possono essere molto grandi, il che rende non pratico eseguire la pre-elaborazione dei dati su una singola macchina. L'approccio descritto in questo articolo utilizza le query eseguite direttamente in BigQuery per suddividere gli ordini in due insiemi. ML e i modelli probabilistici usano le stesse query, in modo che entrambi i modelli operino sugli stessi dati.

La data di soglia ottimale potrebbe essere diversa per i modelli ML e per i modelli probabilistici. Puoi aggiornare questo valore della data direttamente nell'istruzione SQL. Pensa alla data di soglia ottimale come a un iperparametro. Puoi trovare il valore più appropriato esplorando i dati ed eseguendo alcuni addestramento di test.

La data di soglia viene utilizzata nella clausola WHERE della query SQL che seleziona i dati di addestramento dalla tabella di dati puliti, come mostrato nell'esempio seguente:

order_date <= DATE('{{ dag_run.conf['threshold_date'] }}')

Aggregazione dei dati

Dopo aver suddiviso i dati in intervalli di addestramento e target, li aggrega per creare funzionalità e target effettivi per ogni cliente. Per i modelli probabilistici, l'aggregazione è limitata ai campi recency, frequenza e monetaria (RFM). Per i modelli DNN, i modelli utilizzano anche le funzionalità RFM, ma possono utilizzare funzionalità aggiuntive per effettuare previsioni migliori.

La seguente query mostra come creare caratteristiche sia per i modelli DNN sia per i modelli probabilistici contemporaneamente:

tf.monetary_dnn,
tf.monetary_btyd,
tf.cnt_orders AS frequency_dnn,
tf.cnt_orders - 1 AS frequency_btyd,
tf.recency,
tf.T,
ROUND(tf.recency/cnt_orders, 2) AS time_between,
ROUND(tf.avg_basket_value, 2) AS avg_basket_value,
ROUND(tf.avg_basket_size, 2) AS avg_basket_size,
tf.cnt_returns,
(CASE
    WHEN tf.cnt_returns > 0 THEN 1
    ELSE 0 END) AS has_returned,

-- Used by BTYD mainly, potentially DNN if clipped improve results
(CASE
    WHEN tf.cnt_orders - 1 > 600 THEN 600
    ELSE tf.cnt_orders - 1 END) AS frequency_btyd_clipped,
(CASE
    WHEN tf.monetary_btyd > 100000 THEN 100000
    ELSE ROUND(tf.monetary_btyd, 2) END) AS monetary_btyd_clipped,
(CASE
    WHEN tt.target_monetary > 100000 THEN 100000
    ELSE ROUND(tt.target_monetary, 2) END) AS target_monetary_clipped,

-- Target calculated for overall period
ROUND(tt.target_monetary, 2) as target_monetary

Nella tabella seguente sono elencate le caratteristiche create dalla query.

Nome funzionalità Description Probabilistica DNN
monetary_dnn La somma dei valori monetari di tutti gli ordini per cliente durante il periodo delle funzionalità. x
monetary_btyd La media dei valori monetari di tutti gli ordini per ciascun cliente durante il periodo delle funzionalità. I modelli probabilistici presumono che il valore del primo ordine sia 0. Questo viene applicato dalla query. x
recency Il tempo che intercorre tra il primo e l'ultimo ordine effettuato da un cliente durante il periodo delle funzionalità. x
frequency_dnn Il numero di ordini effettuati da un cliente durante il periodo delle funzionalità. x
frequency_btyd Il numero di ordini effettuati da un cliente durante il periodo delle funzionalità meno il primo. x
T Il tempo che intercorre tra il primo ordine effettuato da un cliente e la fine del periodo di funzionalità. x x
time_between Il tempo medio tra gli ordini di un cliente durante il periodo delle funzionalità. x
avg_basket_value Il valore monetario medio del carrello del cliente durante il periodo delle funzionalità. x
avg_basket_size Il numero di articoli che il cliente ha in media nel carrello durante il periodo delle funzionalità. x
cnt_returns Il numero di ordini che il cliente ha restituito durante il periodo relativo alle funzionalità. x
has_returned Indica se il cliente ha restituito almeno un ordine durante il periodo delle funzionalità. x
frequency_btyd_clipped Uguale a frequency_btyd, ma troncato per valori anomali. x
monetary_btyd_clipped Uguale a monetary_btyd, ma troncato per valori anomali. x
target_monetary_clipped Uguale a target_monetary, ma troncato per valori anomali. x
target_monetary L'importo totale speso da un cliente, inclusi i periodi di addestramento e target. x

La selezione di queste colonne viene effettuata nel codice. Per i modelli probabilistici, la selezione viene eseguita utilizzando un DataFrame Pandas:

df_ft = pd.read_csv(ft_file)

# Extracts relevant dataframes for RFM:
# - summary has aggregated values before the threshold date
# - actual_df has values of the overall period.
summary = df_ft[['customer_id', 'frequency_btyd', 'recency', 'T',
                 'monetary_btyd']]

Per i modelli DNN, le funzionalità di TensorFlow sono definite nel file context.py. Per questi modelli, le funzionalità seguenti vengono ignorate come funzionalità:

  • customer_id. Si tratta di un valore univoco non utile come elemento.
  • target_monetary. Questo è il target che il modello deve prevedere, quindi non viene utilizzato come input.

Creazione dei set di addestramento, valutazione e test per DNN

Questa sezione riguarda solo i modelli DNN. Per addestrare un modello ML, devi utilizzare tre set di dati non sovrapposti:

  • Il set di dati di addestramento (70-80%) viene utilizzato per apprendere le ponderazioni al fine di ridurre una funzione di perdita. L'addestramento continua fino a quando la funzione di perdita non diminuisce più.

  • Il set di dati di valutazione (10-15%) viene utilizzato durante la fase di addestramento per prevenire l'overfitting, ovvero quando un modello funziona bene con i dati di addestramento, ma non generalizza bene.

  • Il set di dati test (10-15%) deve essere utilizzato una sola volta, al termine dell'addestramento e della valutazione, per eseguire una misura finale delle prestazioni del modello. Questo set di dati non è mai stato rilevato dal modello durante il processo di addestramento, quindi fornisce una misura statisticamente valida dell'accuratezza del modello.

La seguente query crea un set di addestramento con circa il 70% dei dati. La query segreta i dati utilizzando la seguente tecnica:

  • Viene calcolato un hash dell'ID cliente, che produce un numero intero.
  • Un'operazione modulo viene utilizzata per selezionare i valori hash che sono al di sotto di una determinata soglia.
SELECT
  *
FROM
  `{{ dag_run.conf['project'] }}.{{ dag_run.conf['dataset'] }}.features_n_target`
WHERE
  -- TRAIN
  MOD(ABS(FARM_FINGERPRINT(CAST(customer_id AS STRING))), 100000) <= 70000

Lo stesso concetto viene utilizzato per il set di valutazione e i set di test, in cui vengono conservati i dati superiori alla soglia.

Addestramento

Come hai visto nella sezione precedente, puoi utilizzare modelli diversi per provare a prevedere il CLV. Il codice utilizzato in questo articolo è stato pensato per consentirti di decidere quale modello utilizzare. Puoi scegliere il modello utilizzando il parametro model_type che passi al seguente script shell di addestramento. Al resto ci pensa il codice.

estimator = get_estimator(estimator_name=args.model_type,
                          config=config,
                          params=params,
                          model_dir=model_dir)

Il primo obiettivo dell'addestramento è che entrambi i modelli siano in grado di superare un benchmark ingenuo, che definiamo di seguito. Se entrambi i tipi di modelli possono battere questo (e dovrebbero), puoi confrontare il rendimento di ciascun tipo rispetto all'altro.

Benchmarking dei modelli

Ai fini di questa serie, viene definito un benchmark ingenuo utilizzando i seguenti parametri:

  • Valore medio del carrello. Questo valore viene calcolato su tutti gli ordini effettuati prima della data della soglia.
  • Conteggio degli ordini. Questo valore viene calcolato per l'intervallo di addestramento su tutti gli ordini effettuati prima della data della soglia.
  • Moltiplicatore del conteggio. Questo valore viene calcolato in base al rapporto tra il numero di giorni precedenti alla data della soglia e il numero di giorni tra la data della soglia e la data corrente.

Il benchmark presuppone in modo ingenuo che il tasso di acquisti stabilito da un cliente durante l'intervallo di addestramento rimanga costante per l'intervallo target. Pertanto, se un cliente ha effettuato 6 acquisti in 40 giorni, si presume che acquisterà 9 volte in 60 giorni (60/40 * 6 = 9). Moltiplicando il moltiplicatore del conteggio, il conteggio degli ordini e il valore medio del carrello per ciascun cliente, si ottiene un valore target previsto ingenuo per quel cliente.

L'errore di benchmark corrisponde all'errore quadratico medio (RMSE) ovvero la media di tutti i clienti della differenza assoluta tra il valore target previsto e il valore target effettivo. L'RMSE viene calcolato utilizzando la seguente query in BigQuery:

SELECT
  ROUND(SQRT( SUM(POW(predicted_monetary - target_monetary, 2)) / COUNT(1) ), 2) as rmse
FROM (
  SELECT
    tf.customer_id,
    avg_basket_value * ( cnt_orders * (1 + target_days/feature_days) ) AS predicted_monetary,
    ROUND(tt.target_monetary, 2) AS target_monetary

Il benchmark restituisce un RMSE di 3760, come mostrato nei seguenti risultati dell'esecuzione del benchmark. I modelli devono battere questo valore.

Risultati dei benchmark

Modelli probabilistici

Come menzionato nella Parte 1 di questa serie, questa serie utilizza una libreria Python denominata Lifetimes che supporta vari modelli, tra cui la distribuzione binomiale Pareto/negativa (NBD) e i modelli BG/NBD con forme geometriche beta. Il seguente codice campione mostra come utilizzare la libreria Durata per eseguire previsioni sul lifetime value con modelli probabilistici.

paretof = ParetoNBDFitter(penalizer_coef=PENALIZER_COEF)
paretof.fit(summary['frequency'], summary['recency'], summary['T'])
return paretof

Per generare i risultati del CLV utilizzando il modello probabiliistico nel tuo ambiente locale, puoi eseguire il seguente script mltrain.sh. Devi fornire i parametri per le date di inizio e di fine della suddivisione dell'addestramento e per la fine del periodo di previsione.

./mltrain.sh local data --model_type paretonbd_model --threshold_date [YOUR_THRESHOLD_DATE] --predict_end [YOUR_END_DATE]

Modelli DNN

Il codice campione include implementazioni in TensorFlow di DNN utilizzando la classe predefinita dello strumento di stima DNNRegressor, oltre a un modello di stima personalizzato. Lo strumento DNNRegressor e lo strumento per la stima personalizzato utilizzano lo stesso numero di livelli e lo stesso numero di neuroni in ogni livello. Questi valori sono iperparametri che devono essere ottimizzati. Nel seguente file task.py puoi trovare un elenco di alcuni degli iperparametri che sono stati impostati su valori testati manualmente e che hanno fornito buoni risultati.

TRAIN_SIZE = 100000
NUM_EPOCHS = 70
BATCH_SIZE = 5
NUM_EVAL = 20

LEARNING_DECAY_RATE = 0.7
HIDDEN_UNITS = '128 64 32 16'
LEARNING_RATE = 0.00135
L1_REGULARIZATION = 0.0216647
L2_REGULARIZATION = 0.0673949
DROPOUT = 0.899732
SHUFFLE_BUFFER_SIZE = 10000

Se usi AI Platform, puoi utilizzare la funzionalità di ottimizzazione degli iperparametri, che eseguirà il test su una serie di parametri definiti in un file YAML. AI Platform utilizza l'ottimizzazione bayesiana per eseguire ricerche nello spazio degli iperparametri.

Risultati del confronto dei modelli

La seguente tabella mostra i valori RMSE per ciascun modello, addestrati sul set di dati di esempio. Tutti i modelli sono addestrati su dati RFM. I valori RMSE variano leggermente tra un'esecuzione e l'altra a causa dell'inizializzazione di parametri casuali. Il modello DNN utilizza funzionalità aggiuntive, come il valore medio del carrello e il conteggio dei resi.

Modello RMSE (RMSE)
DNN 1.000,00
BG/NBD 1557
Pareto/NBD 1558

I risultati mostrano che in questo set di dati, il modello DNN ottiene prestazioni migliori dei modelli probabilistici quando prevede il valore monetario. Tuttavia, le dimensioni relativamente ridotte del set di dati UCI limitano la validità statistica di questi risultati. Dovresti provare ciascuna delle tecniche sul tuo set di dati per vedere quale garantisce i risultati migliori. Tutti i modelli sono stati addestrati utilizzando gli stessi dati originali (tra cui ID cliente, data e valore dell'ordine) su valori RFM estratti da questi dati. I dati di addestramento DNN includevano alcune funzionalità aggiuntive, come il volume medio del carrello e il numero di resi.

Il modello DNN restituisce solo il valore monetario complessivo del cliente. Se ti interessa prevedere la frequenza o il tasso di abbandono, devi eseguire alcune attività aggiuntive:

  • Prepara i dati in modo diverso per cambiare il target ed eventualmente la data della soglia.
  • Reimposta un modello regressivo per prevedere il target che ti interessa.
  • Ottimizzare gli iperparametri.

Lo scopo era eseguire un confronto sulle stesse caratteristiche di input tra i due tipi di modelli. Un vantaggio dell'utilizzo delle DNN è che potresti migliorare i risultati aggiungendo più funzionalità rispetto a quelle utilizzate in questo esempio. Con i DNN, puoi sfruttare i dati di origini come eventi di clickstream, profili utente o funzionalità di prodotti.

Ringraziamenti

Dua, D. e Karra Taniskidou, E. (2017); Repository di machine learning UCI http://archive.ics.uci.edu/ml. Irvine, CA: University of California, School of Information and Computer Science.

Passaggi successivi