Travel Insurance Prediction
Introduction
Pada analisis kali ini saya akan menggunakan metode
Supervised Learning (Classfication Machine Learning)
untuk mengkaji data prediksi asuransi perjalanan, mencari indikator yang
dapat digunakan untuk memprediksi pelanggan yang ingin memakai asuransi
perjalanan. Metode pendekatan Supervised Learning yang akan dilakukan
terdiri dari Klasifikasi Naive Bayes,
Decision Tree dan Random Forest.
Library
Data Preparation
Import Data
#> X Age Employment.Type GraduateOrNot AnnualIncome FamilyMembers
#> 1 0 31 Government Sector Yes 400000 6
#> 2 1 31 Private Sector/Self Employed Yes 1250000 7
#> 3 2 34 Private Sector/Self Employed Yes 500000 4
#> 4 3 28 Private Sector/Self Employed Yes 700000 3
#> 5 4 28 Private Sector/Self Employed Yes 700000 8
#> 6 5 25 Private Sector/Self Employed No 1150000 4
#> ChronicDiseases FrequentFlyer EverTravelledAbroad TravelInsurance
#> 1 1 No No 0
#> 2 0 No No 0
#> 3 1 No No 1
#> 4 1 No No 0
#> 5 1 Yes No 0
#> 6 0 No No 0
Data Cleansing
🧮 Mengecek tipe data
#> Rows: 1,987
#> Columns: 10
#> $ X <int> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, …
#> $ Age <int> 31, 31, 34, 28, 28, 25, 31, 31, 28, 33, 31, 26, 32…
#> $ Employment.Type <fct> Government Sector, Private Sector/Self Employed, P…
#> $ GraduateOrNot <fct> Yes, Yes, Yes, Yes, Yes, No, Yes, Yes, Yes, Yes, Y…
#> $ AnnualIncome <int> 400000, 1250000, 500000, 700000, 700000, 1150000, …
#> $ FamilyMembers <int> 6, 7, 4, 3, 8, 4, 4, 3, 6, 3, 9, 5, 6, 6, 3, 7, 4,…
#> $ ChronicDiseases <int> 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1,…
#> $ FrequentFlyer <fct> No, No, No, No, Yes, No, No, Yes, Yes, Yes, No, Ye…
#> $ EverTravelledAbroad <fct> No, No, No, No, No, No, No, Yes, Yes, No, No, Yes,…
#> $ TravelInsurance <int> 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0,…
⚙️ Mengubah isi nama kolom Travel Insurance untuk kelas
target
⚙️ Mengubah tipe data dan menghapus kolom yang tidak digunakan
travel_clean <- travel %>%
select(-X) %>%
mutate(ChronicDiseases = as.factor(ChronicDiseases))
travel_clean %>% head()#> Age Employment.Type GraduateOrNot AnnualIncome FamilyMembers
#> 1 31 Government Sector Yes 400000 6
#> 2 31 Private Sector/Self Employed Yes 1250000 7
#> 3 34 Private Sector/Self Employed Yes 500000 4
#> 4 28 Private Sector/Self Employed Yes 700000 3
#> 5 28 Private Sector/Self Employed Yes 700000 8
#> 6 25 Private Sector/Self Employed No 1150000 4
#> ChronicDiseases FrequentFlyer EverTravelledAbroad TravelInsurance
#> 1 1 No No Yes
#> 2 0 No No Yes
#> 3 1 No No No
#> 4 1 No No Yes
#> 5 1 Yes No Yes
#> 6 0 No No Yes
#> Rows: 1,987
#> Columns: 9
#> $ Age <int> 31, 31, 34, 28, 28, 25, 31, 31, 28, 33, 31, 26, 32…
#> $ Employment.Type <fct> Government Sector, Private Sector/Self Employed, P…
#> $ GraduateOrNot <fct> Yes, Yes, Yes, Yes, Yes, No, Yes, Yes, Yes, Yes, Y…
#> $ AnnualIncome <int> 400000, 1250000, 500000, 700000, 700000, 1150000, …
#> $ FamilyMembers <int> 6, 7, 4, 3, 8, 4, 4, 3, 6, 3, 9, 5, 6, 6, 3, 7, 4,…
#> $ ChronicDiseases <fct> 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1,…
#> $ FrequentFlyer <fct> No, No, No, No, Yes, No, No, Yes, Yes, Yes, No, Ye…
#> $ EverTravelledAbroad <fct> No, No, No, No, No, No, No, Yes, Yes, No, No, Yes,…
#> $ TravelInsurance <fct> Yes, Yes, No, Yes, Yes, Yes, Yes, No, No, Yes, Yes…
✏️ Pastikan data tidak ada missing value
#> Age Employment.Type GraduateOrNot AnnualIncome
#> 0 0 0 0
#> FamilyMembers ChronicDiseases FrequentFlyer EverTravelledAbroad
#> 0 0 0 0
#> TravelInsurance
#> 0
Exploratory Data Analysis
#> Age Employment.Type GraduateOrNot
#> Min. :25.00 Government Sector : 570 No : 295
#> 1st Qu.:28.00 Private Sector/Self Employed:1417 Yes:1692
#> Median :29.00
#> Mean :29.65
#> 3rd Qu.:32.00
#> Max. :35.00
#> AnnualIncome FamilyMembers ChronicDiseases FrequentFlyer
#> Min. : 300000 Min. :2.000 0:1435 No :1570
#> 1st Qu.: 600000 1st Qu.:4.000 1: 552 Yes: 417
#> Median : 900000 Median :5.000
#> Mean : 932763 Mean :4.753
#> 3rd Qu.:1250000 3rd Qu.:6.000
#> Max. :1800000 Max. :9.000
#> EverTravelledAbroad TravelInsurance
#> No :1607 Yes:1277
#> Yes: 380 No : 710
#>
#>
#>
#>
Cek proporsi kelas target
#> .
#> Yes No
#> 0.6426774 0.3573226
Naive Bayes
Cross Validation
✏️ Pisahkan data menjadi data test dan data train dengan perbandingan
75% : 25%. Pengambilan data secara acak menggunakan nilai seed 100.
Penggunaan seed dilakukan agar hasil pengacakan tetap.
RNGkind(sample.kind = "Rounding")
set.seed(100)
index_travel <- sample(nrow(travel_clean), nrow(travel_clean)*0.75)
travel_train <- travel_clean[index_travel, ]
travel_test <- travel_clean[-index_travel, ]#> .
#> Yes No
#> 0.6463087 0.3536913
Build Model
Dalam memodelkan Naive Bayes menggunakan data train dengan fungsi
naiveBayes(), dan cukup menambahkan parameter
laplace = 1
#> [1] "Age" "Employment.Type" "GraduateOrNot"
#> [4] "AnnualIncome" "FamilyMembers" "ChronicDiseases"
#> [7] "FrequentFlyer" "EverTravelledAbroad" "TravelInsurance"
# train model
model_naive <- naiveBayes(formula = TravelInsurance~., data = travel_train, laplace = 1)
model_naive#>
#> Naive Bayes Classifier for Discrete Predictors
#>
#> Call:
#> naiveBayes.default(x = X, y = Y, laplace = laplace)
#>
#> A-priori probabilities:
#> Y
#> Yes No
#> 0.6463087 0.3536913
#>
#> Conditional probabilities:
#> Age
#> Y [,1] [,2]
#> Yes 29.47560 2.633184
#> No 29.85389 3.337125
#>
#> Employment.Type
#> Y Government Sector Private Sector/Self Employed
#> Yes 0.3274611 0.6725389
#> No 0.1795841 0.8204159
#>
#> GraduateOrNot
#> Y No Yes
#> Yes 0.1585492 0.8414508
#> No 0.1436673 0.8563327
#>
#> AnnualIncome
#> Y [,1] [,2]
#> Yes 817808.9 330118.5
#> No 1137476.3 371507.4
#>
#> FamilyMembers
#> Y [,1] [,2]
#> Yes 4.638629 1.575621
#> No 4.952562 1.657919
#>
#> ChronicDiseases
#> Y 0 1
#> Yes 0.7181347 0.2818653
#> No 0.7126654 0.2873346
#>
#> FrequentFlyer
#> Y No Yes
#> Yes 0.8632124 0.1367876
#> No 0.6672968 0.3327032
#>
#> EverTravelledAbroad
#> Y No Yes
#> Yes 0.93056995 0.06943005
#> No 0.56899811 0.43100189
Model Prediction
Lakukan predict class pada data test, menggunakan fungsi
predict()
travel_predClass <- predict(object = model_naive, newdata = travel_test, type = "class")
head(travel_predClass)#> [1] Yes Yes No Yes No No
#> Levels: Yes No
Model Evaluation
Evaluasi hasil model dengan confusion matrix
# confusion matrix
library(caret)
confusionMatrix(data = travel_predClass,
reference = travel_test$TravelInsurance,
positive = "Yes")#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction Yes No
#> Yes 283 90
#> No 31 93
#>
#> Accuracy : 0.7565
#> 95% CI : (0.7163, 0.7937)
#> No Information Rate : 0.6318
#> P-Value [Acc > NIR] : 0.000000001884
#>
#> Kappa : 0.439
#>
#> Mcnemar's Test P-Value : 0.000000134411
#>
#> Sensitivity : 0.9013
#> Specificity : 0.5082
#> Pos Pred Value : 0.7587
#> Neg Pred Value : 0.7500
#> Prevalence : 0.6318
#> Detection Rate : 0.5694
#> Detection Prevalence : 0.7505
#> Balanced Accuracy : 0.7047
#>
#> 'Positive' Class : Yes
#>
📝 Berdasarkan hasil Confusion Matrix, dapat disimpulkan bahwa
tingkat akurasi model sebesar 75,65%. Lalu karena dalam hal ini, kami
menawarkan investasi perjalanan kepada pelanggan, dan ingin memprediksi
apakah pelanggan akan tertarik berinvestasi. Jadi, kami akan menggunakan
metrik Sensitivitas/Recall, yang memiliki tingkat
keberhasilan sebesar 90,13%.
ROC and AUC
Receiver-Operating Curve (ROC)
ROC adalah kurva yang menggambarkan hubungan antara True Positive Rate dengan False Positive Rate pada setiap threshold. Model yang baik idealnya memiliki True Positive Rate yang tinggi dan False Positive Rate yang rendah.
travel_predProb <- predict(object = model_naive, newdata = travel_test, type = "raw")
head(travel_predProb)#> Yes No
#> [1,] 0.87101836 0.12898164
#> [2,] 0.79449348 0.20550652
#> [3,] 0.04714785 0.95285215
#> [4,] 0.90178131 0.09821869
#> [5,] 0.04494304 0.95505696
#> [6,] 0.01639295 0.98360705
# ambil peluang kelas positif
pred_prob <- travel_predProb[,1]
# membuat prediction object supaya bisa menghitung nilai tpr, fpr, dan auc
bayes_roc <- prediction(predictions = pred_prob,
labels = travel_test$TravelInsurance)# performance
model_roc_naive <- performance(bayes_roc,
"tpr",
"fpr")
# membuat plot
plot(model_roc_naive)
abline(0,1 , lty = 2)Karena berbentuk visual, kurva ROC sulit untuk dibandingkan antar
model. Oleh karena itu diperlukan AUC.
Area Under ROC Curve (AUC)
AUC biasa digunakan untuk membandingkan performa antar model. Semakin
tinggi nilai AUC, semakin bagus performa modelnya. Untuk mendapatkan
nilai AUC, tulis auc pada parameter measure
dari performance() dan ambil nilai
y.values.
#> [[1]]
#> [1] 0.749913
📝 Hasil nilai AUC sebesar 0.74, maka dapat disimpulkan bahwa model
kita sudah baik dalam memisahkan kelas positif dan negatif.
Decision Tree
Cross Validation
✏️ Pisahkan data menjadi data test dan data train dengan perbandingan
75% : 25%.
RNGkind(sample.kind = "Rounding")
set.seed(100)
index_travel <- sample(nrow(travel_clean), nrow(travel_clean)*0.75)
travel_train <- travel_clean[index_travel, ]
travel_test <- travel_clean[-index_travel, ]Gunakan teknik downsample untuk mengurangi observasi
kelas mayoritas hingga seimbang dengan kelas minoritas.
# downsampling
RNGkind(sample.kind = "Rounding")
set.seed(100)
library(caret)
travel_train_down <- downSample(x = travel_train %>% select(-TravelInsurance),
y = travel_train$TravelInsurance,
yname = "TravelInsurance")Cek proporsi kelas target
#> .
#> Yes No
#> 0.5 0.5
Model Fitting
Untuk membuat model Decision Tree, dapat digunakan
fungsi ctree() dengan parameter:
formula= y ~ x
data= data
#>
#> Model formula:
#> TravelInsurance ~ Age + Employment.Type + GraduateOrNot + AnnualIncome +
#> FamilyMembers + ChronicDiseases + FrequentFlyer + EverTravelledAbroad
#>
#> Fitted party:
#> [1] root
#> | [2] AnnualIncome <= 1300000
#> | | [3] Age <= 32: Yes (n = 607, err = 29.2%)
#> | | [4] Age > 32
#> | | | [5] FamilyMembers <= 5: Yes (n = 120, err = 35.0%)
#> | | | [6] FamilyMembers > 5: No (n = 75, err = 10.7%)
#> | [7] AnnualIncome > 1300000
#> | | [8] EverTravelledAbroad in No
#> | | | [9] Age <= 25: No (n = 28, err = 3.6%)
#> | | | [10] Age > 25: No (n = 9, err = 44.4%)
#> | | [11] EverTravelledAbroad in Yes: No (n = 215, err = 2.8%)
#>
#> Number of inner nodes: 5
#> Number of terminal nodes: 6
📈 Dari hasil di atas, dapat dilihat ada error sebesar 2.8%, yang
artinya ada 215 data atau 2.8% yg kelasnya bukan positif.
Model Evaluation
Mari evaluasi travel_tree menggunakan confusion matrix
berdasarkan hasil prediksi di data test
# prediksi label kelas di data test
pred_test_label <- predict(travel_tree, newdata = travel_test, type = "response")
# confusion matrix data test
confusionMatrix(data = pred_test_label,
reference = travel_test$TravelInsurance,
positive= "Yes")#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction Yes No
#> Yes 305 71
#> No 9 112
#>
#> Accuracy : 0.839
#> 95% CI : (0.8037, 0.8703)
#> No Information Rate : 0.6318
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.6277
#>
#> Mcnemar's Test P-Value : 0.000000000009104
#>
#> Sensitivity : 0.9713
#> Specificity : 0.6120
#> Pos Pred Value : 0.8112
#> Neg Pred Value : 0.9256
#> Prevalence : 0.6318
#> Detection Rate : 0.6137
#> Detection Prevalence : 0.7565
#> Balanced Accuracy : 0.7917
#>
#> 'Positive' Class : Yes
#>
📝 Berdasarkan hasil Confusion Matrix, dapat disimpulkan bahwa
tingkat akurasi model sebesar 83,9%. Lalu karena dalam hal ini, kami
menawarkan investasi perjalanan kepada pelanggan, dan ingin memprediksi
apakah pelanggan akan tertarik berinvestasi. Jadi, kami akan menggunakan
metrik Sensitivitas/Recall, yang memiliki tingkat
keberhasilan sebesar 97,13%.
Random Forest
Cross Validation
✏️ Pisahkan data menjadi data test dan data train dengan perbandingan
75% : 25%.
Model Fitting
Model Random Forest akan menggunakan data OOB (Out-of-Bag) sebagai
data untuk melakukan evaluasi dengan cara menghitung error.
library(randomForest)
model_rf <- randomForest(TravelInsurance ~ ., data = travel_train, importance = TRUE,
ntree = 100)
model_rf#>
#> Call:
#> randomForest(formula = TravelInsurance ~ ., data = travel_train, importance = TRUE, ntree = 100)
#> Type of random forest: classification
#> Number of trees: 100
#> No. of variables tried at each split: 2
#>
#> OOB estimate of error rate: 17.18%
#> Confusion matrix:
#> Yes No class.error
#> Yes 933 30 0.03115265
#> No 226 301 0.42884250
📈 Nilai OOB error pada model sebesar 17,18%. Dengan kata lain,
akurasi model pada data OOB adalah 82,68%.
Prediction and Model Evaluation
pred_rf_test <- predict(model_rf, newdata = travel_test)
confusionMatrix(as.factor(pred_rf_test), travel_test$TravelInsurance, positive="Yes")#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction Yes No
#> Yes 308 76
#> No 6 107
#>
#> Accuracy : 0.835
#> 95% CI : (0.7994, 0.8666)
#> No Information Rate : 0.6318
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.6146
#>
#> Mcnemar's Test P-Value : 0.00000000000002541
#>
#> Sensitivity : 0.9809
#> Specificity : 0.5847
#> Pos Pred Value : 0.8021
#> Neg Pred Value : 0.9469
#> Prevalence : 0.6318
#> Detection Rate : 0.6197
#> Detection Prevalence : 0.7726
#> Balanced Accuracy : 0.7828
#>
#> 'Positive' Class : Yes
#>
📝 Berdasarkan hasil Confusion Matrix, dapat disimpulkan bahwa
tingkat akurasi model sebesar 83,5%. Lalu karena dalam hal ini, kami
menawarkan investasi perjalanan kepada pelanggan, dan ingin memprediksi
apakah pelanggan akan tertarik berinvestasi. Jadi, kami akan menggunakan
metrik Sensitivitas/Recall, yang memiliki tingkat
keberhasilan sebesar 98,09%.
Conclusion
Dalam hal ini, kami telah membuat beberapa model yang dapat
memprediksi apakah pelanggan akan tertarik untuk membeli asuransi
perjalanan berdasarkan parameter tertentu. Dan kami akan menggunakan
metrik Post Pred Value/Precision, karena ingin mendekati
atau menawarkan pelanggan sebanyak mungkin.
Jika dibandingkan dengan ketiga model lainnya yaitu Naive Bayes,
Decision Tree dan Random Forest. Dari model Naive Bayes memiliki nilai
tingkat accuracy 75,65% dan recall sebesar 90,13%. Yang kedua model
Decision Tree memiliki nilai tingkat accuracy 83,9%% dan recall sebesar
97,13%. Yang ketiga model Random Forest memiliki nilai tingkat accuracy
83,5%% dan recall sebesar 98,09%. Berdasarkan urutan tingkat
accuracy dan nilai precision, model
klasifikasi Random Forest adalah model terbaik.
Perusahaan dapat memprediksi calon pelanggan dengan lebih baik dan
mengurangi resiko penyediaan asuransi perjalanan dengan menggunakan
model ini.