Churn Prediction in Python con analisi del sentiment con NLTK

banner

Nel campo della data science, ci sono molte applicazioni pratiche che possono aiutare le aziende a migliorare la loro strategia di business. Una di queste applicazioni è quella che si chiama “churn prediction”, ovvero la previsione dei clienti che potrebbero abbandonare un servizio o prodotto.

Intro

La predizione di “abbandono” è una delle strategie più importanti per le aziende che desiderano mantenere una base di clienti fedeli e ridurre i costi associati all’acquisizione di nuovi clienti. Utilizzare l’analisi del sentiment per prevedere il churn può essere particolarmente efficace, poiché consente di comprendere meglio le emozioni e le opinioni dei clienti nei confronti del servizio o prodotto offerto. In questo tutorial, esploreremo come utilizzare Python per eseguire una predizione di churn basata sull’analisi del sentiment.

Passaggi per la predizione del churn con Python e NLTK

Requisiti

Assicurati di avere installato le seguenti librerie Python:

  • pandas
  • numpy
  • nltk
  • pycaret
  • ydata-profiling

Tieni conto che nel caso di pycaret e ydata-profiling, la compatibilità con la versione di Python in uso potrebbe essere limitata. Si consiglia di utilizzare Python 3.8 o 3.11 al massimo per evitare problemi di compatibilità.

Passo 1: Import delle librerie

Per iniziare, è necessario importare tutte le librerie Python necessarie per l’analisi dei dati e la predizione del churn. Queste librerie includono pandas per la manipolazione dei dati, numpy per le operazioni numeriche, nltk per l’analisi del sentiment e pycaret per la creazione e la valutazione dei modelli di classificazione.

import pandas as pd
import numpy as np
from ydata_profiling import ProfileReport
from pycaret.classification import *
import matplotlib.pyplot as plt
import random
import nltk
from nltk.sentiment.vader import SentimentIntensityAnalyzer

Passo 2: Download del lexicon NLTK

Per utilizzare l’analisi del sentiment con NLTK, è necessario scaricare il lexicon VADER, che è uno strumento popolare per l’analisi del sentiment dei testi in inglese. Il lexicon, in altre parole, è un insieme di parole con punteggi di sentiment associati. VADER è quello più adatto per l’analisi del sentiment in contesti sociali e di recensioni, ma ne esistono altri per altre lingue e contesti, come TextBlob, SentiWordNet, ecc.

nltk.download('vader_lexicon')

Come funziona VADER, e cos’è: parliamo di un modello pre-addestrato di analisi del sentiment basato su regole che utilizza un dizionario di parole con punteggi di sentiment associati. VADER è progettato per essere efficace nell’analisi del sentiment in contesti sociali e di recensioni, ed è particolarmente utile per testi brevi come tweet, commenti sui social media e recensioni di prodotti. Funziona grazie a un insieme di regole che tengono conto dell’analisi sintattica e semantica della lingua, come l’uso di punteggiatura, emoticon e intensificatori (ad esempio, “molto”, “estremamente”) per calcolare un punteggio di sentiment complessivo per un dato testo.

Passo 3: Generazione di dati sintetici

Poiché non sempre si dispone di dati reali, possiamo generare dati sintetici per testare il nostro modello. Questi dati includono informazioni come il numero di interazioni, il tempo trascorso, il numero di sessioni, i giorni dall’ultimo accesso e il feedback dei clienti. Teniamo presente che, se abbiamo a disposizione un dataset reale, possiamo saltare questo passaggio e caricare direttamente i dati.

def generate_synthetic_churn_data(n_users=1000):
    np.random.seed(42)
    random.seed(42)

    user_ids = [f"user_{i}" for i in range(n_users)]
    interactions = np.random.poisson(5, n_users)
    time_spent = np.random.normal(loc=50, scale=10, size=n_users)
    number_of_sessions = np.random.poisson(3, n_users)
    days_since_last_login = np.random.randint(0, 30, n_users)
    avg_interactions_per_session = interactions / np.maximum(1, number_of_sessions)
    feedback = []
    churned = []
    for i in range(n_users):
        if time_spent[i] > 60:
            feedback.append("positive")
            churned.append("no")
        elif days_since_last_login[i] > 20 and number_of_sessions[i] < 2:
            feedback.append("negative")
            churned.append("yes")
        else:
            feedback.append("neutral")
            churned.append(np.random.choice(["yes", "no"], p=[0.8, 0.2]))

    synthetic_data = pd.DataFrame({
        "user_id": user_ids,
        "interactions": interactions,
        "time_spent": time_spent,
        "number_of_sessions": number_of_sessions,
        "days_since_last_login": days_since_last_login,
        "avg_interactions_per_session": avg_interactions_per_session,
        "feedback": feedback,
        "churned": churned
    })
    return synthetic_data

All’interno di questo passaggio, andiamo infatti a definire una funzione che genera un DataFrame con dati sintetici per 1000 utenti, includendo variabili che potrebbero influenzare il churn, come ad esempio il numero di interazioni e il feedback nel contesto di utilizzo di un servizio. Per questa ragione, nella generazione di questo dataset sono state incluse variabili come il numero di sessioni e il tempo trascorso, che possono essere utili per la predizione del churn. Per dare una “spinta” al dataset, nel caso della generazione del feedback e del churn, sono state definite delle regole basate su alcune condizioni (ad esempio, se il tempo trascorso è superiore a 60 minuti, il feedback è positivo e il churn è “no”). Sono del tutto arbitrarie, ma servono a creare una relazione tra le variabili che possa essere utile per il modello di predizione e a renderlo più realistico.


> La cosa importante in questo passaggio è l'avere a disposizione un dataset, in formato .csv o simili, che contenga le informazioni necessarie per la predizione del churn. Se si dispone di un dataset reale, è possibile caricarlo direttamente utilizzando `pd.read_csv()` o altre funzioni di caricamento dei dati. 

Non esiste un numero giusto o sbagliato di variabili da includere nel dataset, ma è importante che queste variabili siano rilevanti per il contesto di utilizzo del servizio o prodotto. L'unico fattore da considerare, per questo progetto, è che all'interno del dataset sia presente l'informazione relativa al feedback dei clienti, in modo da poter eseguire l'analisi del sentiment, e l'informazione relativa al churn (se il cliente ha abbandonato o meno il servizio). Tieniamo ancore presente che, in un contesto reale, il dataset potrebbe essere molto più complesso e includere molte più variabili, e quello generato potrebbe dare risultati non del tutto realistici.

### Passo 4: Analisi del sentiment

Siamo al clue del progetto: adesso dobbiamo utilizzare i nostri dati per analizzare il sentiment del feedback. Come anticipato, utilizziamo VADER per calcolare il punteggio del sentiment per ogni feedback ricevuto. Questo punteggio ci aiuta a comprendere se il feedback è positivo, neutrale o negativo.

```python
sid = SentimentIntensityAnalyzer()
synthetic_data["sentiment"] = synthetic_data["feedback"].apply(lambda x: sid.polarity_scores(x)["compound"])

# Codifica dei dati per la predizione
synthetic_data_encoded = synthetic_data.drop(columns=['user_id'])
synthetic_data_encoded = pd.get_dummies(synthetic_data_encoded, columns=["feedback"], drop_first=True)

Come visto, per farlo, utilizziamo la funzione polarity_scores di VADER per calcolare il punteggio del sentiment per ogni feedback. Il punteggio restituito è un valore compreso tra -1 (molto negativo) e 1 (molto positivo). Inoltre, aggiungiamo questo punteggio come una nuova colonna nel nostro DataFrame, così da poterlo utilizzare successivamente per la predizione del churn. L’oggetto SentimentIntensityAnalyzer() viene utilizzato per creare un’istanza dell’analizzatore di sentiment VADER, che viene poi utilizzata per calcolare i punteggi di sentiment per ogni feedback nel dataset.

Passo 5: Generazione di un report di esplorazione dei dati (EDA)

Quando si studiano i dati, è sempre una buona pratica eseguire un’analisi esplorativa dei dati per comprendere meglio le caratteristiche del dataset. Nel contesto della data science, si tratta di un passaggio fondamentale per identificare eventuali problemi nei dati, come valori mancanti o anomalie, e per comprendere le relazioni tra le variabili.

Per comprendere meglio i nostri dati, generiamo un report EDA che include statistiche descrittive e visualizzazioni dei dati.

profile = ProfileReport(synthetic_data_encoded, title="Synthetic Data EDA Report", explorative=True)
profile.to_file("synthetic_data_eda_report.html")
print("EDA report has been generated and saved as 'synthetic_data_eda_report.html'.")

Per farlo, abbiamo usato la libreria ydata_profiling, che consente di generare report EDA in modo semplice e veloce. Il report viene salvato come file HTML, che può essere aperto in un browser per una visualizzazione interattiva.

Passo 6: Test del modello di predizione del churn

A questo punto, configuriamo e confrontiamo diversi modelli di classificazione per trovare il migliore per prevedere il churn. Utilizziamo la libreria pycaret per semplificare il processo, dal momento che consente di eseguire rapidamente il setup dei dati, confrontare i modelli e valutarne le prestazioni.

synthetic_data_encoded["churned"] = synthetic_data_encoded["churned"].astype(str)

clf = setup(data=synthetic_data_encoded, target="churned", session_id=42, normalize=True, 
            transformation=True, remove_outliers=True, fix_imbalance=True, html=False, verbose=False, use_gpu=False)

best_model = compare_models(sort="F1")

Vediamo passo passo cosa fa questo codice:

  1. Convertiamo la colonna “churned” in stringa per assicurarci che sia trattata come una variabile categorica, così che sia più facile per i modelli di classificazione lavorarci.
  2. Configuriamo l’ambiente di pycaret utilizzando la funzione setup, specificando il dataset, la variabile target e alcune opzioni per la normalizzazione, la trasformazione dei dati, la rimozione degli outlier e il bilanciamento delle classi.
  3. Confrontiamo diversi modelli di classificazione utilizzando la funzione compare_models della libreria pycaret, ordinandoli in base al punteggio F1, che è una metrica importante per valutare le prestazioni dei modelli di classificazione, soprattutto in presenza di classi sbilanciate.

Infine, valutiamo le prestazioni del modello migliore utilizzando metriche come precisione, recall e F1-score, sempre utilizzando le funzionalità di pycaret.

evaluate_model(best_model)

Passo 7: Predizione del churn

Ora che abbiamo selezionato il modello migliore, possiamo utilizzarlo per fare predizioni sul churn. Usiamo la funzione predict_model di pycaret per ottenere le predizioni sul nostro dataset.

predictions = predict_model(best_model, data=synthetic_data_encoded)
print(predictions[['Label', 'Score']].head(10))  # Visualizza le prime 10 predizioni

Immaginiamo quindi di avere un dataset di nuovi clienti per i quali vogliamo prevedere il churn. Possiamo utilizzare lo stesso modello per fare predizioni su questi nuovi dati.

new_customers = ... # Caricamento o generazione di nuovi dati dei clienti
new_customers["sentiment"] = new_customers["feedback"].apply(lambda x: sid.polarity_scores(x)["compound"])
new_customers_encoded = new_customers.drop(columns=['user_id'])
new_customers_encoded = pd.get_dummies(new_customers_encoded, columns=["feedback"], drop_first=True)
new_predictions = predict_model(best_model, data=new_customers_encoded)
print(new_predictions[['Label', 'Score']].head(10))  # Visualizza le
# prime 10 predizioni per i nuovi clienti

Passo 8: Engagement dei clienti (opzionale)

Ora che abbiamo preparato un modello per avere un’idea dei clienti che potrebbero abbandonare il servizio, creiamo messaggi personalizzati in base al loro feedback e al punteggio del sentiment. Possiamo quindi utilizzare una funzione come la seguente che, sulla base del feedback, del sentiment, del numero di interazioni e dei giorni dall’ultimo accesso, genera un messaggio di ri-coinvolgimento personalizzato per ogni cliente che ha abbandonato il servizio.

def create_reengagement_message(feedback, sentiment_score, interactions, days_since_last_login):
    if sentiment_score  0.5:
        return "Ti manchiamo! Torna e continua da dove hai lasciato con le funzionalità che ami."
    elif interactions  7:
        return "Sembra che tu stia perdendo qualcosa! Entra ora per reclamare un bonus speciale."
    else:
        return "Stiamo costantemente migliorando. Torna e dai un'altra possibilità!"

# Applicazione della funzione di messaggio di ri-coinvolgimento ai clienti che hanno abbandonato
synthetic_data["reengagement_message"] = synthetic_data.apply(
    lambda x: create_reengagement_message(
        x["feedback"], x["sentiment"], x["interactions"], x["days_since_last_login"]
    ) if x["churned"] == "yes" else None,
    axis=1
)

# Visualizzazione di alcuni clienti che hanno abbandonato con i loro messaggi di ri-coinvolgimento
churned_users = synthetic_data[synthetic_data['churned'] == "yes"][['feedback', 'sentiment', 'reengagement_message']]
print(churned_users.head(10))

Conclusioni

La predizione del churn è un aspetto cruciale per le aziende che desiderano mantenere una base di clienti fedeli e ridurre i costi associati all’acquisizione di nuovi clienti. Utilizzare l’analisi del sentiment per comprendere meglio le opinioni dei clienti può aiutare a creare strategie di ri-coinvolgimento più efficaci. Questo tutorial ha mostrato come utilizzare Python e nltk per generare dati sintetici, eseguire l’analisi del sentiment e creare un modello di predizione del churn. Inoltre, ha illustrato come creare messaggi personalizzati per ri-coinvolgere i clienti che hanno abbandonato. Queste strategie possono essere adattate e migliorate ulteriormente in base alle esigenze specifiche del tuo business.

Post correlati

TheRedCode.it - Il mondo #tech a piccoli #bit

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source
Logo di NgRome
Logo de La Locanda del Tech
Logo di Tomorrow Devs
Logo di DevDojo

Vuoi diventare #tech content creator? 🖊️

Se vuoi raccontare la tua sul mondo #tech con dei post a tema o vuoi condividere la tua esperienza con la community, sei nel posto giusto! 😉

Manda una mail a collaborazioni[at]theredcode.it con la tua proposta e diventa la prossima penna del blog!

Ma sì, facciamolo!