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
modificaI 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")
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
modificaSi 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
modificaI 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
modificaDopo 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
modificaOra è 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")