Intro

Data

Pada kesempatan kali ini saya akan menggunakan dataset yang berisikan data telemarketing pada lembaga bank Portugis. Output yang diinginkan adalah membuat model yang mampu memprediksi keberhasilan dari telemarketing tersebut berdasarkan prediktor-prediktor yang tersedia. Dari output tersebut lembaga bank dapat mengidentifikasikan faktor-faktor yang meningkatkan tingkat keberhasilan dari sebuah telemarketing.

Library

library(dplyr)
library(e1071)
library(rsample)
library(caret)
library(partykit)

#{-}

Data Preparation

Pertama kita akan memanggil data yang akan kita olah.

bank <- read.csv2("bank/bank-full.csv")

Gunakan fungsi glimpse untuk memberikan gambaran dataset bank yang telah dipanggil.

glimpse(bank)
## Rows: 45,211
## Columns: 17
## $ age       <int> 58, 44, 33, 47, 33, 35, 28, 42, 58, 43, 41, 29, 53, 58, 57, …
## $ job       <chr> "management", "technician", "entrepreneur", "blue-collar", "…
## $ marital   <chr> "married", "single", "married", "married", "single", "marrie…
## $ education <chr> "tertiary", "secondary", "secondary", "unknown", "unknown", …
## $ default   <chr> "no", "no", "no", "no", "no", "no", "no", "yes", "no", "no",…
## $ balance   <int> 2143, 29, 2, 1506, 1, 231, 447, 2, 121, 593, 270, 390, 6, 71…
## $ housing   <chr> "yes", "yes", "yes", "yes", "no", "yes", "yes", "yes", "yes"…
## $ loan      <chr> "no", "no", "yes", "no", "no", "no", "yes", "no", "no", "no"…
## $ contact   <chr> "unknown", "unknown", "unknown", "unknown", "unknown", "unkn…
## $ day       <int> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, …
## $ month     <chr> "may", "may", "may", "may", "may", "may", "may", "may", "may…
## $ duration  <int> 261, 151, 76, 92, 198, 139, 217, 380, 50, 55, 222, 137, 517,…
## $ campaign  <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ pdays     <int> -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, …
## $ previous  <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ poutcome  <chr> "unknown", "unknown", "unknown", "unknown", "unknown", "unkn…
## $ y         <chr> "no", "no", "no", "no", "no", "no", "no", "no", "no", "no", …

Data bank terdiri dari 45.211 baris dan 17 kolom. Kolom-kolom tersebut terdiri dari :

  • age: umur
  • job: kategori pekerjaan
  • marital: status pernikahan
  • education: tingkat pendidikan
  • default: memiliki kredit gagal bayar atau tidak
  • balance: uang yang tersimpan dalam rekening
  • housing: memiliki kredit rumah atau tidak
  • loan: memiliki kredit preibadi atau tidak
  • contact: metode kontak/telefon
  • day: day-of-month dari kontak terakhir
  • month: bulan dari kontak terakhir
  • duration: durasi kontak pada telemarketing dilakukan
  • campaign: jumlah kontak yang dilakukan pada telemarketing
  • pdays: jumlah hari berlalu setelah kontak dari telemarketing sebelumnya
  • previous: jumlah kontak yang dilakukan pada telemarketing sebelumnya
  • poutcome: outcome dari telemarketing sebelumnya
  • y: keberhasilan dari telemarketing (iya atau tidak)

Data Preprocessing & EDA

Selanjutnya kita akan check missing value

anyNA(bank)
## [1] FALSE
colSums(is.na(bank))
##       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

Sekilas tidak ada missing value, namun kita juga akan mengecek nilai unique beberapa kolomnya

unique(bank$contact)
## [1] "unknown"   "cellular"  "telephone"
unique(bank$poutcome)
## [1] "unknown" "failure" "other"   "success"
unique(bank$education)
## [1] "tertiary"  "secondary" "unknown"   "primary"

Ternyata terdapat values “unknown” dalam kolom contact, poutcome, dan education. Kita juga dapat melihat sebarapa banyak nila “unknown” dalam kolom-kolom tersebut.

table(bank$contact)
## 
##  cellular telephone   unknown 
##     29285      2906     13020
table(bank$poutcome)
## 
## failure   other success unknown 
##    4901    1840    1511   36959
table(bank$education)
## 
##   primary secondary  tertiary   unknown 
##      6851     23202     13301      1857

Pada kolom putcome terdapat nilai “unknown” yang cukup besar dan menjadi mayoritas dibandingkan kelas lainnya. Nilai-nilai unknown tersebut nantinya akan kita coba hilangkan.

Data Cleansing & Wrangling

Kita akan menghilankan nilai “unknown” dan mengubah type data character menjadi factor.

bank_clean <- bank %>% 
  filter(contact != "unknown" & poutcome != "unknown" & education != "unknown") %>% 
  mutate_if(is.character,as.factor)

Gambaran dari data yang sudah dibersihkan:

glimpse(bank_clean)
## Rows: 7,864
## Columns: 17
## $ age       <int> 33, 42, 33, 36, 36, 44, 26, 51, 33, 30, 30, 44, 51, 51, 44, …
## $ job       <fct> admin., admin., services, management, management, blue-colla…
## $ marital   <fct> married, single, married, married, married, married, single,…
## $ education <fct> tertiary, secondary, secondary, tertiary, tertiary, secondar…
## $ default   <fct> no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, …
## $ balance   <int> 882, -247, 3444, 2415, 0, 1324, 172, 3132, 1005, 873, 1243, …
## $ housing   <fct> no, yes, yes, yes, yes, yes, no, no, yes, yes, yes, yes, no,…
## $ loan      <fct> no, yes, no, no, no, no, yes, no, no, no, no, no, no, no, ye…
## $ contact   <fct> telephone, telephone, telephone, telephone, telephone, telep…
## $ day       <int> 21, 21, 21, 22, 23, 25, 4, 5, 10, 12, 13, 17, 17, 17, 17, 17…
## $ month     <fct> oct, oct, oct, oct, oct, oct, nov, nov, nov, nov, nov, nov, …
## $ duration  <int> 39, 519, 144, 73, 140, 119, 21, 449, 175, 119, 86, 81, 200, …
## $ campaign  <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ pdays     <int> 151, 166, 91, 86, 143, 89, 140, 176, 174, 167, 174, 195, 165…
## $ previous  <int> 3, 1, 4, 4, 3, 2, 4, 1, 2, 3, 1, 2, 2, 2, 1, 2, 1, 1, 2, 3, …
## $ poutcome  <fct> failure, other, failure, other, failure, other, other, failu…
## $ y         <fct> no, yes, yes, no, yes, no, no, no, no, no, no, no, no, no, n…

Cross Validation

Sebelum membuat model, kita akan memisahkan data bank menjadi data train dan data test.

RNGkind(sample.kind = "Rounding")
## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
set.seed(2012)


index <- initial_split(data = bank_clean, 
                       prop = 0.8,
                       strata = "y")

bank_train <- training(index)
bank_test <- testing(index)

Cek proporsi data train

prop.table(table(bank_train$y))
## 
##        no       yes 
## 0.7717011 0.2282989

Dari hasil di atas, data train belum seimbang, maka akan kita upsampling pada data tersebut

set.seed(2012)
bank_train.up <- upSample(x = bank_train %>% select(-y),
                          y = bank_train$y,
                          yname = "y")

Cek kembali proporsi data train

prop.table(table(bank_train.up$y))
## 
##  no yes 
## 0.5 0.5

Dapat dilihat data train sudah memiliki proporsi yang seimbang.

Modelling

Model Naive Bayes

Naive Bayes adalah metode yang cocok untuk klasifikasi biner dan multiclass. Metode yang juga dikenal sebagai Naive Bayes Classifier ini menerapkan teknik supervised klasifikasi objek di masa depan dengan menetapkan label kelas ke instance/catatan menggunakan probabilitas bersyarat.

Model naive yang akan kita buat adalah sebagai berikut

model_naive <- naiveBayes(formula = y ~.,
                          data = bank_train.up,
                          laplace = 1)

Buat prediksi dari model naive

pred.naive <- predict(model_naive, newdata = bank_test,
                type = "class")

Model Decision Tree

Decision tree adalah amachine learning yang menggunakan seperangkat aturan untuk membuat keputusan dengan struktur seperti pohon yang memodelkan kemungkinan hasil, biaya sumber daya, utilitas dan kemungkinan konsekuensi atau resiko.

Berikut model decision tree yang akan kita buat:

model_dtree <- ctree(formula = y ~.,
                     data = bank_train.up,
                     control = ctree_control(mincriterion = 0.97))
plot(model_dtree, 
     type = "simple")

Kemudian kita juga akan membuat prediksi dari model tersebut

test_pred <- predict(object = model_dtree, 
                  newdata = bank_test,
                  type = "response")

train_pred <- predict(object = model_dtree,
                      newdata = bank_train.up,
                      type = "response")

#{-}

Model Evaluation

Naive Bayes

confusionMatrix(data = pred.naive, 
                reference = bank_test$y, 
                positive = "yes")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  no yes
##        no  941  84
##        yes 273 276
##                                              
##                Accuracy : 0.7732             
##                  95% CI : (0.7517, 0.7937)   
##     No Information Rate : 0.7713             
##     P-Value [Acc > NIR] : 0.4425             
##                                              
##                   Kappa : 0.4573             
##                                              
##  Mcnemar's Test P-Value : <0.0000000000000002
##                                              
##             Sensitivity : 0.7667             
##             Specificity : 0.7751             
##          Pos Pred Value : 0.5027             
##          Neg Pred Value : 0.9180             
##              Prevalence : 0.2287             
##          Detection Rate : 0.1753             
##    Detection Prevalence : 0.3488             
##       Balanced Accuracy : 0.7709             
##                                              
##        'Positive' Class : yes                
## 

Model naive menghasilkan accuracy sebesar 77%, sensitivity sebesar 76%, dan precision sebesar 50%

Decision Tree

Evaluasi pada data test

confusionMatrix(data = test_pred, reference = bank_test$y,
                positive = "yes")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  no yes
##        no  980  66
##        yes 234 294
##                                                
##                Accuracy : 0.8094               
##                  95% CI : (0.7891, 0.8285)     
##     No Information Rate : 0.7713               
##     P-Value [Acc > NIR] : 0.000136             
##                                                
##                   Kappa : 0.5359               
##                                                
##  Mcnemar's Test P-Value : < 0.00000000000000022
##                                                
##             Sensitivity : 0.8167               
##             Specificity : 0.8072               
##          Pos Pred Value : 0.5568               
##          Neg Pred Value : 0.9369               
##              Prevalence : 0.2287               
##          Detection Rate : 0.1868               
##    Detection Prevalence : 0.3355               
##       Balanced Accuracy : 0.8120               
##                                                
##        'Positive' Class : yes                  
## 

Hasi evaluasi model dtree pada data test menghasilkan accuracy sebesar 80%, Sensistivity sebesar 81%, dan post pred values sebesar 55%

Evaluasi pada data train

confusionMatrix(data = train_pred, reference = bank_train.up$y,
                positive = "yes")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   no  yes
##        no  3980  461
##        yes  874 4393
##                                                
##                Accuracy : 0.8625               
##                  95% CI : (0.8555, 0.8693)     
##     No Information Rate : 0.5                  
##     P-Value [Acc > NIR] : < 0.00000000000000022
##                                                
##                   Kappa : 0.725                
##                                                
##  Mcnemar's Test P-Value : < 0.00000000000000022
##                                                
##             Sensitivity : 0.9050               
##             Specificity : 0.8199               
##          Pos Pred Value : 0.8341               
##          Neg Pred Value : 0.8962               
##              Prevalence : 0.5000               
##          Detection Rate : 0.4525               
##    Detection Prevalence : 0.5425               
##       Balanced Accuracy : 0.8625               
##                                                
##        'Positive' Class : yes                  
## 

Hasi evaluasi model dtree pada data train menghasilkan accuracy sebesar 86%, Sensistivity sebesar 90%, dan post pred values sebesar 83%

Conclusion

Hasi evaluasi model dtree pada data test menghasilkan accuracy sebesar 80%, Sensistivity sebesar 81%, dan post pred values sebesar 55%. Oleh karena itu kita akan memilih model dtree untuk melakukan prediksi pada dataset telemarketing bank protugal. Selain itu sensitivity lebih penting pada kasus ini karena tentunya bank portugis tidak mau melewakan satu pun potential customer produk yang mereka tawarkan.