Il dataset utilizzato per questa analisi provienente dall’ UCI Machine Learning Repository rappresenta il risultato di una campagna di marketing effettuata da un istituto bancario portoghese e riporta il dettaglio degli utenti che hanno sottoscritto o meno un deposito a termine. Lo scopo del progetto è portare avanti un’analisi statistica monovariata e bivariata sulle variabili coinvolte, ed implementare un modello di regressione logistica per predire se un utente sottoscriverà o meno un deposito.
Secondo le definizioni fornite, il dataset contiene 17 variabili con le seguenti informazioni:
Informazioni sul cliente:
age: età del cliente (numeric)
job: tipo di lavoro (categorical: ‘admin.’, ‘blue-collar’, ‘entrepreneur’, ‘housemaid’, ‘management’, ‘retired’, ‘self-employed’, ‘services’, ‘student’, ‘technician’, ‘unemployed’, ‘unknown’)
marital: stato civile (categorical: ‘divorced’, ‘married’, ‘single’, ‘unknown’; note: ‘divorced’ means divorced or widowed)
education: (categorical: ‘unknown’, ‘primary’, ‘secondary’, ‘tertiary’)
default: ha il credito in default? (categorical: ‘no’, ‘yes’, ‘unknown’)
balance: bilancio annulae medio, in euro (numeric)
housing: ha un mutuo? (categorical: ‘no’, ‘yes’, ‘unknown’)
loan: ha un prestito personale? (categorical: ‘no’,‘yes’,‘unknown’)
Informazioni sull’ultimo contatto durante la campagna marketing:
contact: tipologia di contatto (categorical: “unknown”, “telephone”, “cellular”)
day: giorno dell’ultimo contatto (numeric)
month: mese dell’ultimo contatto (categorical: “jan”, “feb”, “mar”, …, “nov”, “dec”)
duration: durata dell’ultimo contatto, in secondi (numeric)
Altri attributi:
campaign: numero di contatti avuti con il cliente durante la campagna (numeric, includes last contact)
pdays: numero di giorni trascorsi da quando il cliente era stato contattato per una precedente campagna marketing (numeric, -1 significa che il cliente non era mai stato contattato in precedenza)
previous: numero di contatti avuti con il cliente prima dell’attuale campagna marketing (numeric)
poutcome: risultato della precedente campagna di marketing (categorical: “unknown”, “other”, “failure”, “success”)
Variabile target:
#Struttura del dataset
str(bank)
## 'data.frame': 4521 obs. of 17 variables:
## $ age : int 30 33 35 30 59 35 36 39 41 43 ...
## $ job : chr "unemployed" "services" "management" "management" ...
## $ marital : chr "married" "married" "single" "married" ...
## $ education: chr "primary" "secondary" "tertiary" "tertiary" ...
## $ default : chr "no" "no" "no" "no" ...
## $ balance : int 1787 4789 1350 1476 0 747 307 147 221 -88 ...
## $ housing : chr "no" "yes" "yes" "yes" ...
## $ loan : chr "no" "yes" "no" "yes" ...
## $ contact : chr "cellular" "cellular" "cellular" "unknown" ...
## $ day : int 19 11 16 3 5 23 14 6 14 17 ...
## $ month : chr "oct" "may" "apr" "jun" ...
## $ duration : int 79 220 185 199 226 141 341 151 57 313 ...
## $ campaign : int 1 1 1 4 1 2 1 2 2 1 ...
## $ pdays : int -1 339 330 -1 -1 176 330 -1 -1 147 ...
## $ previous : int 0 4 1 0 0 3 2 0 0 2 ...
## $ poutcome : chr "unknown" "failure" "failure" "unknown" ...
## $ y : chr "no" "no" "no" "no" ...
#Conteggio degli NAs per ciascun attributo
sapply(bank, function(x) sum(is.na(x)))
## age job marital education default balance housing loan
## 0 0 0 0 0 0 0 0
## contact day month duration campaign pdays previous poutcome
## 0 0 0 0 0 0 0 0
## y
## 0
Da una primissima panoramica sui dati, si evince quanto segue:
Per l’analisi univariata vengono utilizzati dei bar chart per la visualizzazione delle variabili categoriche e degli istogrammi e boxplot per la visualizzazione delle variabili numeriche. Per le variabili categoriche, il grafico mostra le categorie sull’asse delle X e la frequenza/count sull’asse delle Y ed è utile quindi per mostrare il numero di osservazioni per categorie. Per le variabili numeriche, dopo una prima sommarizzazione dove vengono mostrati i valori dei principali indici di centralità, dispersione e forma, il grafico mostra, per ciascuna variabile, l’istogramma ed il boxplot. Infatti, mentre l’istogramma è utile per comprendere la forma e la distribuzione dei dati, il boxplot dà informazioni sul range degli attributi e aiuta ad identificare eventuali outliers.
Prima di procedere all’analisi vera e propria si eseguono alcune trasformazioni sui dati. Ci sono 4 variabili categoriche (“default”, “housing”, “loan” e il target “y”) che hanno la stessa tipologia di risposta binaria (“yes” o “no”). Per evitare confusione con la variabile target durante la fase di data analysis/visualization, i valori di queste variabili sono stati ricodificati come segue:
##
## admin. blue-collar entrepreneur housemaid management
## 478 946 168 112 969
## retired self-employed services student technician
## 230 183 417 84 768
## unemployed unknown
## 128 38
##
## admin. blue-collar entrepreneur housemaid management
## 10.57 20.92 3.72 2.48 21.43
## retired self-employed services student technician
## 5.09 4.05 9.22 1.86 16.99
## unemployed unknown
## 2.83 0.84
Si nota che circa il 60% dei tipi di lavoro nel dataset appartengono a 3 sole categorie (management, blue-collar, technician). Tipologie di lavoro con poche osservazioni potrebbero limitare il potere predittivo di questa variabile. In seguito, prima di costruire il modello di regressione, saranno accorpate tra loro più categorie simili (es. self-employed e entrepreneur) di modo da ridurre i livelli associati a questa variabile.
##
## divorced married single
## 528 2797 1196
##
## divorced married single
## 11.68 61.87 26.45
La distribuzione di questa variabile è relativamente bilanciata tra i “married” ed i “single” (single+divorced). In seguito verranno accorpati single e divorced in un unico livello per un miglior bilanciamento.
##
## primary secondary tertiary unknown
## 678 2306 1350 187
##
## primary secondary tertiary unknown
## 15.00 51.01 29.86 4.14
Più del 50% degli individui possiede un’educazione secondaria (diploma). C’è una piccola percentuale con un livello di educazione sconosciuto che probabilmente non sarà significativa nel modello predittivo.
##
## defaulter no defaulter
## 76 4445
##
## defaulter no defaulter
## 1.68 98.32
C’è una percentuale molto bassa di persone che risultano inadempienti nei pagamenti, per cui questa variabile non sembra molto utile per l’analisi predittiva.
##
## housing loan no housing loan
## 2559 1962
##
## housing loan no housing loan
## 56.6 43.4
C’è una distribuzione quasi omogenea tra chi ha sottoscritto un mutuo e chi no.
##
## no personal loan personal loan
## 3830 691
##
## no personal loan personal loan
## 84.72 15.28
Più dell’80% dei rispondenti non ha richiesto un prestito personale.
##
## cellular telephone unknown
## 2896 301 1324
##
## cellular telephone unknown
## 64.06 6.66 29.29
Il 64% circa dei rispondenti sono stati contattati via cellulare. C’è una percentuale considerevole di unknown ed una piccola percentuale di persone contattate via telefono.
##
## apr aug dec feb jan jul jun mar may nov oct sep
## 293 633 20 222 148 706 531 49 1398 389 80 52
##
## apr aug dec feb jan jul jun mar may nov oct sep
## 6.48 14.00 0.44 4.91 3.27 15.62 11.75 1.08 30.92 8.60 1.77 1.15
La maggior parte degli intervistati è stato contattato durante i mesi estivi, in particolare più del 30% dei contatti sono avvenuti nel mese di Maggio. Il mese in cui vengono contattate le persone puù avere un impatto sostanziale sull’output desiderato (es. in alcuni periodi dell’anno le persone potrebbero ricevere bonus o premi di produzione, quindi potrebbe essere un buon momento per proporre la sottoscrizione di un deposito). L’asimmetria tra l’effort messo nelle precedenti campagne (previous) ed il periodo estivo potrebbe avere potenzialmente impatto sul risultato delle future campagne, specialmente se i mesi estivi risulteranno essere un predittore in negativo per il successo della campagna.
##
## failure other success unknown
## 490 197 129 3705
##
## failure other success unknown
## 10.84 4.36 2.85 81.95
Per più dell’81% degli intervistati, il valore di questa variabile è unknown. Gli unknown potrebbero essere i nuovi clienti che quindi non erano mai stati contattati prima, mentre coloro che rientrano nella categoria failure+success+other rappresentano i clienti già noti. Più avanti nell’analisi verranno combinati questi livelli per capire se l’appartenenza ad uno o all’altro possa influenzare il successo della campagna. Infatti coloro che sono già clienti potrebbero essere più disposti a sottoscrivere un deposito di coloro che non hanno mai sentito parlare prima di questa opportunità.
##
## no yes
## 4000 521
##
## no yes
## 88.48 11.52
Solo l’11% circa dei rispondenti alla campagna attuale hanno alla fine sottoscritto un deposito. Questo rende il dataset molto sbilanciato e richiederà l’applicazione di metodi per compensare questo sbilanciamento (non bilanciare i dati potrebbe comportare l’avere un modello con alte performance predittive per il semplice fatto che sarà molto trainato verso la risposta “no”, che risulterà corretta nella maggior parte dei casi, ignorando le risposte positive)
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
La linea continua rappresenta la mediana, mentre la linea tratteggiata rappresenta la media
La distribuzione dell’età è piuttosto bilanciata, con la maggior parte degli individui che hanno un’età compresa tra i 30 ed i 60 anni.
Il boxplot per i valori medi del saldo annuale mostrano valori di mediana a zero, il che significa che la maggior parte delle persone contattate per questa campagna hanno un saldo annuale negativo o prossimo allo zero.
La maggior parte degli individui sono stati contattati solo una volta o due durante la campagna corrente.
La distribuzione di questa variabile è piuttosto uniforme e non ci sono particolari asimmetrie. Ai fini del modello predittivo probabilmente questa variabile non sarà significativa.
La maggior parte delle persone decide riguardo la sottoscrizione del deposito entro i primi 300 secondi (5 minuti), con una mediana di circa 240 secondi (4 minuti). Questa variabile influisce molto sul modello predittivo in quanto se duration=0 allora y=”no”; si valuterà in seguito se non considerarla all’interno del modello di regressione.
Il grafico mostra il numero di giorni passati dopo l’ultimo contatto con il cliente durante la campagna precedente. La distribuzione è altamente asimmetrica verso il valore -1, perchè questo è il valore assegnato ai i clienti che non sono mai stati contattati prima della campagna corrente. La maggior parte dei rispondenti è stato quindi contattato per la prima volta durante questa campagna. Inoltre coloro che non sono mai stati contattati prima portano a creare un’assimmetria verso lo zero anche nella distribuzione delle variabili campaign e previous
Le considerazioni fatte per la variabile pdays sono confermate dal grafico della variabile previous, dove il numero di contatti avuti con lo stesso cliente prima di questa campagna presenta una mediana a zero senza alcuna distanza interquartile, che significa che non si erano avuti precedenti contatti con il cliente contattato durante questa campagna.
Si procede verificando se le variabili categoriche del dataset sono indipendenti l’una dall’altra utilizzando il test del chi-quadrato con un livello di confidenza del 95%. Saranno comparate le seguenti coppie di variabili:
L’ipotesi nulla per ogni coppia di variabili è che esse siano indipendenti l’una dall’altra. Un alto valore di chi-quadrato e un basso valore di p-value permetteranno di rigettare l’ipotesi nulla e quindi concludere che le variabili sono tra loro dipendenti.
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 2840, df = 33, p-value < 2.2e-16
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 373.18, df = 22, p-value < 2.2e-16
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 380, df = 11, p-value < 2.2e-16
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 47.191, df = 11, p-value = 1.989e-06
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 226.51, df = 22, p-value < 2.2e-16
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 139.09, df = 6, p-value < 2.2e-16
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 8.2645, df = 2, p-value = 0.01605
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 10.88, df = 2, p-value = 0.004339
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 29.519, df = 4, p-value = 6.133e-06
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 29.519, df = 4, p-value = 6.133e-06
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 39.798, df = 3, p-value = 1.176e-08
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 147.01, df = 6, p-value < 2.2e-16
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: cont_table
## X-squared = 1.4374, df = 1, p-value = 0.2306
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 216.68, df = 2, p-value < 2.2e-16
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 0.32242, df = 2, p-value = 0.8511
Dai risultati del test appena effettuato, si può concludere che:
Non vi sono correlazioni particolarmente significative tra le variabili numeriche, eccetto, come ci si aspettava, tra le variabili previous e pdays che hanno una forte correlazione positiva, dal momento che a valori di pdays=-1 corrisponde previous=0.
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 68.988, df = 11, p-value = 1.901e-10
Le persone tra i blue-collars, nel management ed i tecnici sono coloro che più degli altri sottoscrivono un deposito a termine. Il risultato appare abbastanza ovvio considerando l’alta proporzione di questi tipi di lavori nel conteggio totale.
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 19.03, df = 2, p-value = 7.374e-05
Data l’elevata proporzione delle persone married nel conteggio totale, non sorprende vedere che questo gruppo sottoscrive con più frequenza un deposito a termine.
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 15.237, df = 3, p-value = 0.001625
Di nuovo, l’elevata proporzione delle persone che hanno un livello di educazione secondary nel conteggio totale porta al fatto che questo gruppo sottoscrive con più frequenza un deposito a termine.
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: cont_table
## X-squared = 1.1844e-27, df = 1, p-value = 1
E’ normale che i no defaulters sottoscrivano un deposito a termine in misura maggiore data la loro elevata percentuale nel conteggio totale. Tuttavia è interessante vedere che ci esistono defaulters che sottoscrivono un deposito.
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: cont_table
## X-squared = 48.885, df = 1, p-value = 2.715e-12
È interessante scoprire che, sebbene nel conteggio totale coloro che hanno un mutuo siano in percentuale più alta rispetto a coloro che non ce l’hanno, tuttavia il loro conteggio nella sottoscrizione di un deposito a termine è inferiore a quello di coloro che non hanno preso un mutuo. È probabile che il mutuo influenzi la propensione/inclinazione di una persona ad investire in un deposito a termine.
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: cont_table
## X-squared = 21.872, df = 1, p-value = 2.915e-06
A causa dell’alta percentuale di persone che hanno un prestito personale, non sorprende che esse si trovino in cima alla classifica in termini di sottoscrizione di depositi a termine. Pertanto, sarebbe interessante scoprire se un prestito, sia esso immobiliare o personale, influisca sulla probabilità di una persona di sottoscrivere un deposito a termine. Di conseguenza, questo aspetto verrà ulteriormente esplorato più avanti in questa sezione con altre variabili.
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 87.87, df = 2, p-value < 2.2e-16
Data l’alta percentuale di persone contattate tramite cellulare, questa categoria è quella che con più frequenza sottoscrive depositi a termine.
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 250.5, df = 11, p-value < 2.2e-16
Anche se, come si era precedente visto, la maggior parte dei contatti avvengono nei mesi estivi ed in modo particolare nel mese di maggio, questo impatta solo in misura limitata alla distribuzione della frequenza di sottoscrizione di un deposito a termine.
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 386.88, df = 3, p-value < 2.2e-16
Data l’alta percentuale di persone il cui potcome è unknown, questa categoria è quella che con più frequenza sottoscrive depositi a termine.
Verranno esplorate le variabili numeriche in relazione alla variabile target Y, ad eccezione di Pdays e Previous perché quasi tutti i clienti contattati durante questa campagna sono stati contattati per la prima volta e il confronto dei grafici sulla base di queste informazioni non produrrebbe intuizioni significative. Inoltre, la maggior parte delle persone è stata contattata solo una o due volte, pertanto anche l’esplorazione della variabile campaign non porta a risultati significativi. Allo stesso modo, eslorare la variabile Day non risulta utile ai fini dell’analisi. Verranno mostrati i grafici di queste variabili per completezza, ma non verranno commentati.
Sebbene le persone di tutte le età possano sottoscrivere un deposito a termine, tuttavia le persone tra i 30 ei 40 anni ne usufruiscono di più. È interessante notare che la stessa fascia d’età ha il conteggio più alto anche tra coloro che non hanno sottoscritto il deposito. Questo porta a pensare che le persone in questa fascia di età siano anche quelle più contattate, data la loro alta presenza nel dataset.
Un attento confronto tra i due grafici dimostra che le persone con un saldo prossimo allo zero o comunque molto basso hanno meno probabilità di sottoscrivere un deposito a termine e pochissime persone con un saldo annuale medio basso optano per il deposito a termine.
La durata ha un impatto importante sul risultato target, nel senso che quando la durata è 0, il risultato della sottoscrizione del deposito a termine è sempre No. L’altra scoperta significativa è che quasi tutte le persone che non desiderano sottoscrivere un deposito a termine decidono nei primi 5 minuti della chiamata, mentre le persone che desiderano sottoscriverlo a volte impiegano un po’ più di tempo per convincersi e decidere.
È molto difficile trarre qualsiasi interpretazione dal default e balance a causa del boxplot distorto, ma è chiaro che le persone che pagano le rate in tempo (vale a dire nessun default) hanno un saldo annuale leggermente sopra la media, e le persone che hanno un saldo più alto hanno più probabilità di sottoscrivere depositi a termine poiché la figura mostra che il saldo mediano per questo gruppo è più alto rispetto agli altri. Quindi, in breve, possiamo dedurre dal grafico che nessun inadempiente che ha un saldo medio annuale prossimo alla media ha maggiori probabilità di avvalersi di depositi a termine presso la banca.
È interessante notare da questa figura che, indipendentemente dal fatto che le persone abbiano o meno mutui, coloro che sottoscrivono depositi a termine trascorrono più tempo al telefono durante la campagna di marketing rispetto a coloro che non sottoscrivono depositi a termine. Inoltre, coloro che hanno già un mutuo impiegano più tempo durante la chiamata nel decidere se sottoscrivere un deposito o meno rispetto a quelli che non hanno un mutuo.
Le persone che hanno già prestiti personali trascorrono più tempo al telefono durante la campagna di marketing rispetto a coloro che non hanno prestiti personali. Inoltre, coloro che hanno prestiti personali hanno maggiori probabilità di sottoscrivere depositi a termine. Si può dire che le persone che si avvalgono di prestiti personali concedono relativamente più tempo al telefono e generalmente sono più propensi a sottoscrivere un deposito a termine.
Prima di procedere alla costruzione del modello di regressione vero e proprio, bisogna operare alcune operazioni sul dataset, come la rimozione degli outliers, la trasformazione delle variabili ed il bilanciamento dei dati per la variabile target.
Le statistiche descrittive hanno mostrato l’asimmetria presente nel dataset. Per rimuovere gli outliers e rendere i dati normalmente distribuiti, vengono eseguite ulteriori analisi. I grafici sotto mostrano come i dati possono essere trasformati e quale trasformazione funzionerà meglio.
A causa della natura dei dati, è meglio non avere i dati tutti normalmente distribuiti, perchè si rischierebbe di alterare troppo l’informazione che possiamo trarre da essi. Per l’imputazione degli outliers verrà utilizzato un metodo denominato capping, che consiste nel limitare (cap) gli outliers al di sotto del 5° percentile e al di sopra del 95° percentile. Questo limite porta alla riduzione degli outliers e ad una distribuzione più fluida dei dati.
Osservo di nuovo le distribuzioni delle variabili numeriche dopo la rimozione degli ouliers:
Correlazione tra le variabili numeriche dopo la rimozione degli outliers:
Come già si evinceva in precedenza, tra Pdays e Previous c’è un’altissima correlazione, per cui in fase di costruzione del modello elimineremo una delle due (pdays)
Per alcune variabili categoriche è possibile combinare più livelli affini in un unico livello, rendendo così l’analisi più accurata. In particolare, saranno applicate le seguenti trasformazioni:
library(caret)
set.seed(1234)
# Creazione dei dataset di train e test
train <- createDataPartition(bank$y, p = 0.6, list=FALSE)
bank_train <- bank[train, ]
bank_test <- bank[-train, ]
#Conversione di Yes No in 1 e 0 respettivamente
bank_train$ObsY <- ifelse (bank_train$y == "yes", 1,0)
bank_test$ObsY <- ifelse (bank_test$y == "yes", 1,0)
bank_test$ObsY <- as.integer(bank_test$ObsY)
bank_train$ObsY <- as.integer(bank_train$ObsY)
Viene trainato il modello di regressione sui dati originali per vedere quali sono le variabili significative:
#Regressione logistica sui dati originali
bank_glm <- glm(y ~ age + job + marital + education + default
+ balance + housing + loan + contact + day
+ month + duration + campaign + pdays + previous
+ poutcome, data = bank_train, family = "binomial")
summary(bank_glm)
##
## Call:
## glm(formula = y ~ age + job + marital + education + default +
## balance + housing + loan + contact + day + month + duration +
## campaign + pdays + previous + poutcome, family = "binomial",
## data = bank_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.7635 -0.3718 -0.2352 -0.1352 2.8637
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.909e+00 9.800e-01 -2.968 0.00299 **
## age -1.246e-03 9.442e-03 -0.132 0.89505
## jobblue-collar -7.495e-01 3.263e-01 -2.297 0.02160 *
## jobentrepreneur -6.224e-01 4.990e-01 -1.247 0.21233
## jobhousemaid -6.273e-01 5.471e-01 -1.146 0.25162
## jobmanagement -1.663e-01 3.131e-01 -0.531 0.59527
## jobretired 5.616e-01 4.079e-01 1.377 0.16852
## jobself-employed -9.560e-01 5.211e-01 -1.835 0.06656 .
## jobservices -4.214e-01 3.665e-01 -1.150 0.25032
## jobstudent 2.593e-01 4.854e-01 0.534 0.59328
## jobtechnician -2.754e-01 2.958e-01 -0.931 0.35196
## jobunemployed -7.642e-01 5.880e-01 -1.300 0.19367
## jobunknown 3.146e-02 7.733e-01 0.041 0.96755
## maritalmarried -5.286e-01 2.341e-01 -2.258 0.02392 *
## maritalsingle -2.917e-01 2.733e-01 -1.067 0.28596
## educationsecondary 2.754e-01 2.718e-01 1.013 0.31097
## educationtertiary 4.909e-01 3.160e-01 1.553 0.12033
## educationunknown 1.311e-01 4.586e-01 0.286 0.77491
## defaultno defaulter -3.912e-01 5.794e-01 -0.675 0.49955
## balance -3.625e-05 3.104e-05 -1.168 0.24282
## housingno housing loan 2.268e-01 1.832e-01 1.238 0.21586
## loanpersonal loan -7.276e-01 2.714e-01 -2.681 0.00733 **
## contacttelephone -2.966e-01 3.304e-01 -0.898 0.36937
## contactunknown -1.314e+00 2.979e-01 -4.410 1.03e-05 ***
## day 5.782e-03 1.092e-02 0.530 0.59636
## monthaug -3.196e-01 3.345e-01 -0.956 0.33928
## monthdec -1.134e+00 1.098e+00 -1.032 0.30188
## monthfeb 2.958e-01 3.885e-01 0.761 0.44648
## monthjan -6.708e-01 4.822e-01 -1.391 0.16419
## monthjul -7.414e-01 3.440e-01 -2.156 0.03111 *
## monthjun 4.620e-01 4.023e-01 1.148 0.25082
## monthmar 1.534e+00 5.141e-01 2.983 0.00285 **
## monthmay -6.947e-01 3.237e-01 -2.146 0.03189 *
## monthnov -7.461e-01 3.635e-01 -2.052 0.04012 *
## monthoct 1.157e+00 4.389e-01 2.637 0.00836 **
## monthsep 6.520e-01 5.626e-01 1.159 0.24655
## duration 4.882e-03 2.849e-04 17.140 < 2e-16 ***
## campaign -7.189e-02 3.661e-02 -1.964 0.04955 *
## pdays 1.755e-03 1.237e-03 1.418 0.15613
## previous -7.615e-03 5.016e-02 -0.152 0.87935
## poutcomeother 5.129e-01 3.663e-01 1.400 0.16149
## poutcomesuccess 2.716e+00 3.749e-01 7.246 4.30e-13 ***
## poutcomeunknown 3.891e-01 4.298e-01 0.905 0.36529
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1940.3 on 2712 degrees of freedom
## Residual deviance: 1245.3 on 2670 degrees of freedom
## AIC: 1331.3
##
## Number of Fisher Scoring iterations: 6
bank_train$ObsY <- as.integer(bank_train$ObsY)
Viene trainato il modello di regressione sui dati standardizzati per vedere quali sono le variabili significative:
#Regressione logistica sui dati standardizzati
bank_glm1 <- glm(y ~ age_imp + job_level + marital_level + education + default
+ balance_imp + housing + loan + contact + day
+ month_level + duration_imp + campaign_imp + previous_imp
+ poutcome_level, data = bank_train, family = "binomial")
summary(bank_glm1)
##
## Call:
## glm(formula = y ~ age_imp + job_level + marital_level + education +
## default + balance_imp + housing + loan + contact + day +
## month_level + duration_imp + campaign_imp + previous_imp +
## poutcome_level, family = "binomial", data = bank_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.7659 -0.3792 -0.2434 -0.1469 3.0497
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.498e+00 1.067e+00 -1.404 0.16024
## age_imp 8.459e-03 7.519e-03 1.125 0.26058
## job_levelno_active_income 3.049e-02 7.361e-01 0.041 0.96696
## job_leveladministration_management -2.410e-01 7.282e-01 -0.331 0.74066
## job_levelblue-collar -6.788e-01 7.304e-01 -0.929 0.35275
## job_levelservices -5.824e-01 7.521e-01 -0.774 0.43876
## job_levelself-employed -8.783e-01 7.704e-01 -1.140 0.25426
## marital_levelno_married 3.943e-01 1.556e-01 2.534 0.01128 *
## educationsecondary 3.671e-01 2.378e-01 1.543 0.12273
## educationtertiary 5.652e-01 2.722e-01 2.076 0.03788 *
## educationunknown 3.715e-01 4.284e-01 0.867 0.38581
## defaultno defaulter -5.043e-01 5.276e-01 -0.956 0.33913
## balance_imp -3.243e-05 3.784e-05 -0.857 0.39133
## housingno housing loan 4.728e-01 1.590e-01 2.974 0.00294 **
## loanpersonal loan -6.957e-01 2.441e-01 -2.850 0.00437 **
## contacttelephone -4.333e-02 2.979e-01 -0.145 0.88436
## contactunknown -9.933e-01 2.160e-01 -4.598 4.26e-06 ***
## day -8.350e-03 9.395e-03 -0.889 0.37416
## month_levelspring_summer -8.018e-02 1.778e-01 -0.451 0.65198
## duration_imp 5.939e-03 3.236e-04 18.350 < 2e-16 ***
## campaign_imp -6.143e-02 4.423e-02 -1.389 0.16487
## previous_imp 1.125e-01 6.663e-02 1.688 0.09137 .
## poutcome_levelrest -2.320e+00 3.190e-01 -7.274 3.49e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1940.3 on 2712 degrees of freedom
## Residual deviance: 1319.1 on 2690 degrees of freedom
## AIC: 1365.1
##
## Number of Fisher Scoring iterations: 6
#Predizione sui dati originali
bank_test$predSub <- predict.glm(bank_glm, newdata = bank_test, type = "response")
library(SDMTools)
#Confusion Matrix - dati originali e soglia a 0,5
confusion.matrix(bank_test$ObsY, bank_test$predSub, threshold = 0.5)
## obs
## pred 0 1
## 0 1555 139
## 1 45 69
## attr(,"class")
## [1] "confusion.matrix"
accuracy(bank_test$ObsY, bank_test$predSub, threshold = 0.5)
## threshold AUC omission.rate sensitivity specificity prop.correct
## 1 0.5 0.6518029 0.6682692 0.3317308 0.971875 0.8982301
## Kappa
## 1 0.3778948
#Predizione sui dati standardizzati
bank_test$predSub1 <- predict.glm(bank_glm1, newdata = bank_test, type = "response")
#Confusion Matrix - dati standardizzati e soglia a 0,5
confusion.matrix(bank_test$ObsY, bank_test$predSub1, threshold = 0.5)
## obs
## pred 0 1
## 0 1548 139
## 1 52 69
## attr(,"class")
## [1] "confusion.matrix"
accuracy(bank_test$ObsY, bank_test$predSub1, threshold = 0.5)
## threshold AUC omission.rate sensitivity specificity prop.correct
## 1 0.5 0.6496154 0.6682692 0.3317308 0.9675 0.8943584
## Kappa
## 1 0.3657841
La matrice di confusione sui dati mostra che il modello con i dati standardizzati ha una migliore predizione dei True Positive (Sensitivity) mentre quello con i dati originali ha una migliore predizione dei True Negative (Specificity). L’accuratezza del modello è migliore per i dati standardizzati (65,2%) rispetto al dataset originale (64,8%).
#Curva di ROC - Dati originali
library(pROC)
myROC <- roc(bank_test$y, bank_test$predSub)
myROC
##
## Call:
## roc.default(response = bank_test$y, predictor = bank_test$predSub)
##
## Data: bank_test$predSub in 1600 controls (bank_test$y no) < 208 cases (bank_test$y yes).
## Area under the curve: 0.8886
plot(myROC)
#### 4.3.3.2 Dati standardizzati
myROC1 <- roc(bank_test$y, bank_test$predSub1)
myROC1
##
## Call:
## roc.default(response = bank_test$y, predictor = bank_test$predSub1)
##
## Data: bank_test$predSub1 in 1600 controls (bank_test$y no) < 208 cases (bank_test$y yes).
## Area under the curve: 0.8747
plot(myROC1)
L’AUC dei dati standardizzati è migliore (87,6%) rispetto a quella dei dati originali (86,8%)
Per trovare la soglia ottimale (threshold) che massimizzi l’accuratezza, si crea un grafico a partire dagli attributi della ROC (Sensitivity, Specificity e Threshold). Il punto in cui Sensitivity e Specificity si intersecano corrisponde al valore della soglia ottimale. Successivamente verrà generata nuovamente la matrice di confusione tenendo conto di questa soglia.
# Distribuzione di TPR (Sensitivity) and TNR (Specificity) sul valore della soglia per i dati originali
matplot(data.frame(myROC$sensitivities, myROC$specificities), x = myROC$thresholds, type='l', xlab = 'threshold', ylab='TPR, TNR')
legend('bottomright', legend=c('TPR', 'TNR'), lty=1:2, col=1:2)
#Confusion Matrix - dati originali e soglia ottima a 0,1
cm <- confusion.matrix(bank_test$ObsY, bank_test$predSub, threshold = 0.1)
accuracy(bank_test$ObsY, bank_test$predSub, threshold = 0.1)
## threshold AUC omission.rate sensitivity specificity prop.correct
## 1 0.1 0.81625 0.1875 0.8125 0.82 0.8191372
## Kappa
## 1 0.4159145
fourfoldplot(cm, color = c("#CC6666", "#99CC99"),
conf.level = 0, margin = 1, main = "Confusion Matrix")
# Distribuzione di TPR (Sensitivity) and TNR (Specificity) sul valore della soglia per i dati standardizzati
matplot(data.frame(myROC1$sensitivities, myROC1$specificities), x = myROC1$thresholds, type='l', xlab = 'threshold', ylab='TPR, TNR')
legend('bottomright', legend=c('TPR', 'TNR'), lty=1:2, col=1:2)
#Confusion Matrix - dati standardizzati e soglia ottima a 0,1
cm1 <- confusion.matrix(bank_test$ObsY, bank_test$predSub1, threshold = 0.1)
accuracy(bank_test$ObsY, bank_test$predSub1, threshold = 0.1)
## threshold AUC omission.rate sensitivity specificity prop.correct
## 1 0.1 0.7832692 0.2259615 0.7740385 0.7925 0.7903761
## Kappa
## 1 0.3549665
fourfoldplot(cm1, color = c("#CC6666", "#99CC99"),
conf.level = 0, margin = 1, main = "Confusion Matrix")
Sia con i dati originali che con quelli standardizzati, la soglia ottimale è 0.1, che significa che se la probabilità è >0.1 allora possiamo concludere che il rispondente sottoscriverà un deposito a termine. Sensitivity, Specificity e Accuracy sono superiori all’80%.
Dal momento che il dataset (in particolare la distribuzione della variabile target) è molto sbilanciato, abbiamo bisogno di procedere con un bilanciamento dei dati per migliorare la predizione. Esistono diverse tecniche adatte a questo scopo, come per esempio Under Sampling, Over Sampling, SMOTE, etc. in questo modello verrà utilizzato il metodo Random Over Sampling (ROSE) sui dati standardizzati.
library(ROSE)
#ROSE
data_rose <- ROSE(y ~ age_imp + job_level + marital_level + education + default
+ balance_imp + housing + loan + contact + day
+ month_level + duration_imp + campaign_imp + pdays_imp + previous_imp
+ poutcome_level, data = bank_train, seed = 1)$data
table(data_rose$y)
##
## no yes
## 1414 1299
Come si può vedere, rispetto ai dati originali, il metodo ROSE ha ribilanciato la minoranza degli outcome positivi portandoli più o meno allo stesso livello degli outcome negativi nel training set. Questo set potrà ora essere utilizzato per nella regressione logistica per la predizione sul test set.
Sono state eliminate dal training del modello le variabili Job, Age, Pdays, Day in quanto non risultavano statisticamente significative.
glm_rose <- glm(y ~ marital_level + education + default
+ balance_imp + housing + loan + contact
+ month_level + duration_imp + campaign_imp + previous_imp
+ poutcome_level,data = data_rose, family = "binomial")
summary(glm_rose)
##
## Call:
## glm(formula = y ~ marital_level + education + default + balance_imp +
## housing + loan + contact + month_level + duration_imp + campaign_imp +
## previous_imp + poutcome_level, family = "binomial", data = data_rose)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -3.4286 -0.7099 -0.2096 0.7024 2.7467
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -6.394e-01 5.137e-01 -1.245 0.21326
## marital_levelno_married 5.742e-01 1.040e-01 5.521 3.38e-08 ***
## educationsecondary 3.646e-01 1.604e-01 2.273 0.02301 *
## educationtertiary 3.663e-01 1.686e-01 2.173 0.02977 *
## educationunknown 2.760e-01 2.745e-01 1.005 0.31471
## defaultno defaulter 1.206e-01 4.004e-01 0.301 0.76322
## balance_imp 1.241e-05 2.336e-05 0.531 0.59509
## housingno housing loan 6.885e-01 1.058e-01 6.507 7.69e-11 ***
## loanpersonal loan -7.984e-01 1.628e-01 -4.904 9.41e-07 ***
## contacttelephone -9.807e-02 1.936e-01 -0.506 0.61253
## contactunknown -1.461e+00 1.490e-01 -9.805 < 2e-16 ***
## month_levelspring_summer 4.486e-02 1.224e-01 0.366 0.71410
## duration_imp 5.797e-03 2.467e-04 23.494 < 2e-16 ***
## campaign_imp -6.221e-02 2.668e-02 -2.331 0.01974 *
## previous_imp 1.079e-01 3.906e-02 2.761 0.00576 **
## poutcome_levelrest -2.185e+00 2.454e-01 -8.902 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 3756.1 on 2712 degrees of freedom
## Residual deviance: 2468.4 on 2697 degrees of freedom
## AIC: 2500.4
##
## Number of Fisher Scoring iterations: 5
Questo mostra che education:secondary, education:unknown, default:no defaulter, contact:telephone non sono statisticamente significative per la predizione del risultato.
#Predizione con dati bilanciati
pred_glm_rose <- predict.glm(glm_rose, newdata = bank_test, type = "response")
# Confusion Matrix
cm_rose <- confusion.matrix(bank_test$ObsY, pred_glm_rose)
accuracy(bank_test$ObsY, pred_glm_rose)
## threshold AUC omission.rate sensitivity specificity prop.correct
## 1 0.5 0.7903125 0.25 0.75 0.830625 0.8213496
## Kappa
## 1 0.3982326
fourfoldplot(cm_rose, color = c("#CC6666", "#99CC99"),
conf.level = 0, margin = 1, main = "Confusion Matrix")
La matrice di confusione mostra che sensitivity, specificity e accuracy sono maggiori dell’80% e bilanciati. Inoltre questa predizione è per una soglia di 0,5 mentre la precedente aveva una soglia ottimale di 0.1.
#AUC ROSE
myROCS <-roc(bank_test$ObsY, pred_glm_rose)
myROCS
##
## Call:
## roc.default(response = bank_test$ObsY, predictor = pred_glm_rose)
##
## Data: pred_glm_rose in 1600 controls (bank_test$ObsY 0) < 208 cases (bank_test$ObsY 1).
## Area under the curve: 0.8729
plot(myROCS)
# Distribuzione di TPR (Sensitivity) and TNR (Specificity) sul valore della soglia per i dati bilanciati
matplot(data.frame(myROCS$sensitivities, myROCS$specificities), x = myROCS$thresholds, type='l', xlab = 'threshold', ylab='TPR, TNR')
legend('bottomright', legend=c('TPR', 'TNR'), lty=1:2, col=1:2)
Il grafico mostra che la soglia ottimale è proprio 0,5, che significa che i dati sono perfettamente bilanciati. Le persone con una probabilità predetta maggiore di 0.5 sottoscriveranno il deposito a termine.