Dataset terkait dengan kampanye pemasaran langsung dari lembaga perbankan Portugis. Kampanye pemasaran didasarkan pada panggilan telepon. Seringkali, lebih dari satu kontak ke klien yang sama dibutuhkan, untuk mengakses apakah produk (deposito bank) akan iya (‘yes’) atau tidak (‘no’) berlangganan. Kemudian digunakan untuk membuat model Naive Bayes, Decision Tree dan Random Forest untuk memprediksi adanya kemungkinan customer berlangganan deposito bank. Kita akan menggunakan dataset Bank bisa dilihat disini
Apa yang akan kita lakukan ?
Kita akan mengolah data dengan Naive Bayes, Decision Tree dan Random Forest menggunakan dataset Bank. Langkah - langkah yang akan kita lakukan sebagai berikut:
y sebagai variabel target dan variabel lainnya sebagai prediktorNaive Bayes, Decision Tree dan Random Forest untuk menjelaskan variabel y berdasarkan prediktor## Rows: 4,521
## Columns: 17
## $ age <int> 30, 33, 35, 30, 59, 35, 36, 39, 41, 43, 39, 43, 36, 20, 3...
## $ job <chr> "unemployed", "services", "management", "management", "bl...
## $ marital <chr> "married", "married", "single", "married", "married", "si...
## $ education <chr> "primary", "secondary", "tertiary", "tertiary", "secondar...
## $ default <chr> "no", "no", "no", "no", "no", "no", "no", "no", "no", "no...
## $ balance <int> 1787, 4789, 1350, 1476, 0, 747, 307, 147, 221, -88, 9374,...
## $ housing <chr> "no", "yes", "yes", "yes", "yes", "no", "yes", "yes", "ye...
## $ loan <chr> "no", "yes", "no", "yes", "no", "no", "no", "no", "no", "...
## $ contact <chr> "cellular", "cellular", "cellular", "unknown", "unknown",...
## $ day <int> 19, 11, 16, 3, 5, 23, 14, 6, 14, 17, 20, 17, 13, 30, 29, ...
## $ month <chr> "oct", "may", "apr", "jun", "may", "feb", "may", "may", "...
## $ duration <int> 79, 220, 185, 199, 226, 141, 341, 151, 57, 313, 273, 113,...
## $ campaign <int> 1, 1, 1, 4, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 5, 1, 1, ...
## $ pdays <int> -1, 339, 330, -1, -1, 176, 330, -1, -1, 147, -1, -1, -1, ...
## $ previous <int> 0, 4, 1, 0, 0, 3, 2, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 2, 0, ...
## $ poutcome <chr> "unknown", "failure", "failure", "unknown", "unknown", "f...
## $ y <chr> "no", "no", "no", "no", "no", "no", "no", "no", "no", "no...
Dataset bank memiliki variabel-variabel sebagai berikut:
Dataset memiliki 4521 baris dan 17 kolom. Variabel target kita adalah y dan kita akan menggunakan variabel lain sebagai prediktor.
Langkah pertama kita cek apakah terdapat missing value pada dateset
## 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
Dataset tidak terdapat missing value
Mari kita ubah beberapa tipe data variabel yang masih belum tepat
## variable = age
## type = integer
## na = 0 of 4 521 (0%)
## unique = 67
## min|max = 19 | 87
## q05|q95 = 27 | 59
## q25|q75 = 33 | 49
## median = 39
## mean = 41.1701
Jadi, untuk customer dengan usia 19-87 tahun mediannya adalah 39 tahun dan puncaknya pada usia 33-49
61.9% dari customer sudah menikah, 26.5 masih single dan sisanya pernah bercerai.
Berikut gambaran persebaran usia customer dengan marital status. Single memiliki usia terendah.
Grafik di atas merupakan persentasi banyaknya customer di setiap bidang kerja
Sementara itu, ini persebaran umur customer disetiap bidang kerja
Grafik di atas menggambarkan persenan customer di setiap bidang education
Dari dataset terdapat sebanyak 88.5% customer yang menyatakan No atau tidak ingin berlangganan produk deposito bank
Sebelumnya kita perlu membagi data menjadi dataset train dan dataset uji. Kita akan menggunakan dataset train untuk melatih model Naive Bayes, Decision Tree, dan Random Forest. Dataset pengujian akan digunakan sebagai pembanding dan melihat apakah model menjadi overfit atau tidak dalam memprediksi data baru yang belum terlihat selama fase pelatihan.
Kita akan membagi sebanyak 80% dari data sebagai data pelatihan dan 20% sebagai data pengujian.
RNGkind(sample.kind = "Rounding")
set.seed(100)
intrain <- sample(nrow(data), nrow(data)*0.8)
data_train <- data[intrain,]
data_test <- data[-intrain,]Kita cek kembali proporsi target pada data train
##
## no yes
## 0.8821903 0.1178097
Proporsi kelas target ternyata tidak seimbang. oleh karena itu kita akan melakukan DownSample untuk membuat proporsi kelas target seimbang
##
## no yes
## 0.5 0.5
Sekarang proporsi kelas target kita sudah seimbang, kita bisa lanjut ke tahap selanjutnya
Model
Prediction
Lakukan prediksi kelas ke data_test dan simpan ke objek naive_class
## [1] yes no no no yes no
## Levels: no yes
Evaluation
Buat Confusion Matrix dan evaluasi performa model
## Confusion Matrix and Statistics
##
## Reference
## Prediction no yes
## no 621 27
## yes 189 68
##
## Accuracy : 0.7613
## 95% CI : (0.7322, 0.7888)
## No Information Rate : 0.895
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.2753
##
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.71579
## Specificity : 0.76667
## Pos Pred Value : 0.26459
## Neg Pred Value : 0.95833
## Prevalence : 0.10497
## Detection Rate : 0.07514
## Detection Prevalence : 0.28398
## Balanced Accuracy : 0.74123
##
## 'Positive' Class : yes
##
Model
Prediction
Lakukan prediksi kelas ke data_test dan simpan ke objek dtree_class
## 1 5 8 9 13 21
## no no no no no no
## Levels: no yes
Evaluation
## Confusion Matrix and Statistics
##
## Reference
## Prediction no yes
## no 636 24
## yes 174 71
##
## Accuracy : 0.7812
## 95% CI : (0.7528, 0.8078)
## No Information Rate : 0.895
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.3138
##
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.74737
## Specificity : 0.78519
## Pos Pred Value : 0.28980
## Neg Pred Value : 0.96364
## Prevalence : 0.10497
## Detection Rate : 0.07845
## Detection Prevalence : 0.27072
## Balanced Accuracy : 0.76628
##
## 'Positive' Class : yes
##
Dari hasil yang didapatkan, performa model tidak cukup baik. Mari cek apakah hal tersebut karena model mengalami overfitting
dtree_class_train <- predict(object = model_dtree, newdata = data_train %>%
select(-y),
type = "response")
confusionMatrix(data = dtree_class_train, reference = data_train$y,
positive = "yes")## Confusion Matrix and Statistics
##
## Reference
## Prediction no yes
## no 346 92
## yes 80 334
##
## Accuracy : 0.7981
## 95% CI : (0.7696, 0.8246)
## No Information Rate : 0.5
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.5962
##
## Mcnemar's Test P-Value : 0.4016
##
## Sensitivity : 0.7840
## Specificity : 0.8122
## Pos Pred Value : 0.8068
## Neg Pred Value : 0.7900
## Prevalence : 0.5000
## Detection Rate : 0.3920
## Detection Prevalence : 0.4859
## Balanced Accuracy : 0.7981
##
## 'Positive' Class : yes
##
Mari coba gunakan random forest untuk mencegah kondisi overfitting namun tetap menghasilkan performa yang baik
Model
RNGkind(sample.kind = "Rounding")
set.seed(100)
ctrl <- trainControl(method="repeatedcv", number = 5, repeats = 3)
model_forest <- train(y ~ ., data = data_train, method = "rf", trControl = ctrl)
saveRDS(model_forest, "model_forest.RDS") # simpan modelMari lihat summary dari model random forest:
## Random Forest
##
## 852 samples
## 16 predictor
## 2 classes: 'no', 'yes'
##
## No pre-processing
## Resampling: Cross-Validated (5 fold, repeated 3 times)
## Summary of sample sizes: 682, 682, 682, 682, 680, 681, ...
## Resampling results across tuning parameters:
##
## mtry Accuracy Kappa
## 2 0.7589991 0.5180499
## 22 0.8133623 0.6267631
## 42 0.8023957 0.6048299
##
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was mtry = 22.
Mari lihat Out of Bag Error yang dihasilkan dari model random forest
##
## Call:
## randomForest(x = x, y = y, mtry = param$mtry)
## Type of random forest: classification
## Number of trees: 500
## No. of variables tried at each split: 22
##
## OOB estimate of error rate: 19.13%
## Confusion matrix:
## no yes class.error
## no 325 101 0.2370892
## yes 62 364 0.1455399
OOB yang dihasilkan mengindikasikan bahwa model akan memiliki akurasi sebesar 80.87% di data baru.
Kita juga bisa melihat variable apa saja yang penting dalam pembuatan random forest dengan menggunakan varImp().
## rf variable importance
##
## only 20 most important variables shown (out of 42)
##
## Overall
## duration 100.000
## balance 23.155
## age 20.583
## day 16.072
## poutcomesuccess 11.747
## contactunknown 11.409
## campaign 10.552
## pdays 9.479
## monthmar 6.138
## previous 5.861
## monthmay 4.338
## housingyes 4.090
## monthjul 3.699
## maritalmarried 2.802
## jobstudent 2.547
## jobblue-collar 2.406
## educationtertiary 2.396
## poutcomeunknown 2.393
## loanyes 2.266
## monthjun 2.089
Variable paling penting dalam pembuatan random forest adalah duration.
Prediction
Lakukan prediksi kelas ke data_test dan simpan ke objek forest_class
## [1] no no no no yes no
## Levels: no yes
Evaluation
Buat Confusion Matrix dan evaluasi performa model di data test
## Confusion Matrix and Statistics
##
## Reference
## Prediction no yes
## no 626 16
## yes 184 79
##
## Accuracy : 0.779
## 95% CI : (0.7505, 0.8056)
## No Information Rate : 0.895
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.3395
##
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.83158
## Specificity : 0.77284
## Pos Pred Value : 0.30038
## Neg Pred Value : 0.97508
## Prevalence : 0.10497
## Detection Rate : 0.08729
## Detection Prevalence : 0.29061
## Balanced Accuracy : 0.80221
##
## 'Positive' Class : yes
##
Pada kasus ini kita akan mengunggulkan metrics recall/Sensitivity karena kita berharap akan banyak customer yang akan berlangganan deposito bank
Berikut ini hasil performa pada uji coba data test di metrics recall/Sensitivity untuk setiap model :
Berdasarkan hasil performa di data test, model Random Forest yang menghasilkan metrics evaluasi dengan nilai paling baik
Mari lihat pula apakah model dapat mengklasifikasi kedua kelas dengan lebih baik menggunakan auc value.
## no yes
## 1 0.824 0.176
## 5 0.910 0.090
## 8 0.974 0.026
## 9 0.992 0.008
## 13 0.282 0.718
## 21 0.754 0.246
forest_auc <- prediction(predictions = forestProb[, 2],
labels = as.numeric(data_test$y == "yes"))
auc <- performance(prediction.obj = forest_auc,
measure = "auc")
auc@y.values## [[1]]
## [1] 0.8710006
Model random forest dapat cukup baik mengklasifikasikan kelas positif dan kelas negatif
Dari 3 macam modelling yang telah kita buat dan uji ke data test, kita ketahui bahwa model Random Forest memiliki hasil performa yang paling baik. Namun dari model tersebut kita tidak bisa langsung menginterpretasinya. Jika ingin hasil yang mudah diinterpretasi maka kita akan memilih model Decision Tree