Applicazioni pratiche di machine learning/Previsioni su direct mail

Caricamento librerie

modifica
 library(data.table)
 library(readr)
 library(dplyr)
 library(hashmap)
 library(xgboost)
 library(ggplot2)
 library(caTools)
 library(caret)

Parte 1: Dati

modifica

I dati dell'azienda in questione riguardano prestiti personali ai propri clienti, che è proprio l'attività di cui si occupa l'azienda. Le direct mail rappresentano una modalità fondamentale con cui il team aziendale si connettette con i propri clienti, che potrebbero aver bisogno di un prestito.

Le direct mail sono una parte fondamentale della strategia di marketing dell'azienda. Per ottenere migliori risultati, l'azienda deve essere sicura di concentrarsi sui clienti che probabilmente risponderanno e che siano buoni candidati per i loro servizi.

Utilizzando una vasta gamma di variabili anonime, l'azienda vuole prevedere quali clienti risponderanno a un'offerta inviata tramite direct mail.

Abbiamo un set di dati con informazioni anonime dei clienti. Ogni riga corrisponde a un cliente. La variabile di risposta è binaria ed è etichettata come "target". Si vuole prevedere la variabile target per ogni riga del testing set.

Le variabili sono state rese anonime per proteggere la privacy e sono di tipo continuo e categoriale.

Caricamento dei dati:

 cat("sampling train to get around 8GB memory limitations\n")

 train <- read_csv("train.csv", n_max=40000)
 test <- read_csv("test.csv")

Panoramica dei dati:

 #    1. numero di righe e colonne in train and test datasets

 dim(train)
 dim(test)
[1] 40000  1934
[1] 145232   1933
#    2. Do un'occhiata alla cima e alla coda dei dati di training 
 head(train)
 tail(train)
    ID VAR_0001 VAR_0002 VAR_0003 VAR_0004 VAR_0005 VAR_0006 VAR_0007 VAR_0008
 <dbl> <chr>       <dbl>    <dbl>    <dbl> <chr>       <dbl>    <dbl> <lgl>   
1     2 H             224        0     4300 C               0        0 FALSE   
2     4 H               7       53     4448 B               1        0 FALSE   
3     5 H             116        3     3464 C               0        0 FALSE   
4     7 H             240      300     3200 C               0        0 FALSE   
5     8 R              72      261     2000 N               0        0 FALSE   
6    14 R               4        4     4422 C               0        0 FALSE  
...

Pulizia dei dati:

 cat("sostituisco valori mancanti con -1\n")
 train[is.na(train)] <- -1
 for (i in 1:ncol(test)) {
   test[which(is.na(test[,i])),i]<- -1
 }

Rimuovo le variabili costanti:

 v<-c()
 for (i in 1:ncol(train)) {
  if(uniqueN(train[,i])==1){
    col<-names(train[,i])
    v<-c(v,col)
  }
 }
 print(v)
 train = train[, !names(train) %in% v]
 test = test[, !names(test) %in% v]

Rimuovo le variabili duplicate:

 map <-hashmap("0","0")
 cols <- names(train)
 for (i in 2:(ncol(train)-1)) {
  c1 <- cols[i]
  for (j in (i+1):(ncol(train)-1)) {
    if (j-1==i) cat(i,"-",j,"\n")
    
    c2 <- cols[j]
    
    if(!(c2 %in% map$keys()) & mean(train[,i]==train[,j])==1)
      {
      map<nowiki>[[c2]]</nowiki> <- c1
     
      }
      
  }
  
 }
 train = train[, !names(train) %in% map$keys()]
 test = test[, !names(test) %in% dup_cols]

Parte 2: Domanda di ricerca

modifica

Utilizzando una vasta gamma di variabili anonime, si vuole prevedere quali clienti risponderanno a un'offerta in direct mail.

Ci viene fornito un dataset "train" di grande dimensione con informazioni anonime dei clienti. Ogni riga è relativa ad un cliente. La variabile da predire è binaria ed è etichettata come "target". "target" assume il valore 1 se il cliente risponde alla direct mail,0 altrimenti. Si vuole prevedere la variabile target per ogni riga del testing set.

Parte 3: Modellizzazione

modifica
 feature.names <- names(train)[2:ncol(train)-1]
 cat("trasformo le variabile categoriche in numeriche\n")
 for (f in feature.names) {
  if (class(train<nowiki>[[f]]</nowiki>)=="character") {
    levels <- unique(c(train<nowiki>[[f]]</nowiki>, test<nowiki>[[f]]</nowiki>))
    train<nowiki>[[f]]</nowiki> <- as.integer(factor(train<nowiki>[[f]]</nowiki>, levels=levels))
    test<nowiki>[[f]]</nowiki>  <- as.integer(factor(test<nowiki>[[f]]</nowiki>,  levels=levels))
  }
 }

 cat("Per creare il modello si utilizza l'algoritmo di Boosting xgboost\n")
 clf <- xgboost(data        = data.matrix(train[,feature.names]),
               label       = train$target,
               nrounds     = 20,
               objective   = "binary:logistic",
               eval_metric = "auc")

Parte 4: Previsione

modifica

Dopo aver ottenuto il modello, è possibile prevedere i clienti valisi calcolando la probabilità che essi rispondano alla direct mail e misurando Accuracy, AUC, Precision, Recall. Vengono considerati clienti validi, quelli che risponderanno alla direct mail oltrepassando il 70% di probabilità.

 p1 = predict(clf, data.matrix(train[,feature.names]))
 p <- rep(0,nrow(train))
 p[p1>=0.7]=1
 p <-as.factor(p)
 confusionMatrix(p,as.factor(train$target))
 auc <-colAUC(p1, train$target)
 cat('Boosting AUC in training set: ', auc, '\n', sep='')
 

Ora è possibile sapere quale sarà la probabilità di rispondere alle direct mail da parte di clienti contenuti nel testing set

 cat("making predictions in batches due to 8GB memory limitation\n")
 submission <- data.frame(ID=test$ID)
 submission$target <- NA 
 for (rows in split(1:nrow(test), ceiling((1:nrow(test))/10000))) {
    submission[rows, "target"] <- predict(clf, data.matrix(test[rows,feature.names]))
 }

 df <-submission %>%
  group_by(ID) %>%
  summarise(target,ValuedCustomer=as.factor(ifelse(target>0.7,"Yes","No"))) 

 head(df)

 df %>%
  ggplot(aes(ID,target, colour= ValuedCustomer)) +  geom_point() +
  ggtitle("Valued Customers with a probability of more ", subtitle = "than 70% to respond to  direct mail")