Dewasa ini, mobil menjadi kebutuhan hidup bagi sebagian besar
masyarakat perkotaan. Peranan yang penting tersebut membuat banyak orang
berlomba-lomba membeli mobil dengan berbagai alasan. Tidak sedikit orang
yang menyesal setelah membeli mobil karena alasan yang kurang tepat.
Untuk mengatasi hal itu, kita perlu mempertimbangkan atribut-atribut
yang terdapat pada suatu mobil sehingga kita dapat menilai apakah mobil
tersebut layak untuk dibeli atau tidak layak dibeli. Namun tidak semua
orang memiliki keahlian atau waktu untuk mempelajari setiap atribut dari
suatu mobil terutama masyarakat perkotaan yang mengingkan sesuatu yang
cepat. Untuk itu diperlukan suatu metode, dimana dengan menggunakan
metode tersebut mampu memberikan hasil yang cepat dari banyak informasi
dan metode Machine Learing menjadi solusi.
Salah satu kemampuan dari machine learning yaitu mampu mempelajari
data-data yang belum pernah dilihat sebelumnnya dengan memanfaatkan
probabilitas, statistika, data historis dll. Kemampuan tersebut dapat
diaplikasikan untuk melakukan evaluasi data mobil, dimana melakukan
suatu evaluasi sebelum melakukan pembelian mobil adalah cara yang bijak
untuk terhindar dari kesalahan dalam pengambilan keputusan sebagai mana
yang dilakukan dalam projek ini.
Projek ini menggunakan data yang berasal dari kaggle yang terdiri
atas data klasifikasi class dan atribut-atribut mobil. Diharapkan dapat
diketahui apakah suatu harga mobil layak atau tidak berdasarkan atribut
kelas yang ada berdasarkan perbandingan beberapa metode machine learning
.
Dataset ini dapat diunduh melalui https://www.kaggle.com/datasets/elikplim/car-evaluation-data-set.
Berikut adalah kolom yang tersedia dalam dataset ini :
-
buying_price: Buying Level or Capacity of the customer
(Very High: vhigh, High: high, Low: low, Medium: med)
-
maint_cost: Maintenence Level (Very High: vhigh, High:
high, Low: low, Medium: med)
- doors: Number of
doors in the car (2, 3, 4, and 5 or more)
-
person_capacity: capacity in terms of persons to carry
(2, 4, and more)
- lug_boot: The size of the
Luggage Boot (small, med, big)
- safety: Safety
Level of Car (high, med, low)
- class:
Unacceptable, Acceptable, VeryGood, Good
1.Pembacaan Data
Pembacaan data menggunakan fungsi read_csv dan penggunaan parameter
stringsAsFactors dikarenakan seluruh datanya bertipe data
faktor.
## vhigh vhigh.1 X2 X2.1 small low unacc
## 1 vhigh vhigh 2 2 small med unacc
## 2 vhigh vhigh 2 2 small high unacc
## 3 vhigh vhigh 2 2 med low unacc
insight:
- seluruh data merupakan data
faktor
2. Pemahaman Data
1. Ubah nama kolom menggunakan ketentuan
berikut
Pengubahan nama kolom dilakukan agar nama kolom lebih informatif
dengan memanfaat kan library dplyr pada fungsi mutate. Kemudian dalam
penelitian ini levels class data diperkecil dari 4 class menjadi 2 class
menggunakn fungsi recode().
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
car <- car |>
select(
buying_price = vhigh,
maintenance_cost = vhigh.1,
doors = X2,
person_capacity = X2.1,
luggage_boot = small,
safety = low,
class = unacc
) |>
mutate(
class = recode(class,
'acc' = 'acceptable',
'good' = 'acceptable',
'vgood' = 'acceptable',
'unacc' = 'unaceptable')
)2. Cek Struktur Data
cek structure data untuk melihat kesesuaian tipe data.
## Rows: 1,727
## Columns: 7
## $ buying_price <fct> vhigh, vhigh, vhigh, vhigh, vhigh, vhigh, vhigh, vhig…
## $ maintenance_cost <fct> vhigh, vhigh, vhigh, vhigh, vhigh, vhigh, vhigh, vhig…
## $ doors <fct> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,…
## $ person_capacity <fct> 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, mo…
## $ luggage_boot <fct> small, small, med, med, med, big, big, big, small, sm…
## $ safety <fct> med, high, low, med, high, low, med, high, low, med, …
## $ class <fct> unaceptable, unaceptable, unaceptable, unaceptable, u…
insight:
- seluruh data merupakan data
faktor
_ data terdiri dari 1727 baris dan 7 kolom
- tidak ada
data yang perlu diubah
3. Cek Missing Value
dilakukan untuk mengilangkan data yang tidak informatif dan dapat
mempengaruhi hasil
## [1] FALSE
insight:
- dalam dataset ini tidak ada missing
value
1. Lihat Summary
## buying_price maintenance_cost doors person_capacity luggage_boot
## high :432 high :432 2 :431 2 :575 big :576
## low :432 low :432 3 :432 4 :576 med :576
## med :432 med :432 4 :432 more:576 small:575
## vhigh:431 vhigh:431 5more:432
## safety class
## high:576 acceptable : 518
## low :575 unaceptable:1209
## med :576
##
insight :
- pada kolom class, class data
unaceptable lebih banyak daripada class data acceptable
2. Cek Proporsi Kelas
##
## acceptable unaceptable
## 0.2999421 0.7000579
insight:
- dataset masih mengandung imbalance
data pada data target
Tahapan ini membagi data menjadi data test dan data train.
1. lakukan split data
Dilakukan proses spliting data dengan proporsi 80:20
## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
set.seed(100)
# train-test splitting
index <- sample(nrow(car), nrow(car)*0.80)
car_train <- car[index,]
car_test <- car[-index,]2. cek proporsi kelas
cek proporsi kelas pada data train sebagai data uji
##
## acceptable unaceptable
## 0.3019551 0.6980449
insight:
- dataset masih mengandung imbalance
data pada data train
- perlu dilakukan balancing data agar prediksi
yang dilakukan tidak hanya mampu memprediksi dengan baik hanya salah
satu kelas
3. Handling Imabalanced Data
balancing data dilakukan dengan menggunakan metode
upsampling.
## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
## Warning: package 'caret' was built under R version 4.3.1
## Loading required package: ggplot2
## Loading required package: lattice
4.Cek kembali proporsi data train
##
## acceptable unaceptable
## 0.5 0.5
insight:
- dataset sudah balance
- handling
imbalance data hanya dilakukan pada data train, karena untuk menjaga
originalitas data test
1. Membuat Model Naive Bayes
menggunakan fungsi naibeBayes dari library e1071. Dalam fungsi
disertakan parameter laplace untuk mengatasi keterbatasan
naiveBayes.
2. Membuat Pemodelan Prediksi
melakukan pemodelan prediksi pada data test
3. Membuat Pemodelan Evaluasi
melakukan evaluasi model menggunakan confusion matrix.
library(caret)
# confusion matrix
eval_naive_test <- confusionMatrix(data = car_test$pred_label, reference=car_test$class)
eval_naive_test## Confusion Matrix and Statistics
##
## Reference
## Prediction acceptable unaceptable
## acceptable 101 37
## unaceptable 0 208
##
## Accuracy : 0.8931
## 95% CI : (0.8556, 0.9236)
## No Information Rate : 0.7081
## P-Value [Acc > NIR] : < 0.00000000000000022
##
## Kappa : 0.7665
##
## Mcnemar's Test P-Value : 0.000000003252
##
## Sensitivity : 1.0000
## Specificity : 0.8490
## Pos Pred Value : 0.7319
## Neg Pred Value : 1.0000
## Prevalence : 0.2919
## Detection Rate : 0.2919
## Detection Prevalence : 0.3988
## Balanced Accuracy : 0.9245
##
## 'Positive' Class : acceptable
##
4. Menghitung Nilai ROC
Nilai ROC digunakan sebagai metrics evaluasi pada data-data yang
belum balance. Dalam hal ini dilakukan opsional karena sudah dilakukan
balancing data.
# ambil hasil prediksi dalam bentuk probability
car_pred_prob <- predict(object = model_nb,
newdata = car_test,
type = "raw")
head(car_pred_prob)## acceptable unaceptable
## [1,] 0.000001274331 0.9999987
## [2,] 0.515808467572 0.4841915
## [3,] 0.000514274723 0.9994857
## [4,] 0.476847591227 0.5231524
## [5,] 0.453431631749 0.5465684
## [6,] 0.440627962633 0.5593720
data_roc_naive <- data.frame(pred_prob = car_pred_prob[,"acceptable"],
actual = ifelse(car_test$class == "acceptable", 1, 0))
head(data_roc_naive)## pred_prob actual
## 1 0.000001274331 0
## 2 0.515808467572 0
## 3 0.000514274723 0
## 4 0.476847591227 0
## 5 0.453431631749 0
## 6 0.440627962633 0
5. Menghitung nilai AUC
## Warning: package 'ROCR' was built under R version 4.3.1
#object prediction
naive_roc <- prediction(predictions = data_roc_naive$pred_prob,
labels = data_roc_naive$actual)
# nilai AUC
naive_auc <- performance(naive_roc, measure = "auc")
naive_auc@y.values[[1]]## [1] 0.9952314
6. Menampilkan Plot Hasil Nilai AUC
plot(performance(naive_roc, "tpr", "fpr"))
abline(0, 1, lty = 2)
text(0.4, 0.6, paste("AUC = ", round(naive_auc@y.values[[1]], 2)))1. Membuat Pemodelan Decision Tree
## Loading required package: grid
## Loading required package: libcoin
## Loading required package: mvtnorm
model_dt <- ctree(formula = car_train$class ~.,
data = car_train %>% select(-class),
control = ctree_control(mincriterion=0.99))
plot(model_dt, type = "simple")2. Membuat Pemodelan Prediksi dan Evaluasi
# prediction to data test
pred_test_dt <- predict(model_dt, newdata = car_test)
eval_dt_test <- confusionMatrix(pred_test_dt, reference = car_test$class, positive = "acceptable")
eval_dt_test## Confusion Matrix and Statistics
##
## Reference
## Prediction acceptable unaceptable
## acceptable 101 10
## unaceptable 0 235
##
## Accuracy : 0.9711
## 95% CI : (0.9475, 0.9861)
## No Information Rate : 0.7081
## P-Value [Acc > NIR] : < 0.00000000000000022
##
## Kappa : 0.9321
##
## Mcnemar's Test P-Value : 0.004427
##
## Sensitivity : 1.0000
## Specificity : 0.9592
## Pos Pred Value : 0.9099
## Neg Pred Value : 1.0000
## Prevalence : 0.2919
## Detection Rate : 0.2919
## Detection Prevalence : 0.3208
## Balanced Accuracy : 0.9796
##
## 'Positive' Class : acceptable
##
3. Menghitung Nilai ROC
# ambil hasil prediksi dalam bentuk probability
car_pred_prob <- predict(object = model_dt,
newdata = car_test,
type = "prob")# menyiapkan pred vs actual
data_roc_dt <- data.frame(pred_prob = car_pred_prob[,"acceptable"],
actual = ifelse(car_test$class == "acceptable", 1, 0))
head(data_roc_dt)## pred_prob actual
## 6 0 0
## 14 0 0
## 18 0 0
## 38 0 0
## 47 0 0
## 49 0 0
4. Menghitung Nilai AUC
#object prediction
dt_roc <- prediction(predictions = data_roc_dt$pred_prob,
labels = data_roc_dt$actual)
# nilai AUC
dt_auc <- performance(dt_roc, measure = "auc")
dt_auc@y.values[[1]]## [1] 0.9872702
5. Menampilkan Plot Hasil Nilai AUC
plot(performance(dt_roc, "tpr", "fpr"))
abline(0, 1, lty = 2)
text(0.4, 0.6, paste("AUC = ", round(dt_auc@y.values[[1]], 2)))1. Membuat Pemodelan Random Forest
set.seed(417)
ctrl <- trainControl(method = "repeatedcv",
number = 5, # k-fold
repeats = 3) # repetisi
car_forest <- train(class ~ .,
data = car_train,
method = "rf", # random forest
trControl = ctrl)2. Membuat Pemodelan Evaluasi
#confusion matrix data test
pred_test_rf <- predict(car_forest, newdata = car_test)
eval_rf_test <- confusionMatrix(pred_test_rf, reference = car_test$class, positive = "acceptable")
eval_rf_test## Confusion Matrix and Statistics
##
## Reference
## Prediction acceptable unaceptable
## acceptable 100 10
## unaceptable 1 235
##
## Accuracy : 0.9682
## 95% CI : (0.9438, 0.984)
## No Information Rate : 0.7081
## P-Value [Acc > NIR] : < 0.0000000000000002
##
## Kappa : 0.9251
##
## Mcnemar's Test P-Value : 0.01586
##
## Sensitivity : 0.9901
## Specificity : 0.9592
## Pos Pred Value : 0.9091
## Neg Pred Value : 0.9958
## Prevalence : 0.2919
## Detection Rate : 0.2890
## Detection Prevalence : 0.3179
## Balanced Accuracy : 0.9746
##
## 'Positive' Class : acceptable
##
3. Menghitung Nilai ROC
# ambil hasil prediksi dalam bentuk probability
car_pred_prob <- predict(object = car_forest,
newdata = car_test,
type = "prob")
head(car_pred_prob)## acceptable unaceptable
## 6 0.000 1.000
## 14 0.000 1.000
## 18 0.000 1.000
## 38 0.000 1.000
## 47 0.194 0.806
## 49 0.000 1.000
# menyiapkan pred vs actual
data_roc_rf <- data.frame(pred_prob = car_pred_prob[,"acceptable"],
actual = ifelse(car_test$class == "acceptable", 1, 0))
head(data_roc_rf)## pred_prob actual
## 1 0.000 0
## 2 0.000 0
## 3 0.000 0
## 4 0.000 0
## 5 0.194 0
## 6 0.000 0
4. Menghitung Nilai AUC
library(ROCR)
#object prediction
rf_roc <- prediction(predictions = data_roc_rf$pred_prob,
labels = data_roc_rf$actual)
# nilai AUC
rf_auc <- performance(rf_roc, measure = "auc")
rf_auc@y.values[[1]]## [1] 0.9920388
plot(performance(rf_roc, "tpr", "fpr"))
abline(0, 1, lty = 2)
text(0.4, 0.6, paste("AUC = ", round(rf_auc@y.values[[1]], 2)))1. Komparasi antar Model
eval_naive <- data_frame(Accuracy = eval_naive_test$overall[1],
Recall = eval_naive_test$byClass[1],
Specificity = eval_naive_test$byClass[2],
Precision = eval_naive_test$byClass[3],
AUC=naive_auc@y.values[[1]])## Warning: `data_frame()` was deprecated in tibble 1.1.0.
## ℹ Please use `tibble()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
eval_dt <- data_frame(Accuracy = eval_dt_test$overall[1],
Recall = eval_dt_test$byClass[1],
Specificity = eval_dt_test$byClass[2],
Precision = eval_dt_test$byClass[3],
AUC=dt_auc@y.values[[1]])
eval_rf <- data_frame(Accuracy = eval_rf_test$overall[1],
Recall = eval_rf_test$byClass[1],
Specificity = eval_rf_test$byClass[2],
Precision = eval_rf_test$byClass[3],
AUC=rf_auc@y.values[[1]])
eval_all <- rbind("Naive Bayes" = eval_naive, "Decision Tree" = eval_dt, "Random Forest" = eval_rf)
eval_all <- eval_all |> mutate(
name = c('Naive Bayes','Decision Tree', 'Random Forest')
) |> select(
name, Accuracy, Recall, Specificity, Precision, AUC
)
eval_all## # A tibble: 3 × 6
## name Accuracy Recall Specificity Precision AUC
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Naive Bayes 0.893 1 0.849 0.732 0.995
## 2 Decision Tree 0.971 1 0.959 0.910 0.987
## 3 Random Forest 0.968 0.990 0.959 0.909 0.992
insight :
- dari tabel diatas diketahui bahwa
nilai Precision tertinggi diperoleh oleh model decision tree, Decision
Tree mampu memprediksi dengan baik nilai Recall dibandingkan nilai lain
- nilai AUC sangat baik hampir mendekati sempurna, hal ini
disebabkan proporsi data yang digunakan telah dilakukan upsampling
2. Interpretasi metrics yang digunakan
FN: model memprediksi unacceptable(harga mobil tidak
layak beli), padahal aslinya acceptable(harga mobil layak beli).
-
Resiko: Customer kehilangan kesempatan membeli mobil murah.
FP: model memprediksi acceptable(harga mobil layak
beli), padahal unacceptable(harga mobil tidak layak beli).
- Resiko:
Customer rugi karena mendapat barang yang kurang sesuai.
Risiko yang concerning adalah jika terjadi kejadian FP sehingga ambil metriks evaluasi Precision
-sebagai sebagai seorang data scientist saya akan menggunakan metode
Decision Tree untuk melakukan klasifikasi kelas evaluasi harga mobil dan
menggunakan Recall untuk mengehindari potensi kerugian setelah
pembelian.