Applicazioni pratiche di machine learning/Segmentazione dei clienti

Caricamento librerie

modifica
 library(gbm)
 library(caTools)
 library(caret)
 library(dplyr)
 library(ggplot2)
 library(corrplot)

Parte 1: Dati

modifica

I seguenti datasets contengono informazioni relativi ai coupons offerti a un gran numero di clienti e consentono di prevedere quali di essi diventeranno fedeli al prodotto in offerta. Supponiamo che venga dato a 100 clienti uno sconto per l'acquisto di due bottiglie d'acqua. Dei 100 clienti, 60 sceglieranno di di utilizzare il coupon. Si vuole prevedere quale dei 60 clienti tornerà (durante o dopo il periodo promozionale) per acquistare lo stesso oggetto di nuovo. Per fare questa previsione, abbiamo lo storico di un anno di acquisti prima dell'incentivo dato al cliente ed inoltre abbiamo anche lo storico degli acquisti di molti altri clienti (alcuni dei quali hanno ricevuto la stessa offerta). La cronologia delle transazioni contiene tutti gli articoli acquistati e non solo quelli correlati all'offerta. Nel dataset ad ogni cliente viene data una sola offerta.

Files:
Ci vengono forniti 3 file relazionali:

  • operations.csv: contiene la cronologia delle transazioni per tutti i clienti per un periodo di almeno 1 anno prima di aver dato loro il coupon
  • trainHistory.csv: contiene dati sul coupon offerto a ciascuno cliente e informazioni sulla sua risposta comportamentale
  • testHistory.csv: contiene dati sul coupon offerto a ciascuno cliente ma non include la sua risposta
  • offers.csv: contiene informazioni sulle offerte (coupons)

Campi:
Tutti i campi sono resi anonimi per proteggere la privacy del cliente e le informazioni sulle vendite.

Trainhistory.csv

  • id: un ID univoco che rappresenta un cliente
  • chain - Un numero intero che rappresenta un'offerta della catena di negozi - Un ID che rappresenta una determinata offerta
  • market: un ID che rappresenta una regione geografica
  • repeattrips: il numero di volte in cui il cliente ha ripetuto l'acquisto
  • repeater - Un valore booleano, uguale a repeattrips> 0
  • offerdate - La data in cui un cliente ha ricevuto l'offerta

transactions.csv

  • id - vedi sopra
  • chain - vedi sopra
  • dept - Un raggruppamento aggregato della categoria (ad es. Acqua)
  • category - La categoria del prodotto (ad es. Acqua gassata)
  • company: un ID dell'azienda che vende l'articolo
  • brand: un ID del marchio a cui appartiene l'articolo
  • date - La data di acquisto
  • productsize - La quantità di prodotto acquistata (ad es. 16 once di acqua)
  • productmeasure - L' unità di misura del prodotto (ad esempio once)
  • purchasequantity: il numero di unità acquistate
  • purchaseamount - L'importo in dollari acquistato

offers.csv

  • offer - vedi sopra
  • category - vedi sopra
  • quantity - Il numero di unità che è necessario acquistare per ottenere lo sconto
  • company - vedi sopra
  • offervalue: il valore in dollari dell'offerta
  • brand: vedi sopra

Il file transazioni.csv occupa circa 21 GB di spazio e quindi per poterlo analizzare, bisogna ridurlo attraverso una funzione in Java, considerando solo gli elementi relativi a selezionati categorie, marchi, aziende questo riduce il file a 76.6MB.

Caricamento dei dati:

 dfTrainHistory <- read.csv("trainHistory.csv")
 dfTestHistory <- read.csv("testHistory.csv")
 dfOffers <- read.csv("offers.csv")
 dfTransactions <-read.csv("transactions_1.csv")
 dfTestHistory <- merge(dfTransactions,dfTestHistory, by =c("id","chain"))
 dfTransactions <- merge(dfTransactions,dfTrainHistory, by =c("id","chain"))

Panoramica dei dati:

 # 1. Rows and colums in transaction merged with history
 dim(dfTransactions)
 ## [1] 465146 16

 # 2. Describe data, columns. Categorical , binary and numerical variables
 str(dfTransactions)

 # 3. Understand the relationship of columns and how they are effecting each other. Check  correlation or Chi-Square.
 # 1. Correlation - shows relataion of Numerical columns
 # 2. Chi-Square - shows relation of Categorical columns
 corrplot(cor(dfTransactions[,c(3,4,5,6,10,11,12,13)]) , method = "number")
 
Non ci sono variabili collineari essendo il coefficiente di correlazione tra le variabili numeriche sempre basso

Pulizia dei dati:

Si cercano eventuali dati mancanti identificati da NA, -1 oppure 999 :

 colSums(is.na(dfTransactions))
 colSums(dfTransactions==-1)
 colSums(dfTransactions==-999)

Non ci sono dati mancanti nelle variabili...

Parte 2: Domanda di ricerca

modifica

Si vuole prevedere quali clienti ritorneranno (durante o dopo il periodo promozionale) per acquistare nuovamente la stessa offerta e quindi quali clienti possono essere considerati “validi clienti" e con quale probabilità ripeteranno l'acquisto.

Parte 3: Modellizzazione

modifica

I dati per costruire il modello sono quelli antecedenti al 01-04-2013 e sono chiamati traning set. Questa data corrispondono al 60% dei dati in base alla variabile offerdate, mentre quelli relativi al periodo successivo costituiscono il validation set.

#### read in training data
 dfTrain <- dfTransactions
 dfTrain$offerdate <- as.Date(dfTrain$offerdate)
 ## split into training and validation set according to offer date
 trainRatio <- 0.6
 thresh <- sort(dfTrain$offerdate)[floor(trainRatio*dim(dfTrain)[1])]
 thresh <- '2013-04-01'
 # indices for training and validation set
 trainInd <- which(dfTrain$offerdate<thresh)
 validInd <- which(dfTrain$offerdate>=thresh)

Si scelgono i predictors cioè le variabili con cui verrà creato il modello e e si sceglie anche la variabile da prevedere 'repeater' che assume il valore 1 se il cliente ripete l'acquisto dell'offerta, o 0 altrimenti. Se il cliente ripete l'acquisto, allora è un valido cliente.

 ###################################
 ## Perform training & validation ##
 #################################### get the names of all predictors
 unused <- c( 'id', 'repeater', 'repeattrips', 'offerdate')
 all.vars <- names(dfTrain)
 # DEL <- grepl('^overall', all.vars)
 # unused <- c(unused, all.vars[DEL])
 predictors <- all.vars[-which(all.vars %in% unused)]
 X_train <- dfTrain[,c(predictors)]
 Y_train <- dfTrain$repeater
 Y <-ifelse(Y_train=="t",1,0)

Per prevedere i clienti validi la libreria gbm adotta l'algoritmo di machine learning gradient stocastic, che modifica in parte l'algoritmo di base.

 gbm_model = gbm(Y[trainInd] ~ dept+ category+company + brand+ purchasequantity + purchaseamount +   offer + market ,
 data=X_train[trainInd,],
 shrinkage = 0.01,
 distribution = "gaussian",
 n.trees = 1000,
 interaction.depth = 5,
 bag.fraction = 0.5,
 train.fraction = 0.8,
 # cv.folds = 5,
 n.cores = -1,
 verbose = T)

Parte 4: Previsione

modifica

Dopo aver ottenuto il modello, è possibile prevedere quali sono i clienti validi calcolando la probabilità di ripetere l'acquisto dell'offerta sia sul training set che sulla validation set calcolando Accuracy, AUC, Precision, Recall. I clienti validi sono considerati coloro che hanno ripeteranno l'acquisto con una probabilità superiori al 65%. Per ottenere una migliore Accuracy, AUC ecc si può migliorare il modello aggiungendo nuovi predictors e/o modificando gli iperparametri nel modello ... DA FARE ...

... nel training set:

 p1 = predict(gbm_model,newdata = X_train[trainInd,], n.trees =1000)
 p <- rep(0,nrow(X_train[trainInd,]))
 p[p1>=0.65]=1
 p <-as.factor(p)
 confusionMatrix(p,as.factor(Y[trainInd]))
## Confusion Matrix and Statistics
Accuracy : 0.8748
##
95% CI : (0.8735, 0.8761)
##
No Information Rate : 0.5836
##
P-Value [Acc > NIR] : < 2.2e-16
Sensitivity : 0.9737
##
Specificity : 0.8042
##
Pos Pred Value : 0.7801
##
Neg Pred Value : 0.9772
##
Prevalence : 0.4164
##
Detection Rate : 0.4054##
 auc <-colAUC(p1, Y_train[trainInd])
 cat('Boosting AUC in training set: ', auc, '\n', sep='')
 ## Boosting AUC in training set: 0.9271135

... nel validation set :

 p1 = predict(gbm_model,newdata = X_train[validInd,], n.trees =1000)
 p <- rep(0,nrow(X_train[validInd,]))
 p[p1>=0.65]=1
 mean(p==Y[validInd])
 ## [1] 0.6371734
 p <-as.factor(p)
 confusionMatrix(p,as.factor(Y[validInd]))
## Confusion Matrix and Statistics
Accuracy : 0.6372
##
95% CI : (0.6352, 0.6392)
##
No Information Rate : 0.5207
##
P-Value [Acc > NIR] : < 2.2e-16
Sensitivity : 0.4143
##
Specificity : 0.8793
##
Pos Pred Value : 0.7885
##
Neg Pred Value : 0.5802##
##
##
 auc<-colAUC(p1, Y_train[validInd])
 cat('Boosting AUC in validation set: ', auc, '\n', sep='')
 ## Boosting AUC in validation set

Parte 5: Conclusione

modifica

Ora è possibile sapere quali sono i clienti validi nel testing set:

 p1 = predict(gbm_model,newdata = dfTestHistory, n.trees = 1000)
 df <- data.frame(idCustomer = dfTestHistory$id,repeatProbability = p1)
 df <-df %>%
 group_by(idCustomer) %>%
 summarise(repeatProbability=mean(repeatProbability),ValuedShopper
 =as.factor(ifelse(repeatProbability>0.65,"Yes","No")))
 
 #first 6 customers with probability to repeat purchase:
 head(df)

 df %>%
 ggplot(aes(idCustomer,repeatProbability, colour= ValuedShopper)) + 
 geom_point() +
 ggtitle("Valued Shoppers a probability of more ", subtitle="than 65% to repeat the purchase of offers")
 
Validi clienti in celeste aventi una probabilità superiore al 65% di ripetere l'acquisto