Applicazioni pratiche di machine learning/Approvazione carte di credito

Indice del libro

Caricamento librerieModifica

 library(dplyr)
 library(caret)
 library(h2o)

Parte 1 : DatiModifica

Una banca per decidere se emettere una carta di credito ad un cliente può valutare l'entità del rischio utilizzando un algoritmo di machine learning . I datasets credit_record.csv e application_record.csv scaricabili da qui : https://www.kaggle.com/rikdifos/credit-card-approval-prediction possono essere utilizzati per prevedere se un candidato è un cliente "buono" o "cattivo" al fine di ricevere la carta di credito.

I dati relativi al cliente sono contenuti in application_record.csv :

  • ID: numero identificativo cliente
  • CODE_GENDER: Sesso
  • FLAG_OWN_CAR: Ha una macchina
  • FLAG_OWN_REALTY: Ha proprietà
  • CNT_CHILDREN: Numero di bambini
  • AMT_INCOME_TOTAL: Reddito annuo
  • NAME_INCOME_TYPE: Tipo di reddito
  • NAME_EDUCATION_TYPE: Livello di istruzione
  • NAME_FAMILY_STATUS: Stato civile
  • NAME_HOUSING_TYPE: Stile di vita
  • DAYS_BIRTH: Numero di giorni indietro fino al compleanno (0), -1 significa ieri
  • DAYS_EMPLOYED: Numero di giorni indietro fino alla data di inizio del rapporto di lavoro .Giorno corrente = 0. Se il numero è positivo, indica la persona attualmente disoccupata viceversa se negativo indica che la persona è occupata.
  • FLAG_MOBIL: Ha un telefono cellulare
  • FLAG_WORK_PHONE: Ha un proprio telefono a lavoro
  • FLAG_PHONE: Ha un telefono fisso
  • FLAG_EMAIL: Ha un'e-mail
  • OCCUPATION_TYPE: Tipo di lavoro
  • CNT_FAM_MEMBERS: Dimensione della famiglia

Il dataset credit_record.csv contiene dati relativi a prestiti e crediti fatti al cliente:

  • ID: numero identificativo cliente
  • MONTHS_BALANCE: Numero di mesi all'indietro rispetto al mese corrente che è 0 , -1 è il mese precedente e così via ...
  • STATUS:
    • 0: da 1-29 giorni in ritardo nel pagamento
    • 1: da 30-59 giorni in ritardo nel pagamento
    • 2: da 60-89 giorni in ritardo nel pagamento
    • 3: da 90-119 giorni in ritardo nel pagamento
    • 4: da 120-149 giorni in ritardo nel pagamento
    • 5: Crediti scaduti o inesigibili, cancellazioni per più di 150 giorni
    • C: pagato quel mese
    • X: Nessun prestito per il mese

Caricamento dati::

credit_record <- read.csv("credit_record.csv")
application_record <- read.csv("application_record.csv")

#Eliminazione records duplicati:
application_record <- unique(application_record, by="ID")

Si stabilisce che chi non paga un credito da più di 60 giorni non è un buon cliente e non merita la carta di credito , per cui (target=1). Invece chi è in ritardo nel pagamento da meno di 60 giorni è un buon cliente e merita la carta di credito (target=0):


# Si crea una nuova variabile target e la si aggiunge al dataset credit_record :

n<-nrow(credit_record)
target <- rep(NA,n)

target[which(credit_record$STATUS=="2")]<- 1
target[which(credit_record$STATUS=="3")]<- 1
target[which(credit_record$STATUS=="4")]<- 1
target[which(credit_record$STATUS=="5")]<- 1
target[which(credit_record$STATUS=="1")]<- 0
target[which(credit_record$STATUS=="0")]<- 0
target[which(credit_record$STATUS=="C")]<- 0
target[which(credit_record$STATUS=="X")]<- 0

credit_record <- cbind(credit_record,target)


Si uniscono i due datasets in un unico dataset df:

df <- merge(application_record,credit_record, by.x = "ID")
df$target <- as.factor(df$target)

Non ci sono valori mancanti nel dataset df :

colSums(is.na(df))

ModellizzazioneModifica

A partire dal dataset df si creano 2 datasets training e testing, il primo contenente il 70% dei records in modo casuale su cui verrà addestrato il modello e il secondo contenente il restante 30% su cui verrà testato il modello :


trainIndex <- createDataPartition(df$target,p=0.7, list = FALSE)
training <- df[trainIndex,]
testing <- df[-trainIndex,]


Si utilizza la libreria h2o per cercare automaticamente per 300 secondi un algoritmo di machine learning idoneo per prevedere con una buona accuratezza la variabile target:

h2o.init()


H2O is not running yet, starting it now...
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu120.04, mixed mode, sharing)
Starting H2O JVM and connecting: .... Connection successful!
R is connected to the H2O cluster: 
   H2O cluster uptime:         5 seconds 862 milliseconds 
   H2O cluster timezone:       Europe/Rome 
   H2O data parsing timezone:  UTC 
   H2O cluster version:        3.28.0.2 
   H2O cluster version age:    8 months and 13 days !!! 
   H2O cluster name:           H2O_started_from_R_gian_kyb058 
   H2O cluster total nodes:    1 
   H2O cluster total memory:   1.92 GB 
   H2O cluster total cores:    2 
   H2O cluster allowed cores:  2 
   H2O cluster healthy:        TRUE 
   H2O Connection ip:          localhost 
   H2O Connection port:        54321 
   H2O Connection proxy:       NA 
   H2O Internal Security:      FALSE 
   H2O API Extensions:         Amazon S3, XGBoost, Algos, AutoML, Core V3, TargetEncoder, Core V4 
   R Version:                  R version 3.6.3 (2020-02-29) 


df_hf <- as.h2o(training)
y <- "target"
x <- names(training)[2:18]

aml <- h2o.automl(x = x, y = y,
                  training_frame = df_hf,
                  max_runtime_secs = 300)

Come algoritmo viene trovato XGBoost


lb <- aml@leaderboard
lb
1	XGBoost_1_AutoML_20201003_190717	


Il modello trovato si prova sul dataset di testing...


test <- as.h2o(testing)
model <- aml@leader
p1 = h2o.predict(model, newdata=test)

Si calcola l'accuratezza che è del 99,53% sul testing set:

df2 <- as.data.frame(p1$predict)

mean(df2$predict==testing$target)
[1] 0.9953368

Si costruisce la matrice di confusione e si trova l'accuratezza del 99,53% con una specificity del 34,55% che indica la possibilità di trovare molti falsi positivi sebbene il modello sia molto accurato:

confusionMatrix(df2$predict,testing$target)
Confusion Matrix and Statistics
         Reference
Prediction      0      1
        0 231933    555
        1    533    293
                                         
              Accuracy : 0.9953          
                95% CI : (0.9951, 0.9956)
   No Information Rate : 0.9964          
   P-Value [Acc > NIR] : 1.0000          
                                         
                 Kappa : 0.3477          
                                         
Mcnemar's Test P-Value : 0.5243          
                                         
           Sensitivity : 0.9977          
           Specificity : 0.3455          
        Pos Pred Value : 0.9976          
        Neg Pred Value : 0.3547          
            Prevalence : 0.9964          
        Detection Rate : 0.9941          
  Detection Prevalence : 0.9965          
     Balanced Accuracy : 0.6716          
                                         
      'Positive' Class : 0

Controversie sull'uso del modelloModifica

Con questo modello una persona povera, proveniente da un quartiere disagiato rischia di non avere la carta di credito o di averla con un credito basso e tassi di interesse più elevati.[1]

  1. Cathy O'Neil, Armi di distruzione matematica, Saggi Bompiani.