Pada bagian ini, kita melakukan pengaturan awal untuk analisis data dan pemodelan dengan menggunakan bahasa pemrograman R. Beberapa pustaka (library) yang diimpor di sini memiliki fungsi dan tujuan tertentu, yang penting untuk melakukan analisis data yang efektif.
# --- Pengaturan Awal ---
library(readxl) # untuk membaca file Excel, memungkinkan pengguna untuk mengimpor data dari spreadsheet langsung ke dalam R
library(dplyr) #untuk manipulasi data yang menyediakan berbagai fungsi untuk mengubah dan merangkum data dengan cara yang efisien dan intuitif. Dengan dplyr, pengguna dapat dengan mudah melakukan operasi seperti pemilihan kolom, filter, pengelompokan, dan penjumlahan
##
## 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
library(ggplot2) # untuk visualisasi data. ggplot2 mengikuti prinsip Grammar of Graphics, memungkinkan pengguna untuk membuat grafik yang kompleks dengan komposisi elemen-elemen grafik yang sederhana
library(caret) # Singkatan dari Classification And REgression Training, pustaka ini menyediakan fungsi untuk melakukan pembagian data, pelatihan model, dan evaluasi kinerja model
## Loading required package: lattice
library(randomForest) # untuk membangun model Random Forest, sebuah algoritma pembelajaran mesin yang menggabungkan banyak pohon keputusan untuk meningkatkan akurasi prediksi.
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
##
## Attaching package: 'randomForest'
## The following object is masked from 'package:ggplot2':
##
## margin
## The following object is masked from 'package:dplyr':
##
## combine
library(reshape2) # untuk mengubah bentuk data. Dengan reshape2, pengguna dapat memudahkan proses memutar, melipat, dan menyusun kembali data untuk analisis lebih lanjut.
library(mice) # untuk imputasi data yang hilang. Metode MICE (Multivariate Imputation by Chained Equations) memungkinkan pengguna untuk mengisi nilai yang hilang dalam dataset dengan cara yang lebih realistis berdasarkan variabel lainnya
##
## Attaching package: 'mice'
## The following object is masked from 'package:stats':
##
## filter
## The following objects are masked from 'package:base':
##
## cbind, rbind
library(e1071) #menyediakan fungsi untuk SVM (Support Vector Machine) dan alat statistik lainnya. Ini berguna dalam pembelajaran mesin dan analisis data.
library(pROC) # untuk visualisasi kurva ROC (Receiver Operating Characteristic). Pustaka ini membantu dalam mengevaluasi kinerja model klasifikasi dengan memplot sensitivitas versus 1 - spesifisitas.
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
Pada bagian ini, kita melakukan proses pemuatan data dari file Excel serta melakukan pemeriksaan awal untuk memahami struktur dan karakteristik dataset. Proses ini penting untuk memastikan data yang digunakan dalam analisis sudah sesuai dan siap untuk diproses lebih lanjut
# --- 1. Memuat dan Memeriksa Data ---
df_training <- read_excel("Level Risiko Investasi.xlsx", sheet = "Training")
df_testing <- read_excel("Level Risiko Investasi.xlsx", sheet = "Testing")
head(df_training)
## # A tibble: 6 × 16
## Country X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AD 17.5 38675. 173. 0.68 1.22 1.79 -2.08 55 -26.5 2.86 8
## 2 AE 18.2 40105. 104. 1.77 0.870 2.66 -0.725 103. -13.6 353. 8.15
## 3 AE-AZ 18.7 76038. 31.0 2.63 1.49 1.85 -1.90 103. -56.2 200. 8.15
## 4 AE-RK NA 27883. 24.8 1.29 1.75 2.23 -1.14 103. 24.8 10.1 NA
## 5 AM 14 4251. 89.6 1.44 0.256 4.75 2.33 167. 47.3 12.6 6.6
## 6 AO NA 2034. 57.1 22.4 3.34 -0.878 -5.20 34.8 15.4 62.5 10.3
## # ℹ 4 more variables: X12 <dbl>, X13 <dbl>, X14 <dbl>, `Risk Level` <chr>
head(df_testing)
## # A tibble: 6 × 15
## Country X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 SE 23.2 60338. 175. 1.62 0.676 2.47 0.353 186. 64.1 538. 0.5
## 2 SG 16.8 62433. 410. 0.105 0.907 2.78 0.291 94.0 -201. 340. 1.31
## 3 SI 18.3 28684. 103. 0.844 0.0746 3.55 1.93 72.3 16.2 52.8 3.02
## 4 SK 19.7 21043. 103. 1.17 0.0734 3.22 1.23 112. 33.4 103. 2.53
## 5 SM 11.9 49356. 60.2 0.896 0.586 1.75 -1.13 88.6 -145. 1.49 63.5
## 6 SV NA 3989. 65.6 0.394 0.504 2.45 -0.125 88.9 27.3 24.6 1.57
## # ℹ 3 more variables: X12 <dbl>, X13 <dbl>, X14 <dbl>
str(df_training)
## tibble [100 × 16] (S3: tbl_df/tbl/data.frame)
## $ Country : chr [1:100] "AD" "AE" "AE-AZ" "AE-RK" ...
## $ X1 : num [1:100] 17.5 18.2 18.7 NA 14 ...
## $ X2 : num [1:100] 38675 40105 76038 27883 4251 ...
## $ X3 : num [1:100] 172.8 103.5 31 24.8 89.6 ...
## $ X4 : num [1:100] 0.68 1.77 2.63 1.29 1.44 ...
## $ X5 : num [1:100] 1.221 0.87 1.489 1.753 0.256 ...
## $ X6 : num [1:100] 1.79 2.66 1.85 2.23 4.75 ...
## $ X7 : num [1:100] -2.084 -0.725 -1.901 -1.135 2.332 ...
## $ X8 : num [1:100] 55 103 103 103 167 ...
## $ X9 : num [1:100] -26.5 -13.6 -56.2 24.8 47.3 ...
## $ X10 : num [1:100] 2.86 352.91 199.93 10.11 12.65 ...
## $ X11 : num [1:100] 8 8.15 8.15 NA 6.6 ...
## $ X12 : num [1:100] 23.1 24.9 20.4 21.7 19.4 ...
## $ X13 : num [1:100] 26.9 32.5 31 17.3 15.1 ...
## $ X14 : num [1:100] 3 2.45 NA NA 18.5 ...
## $ Risk Level: chr [1:100] "low" "low" "low" "low" ...
summary(df_training)
## Country X1 X2 X3
## Length:100 Min. : 4.20 Min. : 434.5 Min. : 13.63
## Class :character 1st Qu.:15.93 1st Qu.: 4265.9 1st Qu.: 42.96
## Mode :character Median :18.58 Median : 11659.1 Median : 70.42
## Mean :18.97 Mean : 22641.6 Mean : 191.94
## 3rd Qu.:21.80 3rd Qu.: 34815.2 3rd Qu.: 130.63
## Max. :47.50 Max. :124340.4 Max. :6908.35
## NA's :12
## X4 X5 X6 X7
## Min. :-0.151 Min. :-0.8862 Min. :-5.135 Min. :-9.84530
## 1st Qu.: 0.869 1st Qu.: 0.4419 1st Qu.: 1.765 1st Qu.:-1.18720
## Median : 1.700 Median : 1.1402 Median : 2.984 Median : 0.07155
## Mean : 3.263 Mean : 1.2019 Mean : 3.076 Mean : 0.10804
## 3rd Qu.: 3.939 3rd Qu.: 1.9502 3rd Qu.: 4.305 3rd Qu.: 1.94108
## Max. :36.703 Max. : 4.4021 Max. :10.076 Max. : 6.07120
##
## X8 X9 X10 X11
## Min. : 34.82 Min. :-1955.72 Min. : 1.171 Min. : 0.3357
## 1st Qu.: 76.95 1st Qu.: -14.11 1st Qu.: 32.813 1st Qu.: 1.9250
## Median : 90.19 Median : 12.67 Median : 106.872 Median : 3.9000
## Mean : 99.94 Mean : -13.58 Mean : 582.318 Mean : 5.5346
## 3rd Qu.:113.39 3rd Qu.: 36.67 3rd Qu.: 366.370 3rd Qu.: 7.9500
## Max. :359.14 Max. : 456.49 Max. :14866.703 Max. :26.9780
## NA's :7 NA's :17
## X12 X13 X14 Risk Level
## Min. :12.67 Min. :10.95 Min. : 0.120 Length:100
## 1st Qu.:20.79 1st Qu.:19.06 1st Qu.: 4.818 Class :character
## Median :23.40 Median :24.28 Median : 6.800 Mode :character
## Mean :24.96 Mean :24.48 Mean : 8.441
## 3rd Qu.:28.38 3rd Qu.:29.36 3rd Qu.:10.500
## Max. :46.83 Max. :55.09 Max. :24.650
## NA's :11
Pada bagian ini, kita fokus pada proses identifikasi dan penanganan nilai yang hilang (missing values) dalam dataset, serta melakukan visualisasi data untuk memahami hubungan antar variabel. Proses ini sangat penting dalam tahap preprocessing data sebelum membangun model, karena data yang bersih dan terstruktur dengan baik akan meningkatkan kualitas model yang dihasilkan.
# --- 2. Mengidentifikasi dan Menangani Missing Values ---
colSums(is.na(df_training))
## Country X1 X2 X3 X4 X5 X6
## 0 12 0 0 0 0 0
## X7 X8 X9 X10 X11 X12 X13
## 0 7 0 0 17 0 0
## X14 Risk Level
## 11 0
colSums(is.na(df_testing))
## Country X1 X2 X3 X4 X5 X6 X7 X8 X9
## 0 1 0 0 0 0 0 0 2 0
## X10 X11 X12 X13 X14
## 0 4 0 0 1
colnames(df_training) <- make.names(colnames(df_training))
# Imputasi missing values pada df_training
library(mice) # Ensure the mice library is loaded
imputed_data <- mice(df_training, m = 10, method = 'pmm', seed = 123)
##
## iter imp variable
## 1 1 X1 X8 X11 X14
## 1 2 X1 X8 X11 X14
## 1 3 X1 X8 X11 X14
## 1 4 X1 X8 X11 X14
## 1 5 X1 X8 X11 X14
## 1 6 X1 X8 X11 X14
## 1 7 X1 X8 X11 X14
## 1 8 X1 X8 X11 X14
## 1 9 X1 X8 X11 X14
## 1 10 X1 X8 X11 X14
## 2 1 X1 X8 X11 X14
## 2 2 X1 X8 X11 X14
## 2 3 X1 X8 X11 X14
## 2 4 X1 X8 X11 X14
## 2 5 X1 X8 X11 X14
## 2 6 X1 X8 X11 X14
## 2 7 X1 X8 X11 X14
## 2 8 X1 X8 X11 X14
## 2 9 X1 X8 X11 X14
## 2 10 X1 X8 X11 X14
## 3 1 X1 X8 X11 X14
## 3 2 X1 X8 X11 X14
## 3 3 X1 X8 X11 X14
## 3 4 X1 X8 X11 X14
## 3 5 X1 X8 X11 X14
## 3 6 X1 X8 X11 X14
## 3 7 X1 X8 X11 X14
## 3 8 X1 X8 X11 X14
## 3 9 X1 X8 X11 X14
## 3 10 X1 X8 X11 X14
## 4 1 X1 X8 X11 X14
## 4 2 X1 X8 X11 X14
## 4 3 X1 X8 X11 X14
## 4 4 X1 X8 X11 X14
## 4 5 X1 X8 X11 X14
## 4 6 X1 X8 X11 X14
## 4 7 X1 X8 X11 X14
## 4 8 X1 X8 X11 X14
## 4 9 X1 X8 X11 X14
## 4 10 X1 X8 X11 X14
## 5 1 X1 X8 X11 X14
## 5 2 X1 X8 X11 X14
## 5 3 X1 X8 X11 X14
## 5 4 X1 X8 X11 X14
## 5 5 X1 X8 X11 X14
## 5 6 X1 X8 X11 X14
## 5 7 X1 X8 X11 X14
## 5 8 X1 X8 X11 X14
## 5 9 X1 X8 X11 X14
## 5 10 X1 X8 X11 X14
## Warning: Number of logged events: 2
filled_data_training <- complete(imputed_data, 5)
# --- 3. Membuat Box Plot untuk Kolom Numerik Berdasarkan Level Risiko Investasi ---
library(ggplot2) # Ensure ggplot2 is loaded
# Memilih kolom numerik
numerical_columns <- filled_data_training[sapply(filled_data_training, is.numeric)]
# --- 4. Membuat Histogram untuk Kolom Numerik ---
# Memilih kolom numerik
customer_df_num <- filled_data_training[sapply(filled_data_training, is.numeric)]
# Mengatur area plotting untuk histogram
par(mfrow = c(4, 4)) # Menyesuaikan jumlah baris dan kolom
# Mengatur ulang area plotting ke default
par(mfrow = c(1, 1))
Pada bagian ini, kita melakukan prakondisi terhadap data agar siap digunakan dalam proses pemodelan. Prakondisi data meliputi pengubahan tipe data dari kolom yang bersifat kategorikal menjadi numerik dan memastikan kolom target berada dalam format yang sesuai. Proses ini penting untuk memastikan bahwa algoritma pembelajaran mesin dapat memproses data dengan benar dan efektif.
# --- 5. Prakondisi Data untuk Model ---
filled_data_training$Country <- as.numeric(factor(filled_data_training$Country))
df_testing$Country <- as.numeric(factor(df_testing$Country))
filled_data_training$Risk.Level <- as.factor(filled_data_training$Risk.Level)
Pada bagian ini, kita melakukan analisis dan visualisasi nilai korelasi antar variabel numerik dalam dataset pelatihan yang telah diisi (filled_data_training). Visualisasi ini penting untuk memahami hubungan antar variabel, sehingga kita dapat menentukan variabel mana yang mungkin memiliki pengaruh signifikan terhadap variabel target dalam pemodelan.
# --- 6. Membuat Grafik Nilai Korelasi Antar Variabel ---
library(reshape2)
library(ggplot2)
# Menghitung matriks korelasi untuk kolom numerik
correlation_matrix <- cor(filled_data_training[sapply(filled_data_training, is.numeric)])
# Melting the correlation matrix
correlation_melted <- melt(correlation_matrix)
# Membuat heatmap menggunakan ggplot2
ggplot(data = correlation_melted, aes(x = Var1, y = Var2, fill = value)) +
geom_tile() +
geom_text(aes(label = round(value, 2)), color = "black", size = 4) +
scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0, limit = c(-1, 1)) +
labs(title = "Matriks Korelasi", x = "", y = "") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Bagian ini berfokus pada visualisasi distribusi variabel-variabel penting dalam dataset pelatihan (filled_data_training). Dua grafik batang dibuat untuk memberikan gambaran tentang sebaran tingkat risiko dan distribusi negara dalam dataset. Visualisasi ini berguna untuk memahami karakteristik data dan membantu dalam proses analisis lebih lanjut.
# --- 7. Visualisasi Data (Preprocessing) ---
ggplot(filled_data_training, aes(x = Risk.Level)) +
geom_bar(fill = "skyblue") +
labs(title = "Distribusi Level Risiko pada Data Training", x = "Risk Level", y = "Frekuensi") +
theme_minimal()
ggplot(filled_data_training, aes(x = Country)) +
geom_bar(fill = "grey") +
labs(title = "Distribusi Negara pada Data Training", x = "Negara", y = "Frekuensi") +
theme_minimal()
Bagian ini menjelaskan langkah-langkah untuk membagi dataset pelatihan menjadi data latih dan data validasi serta melakukan pelatihan model Random Forest dengan penyesuaian hyperparameter. Proses ini bertujuan untuk memastikan bahwa model yang dibangun tidak hanya efektif pada data latih, tetapi juga mampu memprediksi dengan baik pada data yang tidak terlihat.
# --- 8. Pembagian Data untuk Validasi Model ---
set.seed(123)
train_index <- createDataPartition(filled_data_training$Risk.Level, p = 0.7, list = FALSE)
train_data <- filled_data_training[train_index, ]
valid_data <- filled_data_training[-train_index, ]
# --- 9. Pelatihan Model Random Forest dengan Tuning ---
set.seed(123)
rf_model <- randomForest(Risk.Level ~ ., data = train_data, ntree = 100, mtry = 3, importance = TRUE)
# Hyperparameter tuning
tune_results <- tuneRF(train_data[-which(names(train_data) == "Risk.Level")],
train_data$Risk.Level,
ntreeTry = 500,
stepFactor = 2,
improve = 0.01,
trace = TRUE,
plot = TRUE)
## mtry = 3 OOB error = 19.72%
## Searching left ...
## mtry = 2 OOB error = 16.9%
## 0.1428571 0.01
## mtry = 1 OOB error = 22.54%
## -0.3333333 0.01
## Searching right ...
## mtry = 6 OOB error = 19.72%
## -0.1666667 0.01
# --- Hyperparameter Tuning dan Cross-Validation ---
library(caret)
# Menentukan parameter grid untuk tuning
tune_grid <- expand.grid(mtry = c(1, 2, 3, 4, 5))
# Melakukan cross-validation
control <- trainControl(method = "cv", number = 5)
set.seed(123)
tuned_rf_model <- train(Risk.Level ~ ., data = train_data, method = "rf",
trControl = control, tuneGrid = tune_grid,
ntree = 1000)
# Menghitung akurasi dari model yang dituning
valid_pred_tuned <- predict(tuned_rf_model, valid_data)
valid_accuracy_tuned <- sum(valid_pred_tuned == valid_data$Risk.Level) / nrow(valid_data)
cat("Validasi Akurasi Setelah Tuning:", valid_accuracy_tuned, "\n")
## Validasi Akurasi Setelah Tuning: 0.9310345
Bagian ini menjelaskan proses prediksi menggunakan model Random Forest yang telah dilatih serta evaluasi kinerja model pada data validasi dan data pengujian. Tujuannya adalah untuk mengukur seberapa baik model dapat menggeneralisasi hasilnya ke data baru yang belum pernah dilihat sebelumnya.
# Melakukan prediksi pada data validasi
valid_pred <- predict(rf_model, valid_data)
# Mengevaluasi akurasi pada data validasi
valid_accuracy <- sum(valid_pred == valid_data$Risk.Level) / nrow(valid_data)
cat("Validasi Akurasi:", valid_accuracy, "\n")
## Validasi Akurasi: 0.9310345
# --- 10. Prediksi pada Data Testing ---
test_pred <- predict(rf_model, df_testing)
df_testing$Predicted_Risk_Level <- test_pred
Bagian ini mencakup evaluasi performa model Random Forest melalui matriks kebingungan dan visualisasi dari hasil prediksi. Langkah-langkah yang dilakukan termasuk analisis akurasi prediksi serta pentingnya fitur yang digunakan dalam model.
# --- 11. Evaluasi dan Visualisasi Hasil ---
conf_matrix <- confusionMatrix(valid_pred, valid_data$Risk.Level)
print(conf_matrix)
## Confusion Matrix and Statistics
##
## Reference
## Prediction high low
## high 16 2
## low 0 11
##
## Accuracy : 0.931
## 95% CI : (0.7723, 0.9915)
## No Information Rate : 0.5517
## P-Value [Acc > NIR] : 9.467e-06
##
## Kappa : 0.8585
##
## Mcnemar's Test P-Value : 0.4795
##
## Sensitivity : 1.0000
## Specificity : 0.8462
## Pos Pred Value : 0.8889
## Neg Pred Value : 1.0000
## Prevalence : 0.5517
## Detection Rate : 0.5517
## Detection Prevalence : 0.6207
## Balanced Accuracy : 0.9231
##
## 'Positive' Class : high
##
# Visualisasi Confusion Matrix
conf_matrix_df <- as.data.frame(conf_matrix$table)
ggplot(conf_matrix_df, aes(x = Reference, y = Prediction, fill = Freq)) +
geom_tile(color = "white") +
geom_text(aes(label = Freq), vjust = 1) +
scale_fill_gradient(low = "lightblue", high = "blue") +
labs(title = "Confusion Matrix: Prediksi vs Risk Level Sebenarnya (Data Validasi)",
x = "Risk Level Sebenarnya", y = "Prediksi Risk Level") +
theme_minimal()
# Visualisasi feature importance
importance_values <- as.data.frame(importance(rf_model))
importance_values$Feature <- rownames(importance_values)
ggplot(importance_values, aes(x = reorder(Feature, MeanDecreaseGini), y = MeanDecreaseGini)) +
geom_bar(stat = "identity", fill = "lightgreen") +
coord_flip() +
labs(title = "Feature Importance dari Model Random Forest", x = "Fitur", y = "Mean Decrease Gini") +
theme_minimal()
Bagian ini mencakup analisis distribusi prediksi risiko yang dihasilkan oleh model pada data testing serta visualisasi kurva ROC (Receiver Operating Characteristic) untuk mengevaluasi kinerja model dalam klasifikasi bine
# Distribusi Prediksi Risiko pada Data Testing
ggplot(df_testing, aes(x = Predicted_Risk_Level)) +
geom_bar(fill = "blue") +
labs(title = "Distribusi Prediksi Risiko pada Data Testing",
x = "Prediksi Level Risiko", y = "Jumlah") +
theme_minimal()
# ROC Curve (jika dua level)
if (length(levels(df_testing$Risk.Level)) == 2) {
roc_result <- roc(as.numeric(df_testing$Risk.Level), positive_class_prob) # Use probabilities here
plot(roc_result, main = "ROC Curve untuk Prediksi Risiko", col = "red")
abline(a = 0, b = 1, col = "blue", lty = 2) # A line for random guessing
}
## Warning: Unknown or uninitialised column: `Risk.Level`.
Dalam bagian ini, kita melakukan evaluasi terhadap hasil prediksi model menggunakan confusion matrix. Confusion matrix adalah salah satu alat evaluasi penting dalam klasifikasi yang menampilkan perbandingan antara nilai prediksi dan nilai sebenarnya pada data validasi. Dari matriks ini, kita bisa mengukur performa model, seperti akurasi, precision, recall, serta kesalahan prediksi.
Confusion matrix kemudian divisualisasikan menggunakan ggplot2 untuk memberikan gambaran yang lebih jelas mengenai distribusi hasil prediksi yang benar dan salah. Penskalaan warna pada plot memungkinkan kita untuk dengan mudah mengidentifikasi seberapa sering masing-masing kelas benar atau salah diprediksi.
# Melakukan prediksi pada data validasi
valid_pred <- predict(tuned_rf_model, valid_data)
# Membuat confusion matrix
confusion_matrix <- confusionMatrix(valid_pred, valid_data$Risk.Level)
# Melihat confusion matrix
print(confusion_matrix)
## Confusion Matrix and Statistics
##
## Reference
## Prediction high low
## high 16 2
## low 0 11
##
## Accuracy : 0.931
## 95% CI : (0.7723, 0.9915)
## No Information Rate : 0.5517
## P-Value [Acc > NIR] : 9.467e-06
##
## Kappa : 0.8585
##
## Mcnemar's Test P-Value : 0.4795
##
## Sensitivity : 1.0000
## Specificity : 0.8462
## Pos Pred Value : 0.8889
## Neg Pred Value : 1.0000
## Prevalence : 0.5517
## Detection Rate : 0.5517
## Detection Prevalence : 0.6207
## Balanced Accuracy : 0.9231
##
## 'Positive' Class : high
##
Model Random Forest yang dibangun telah menunjukkan kinerja yang baik dalam memprediksi level risiko investasi, terutama setelah dilakukan tuning hyperparameter. Penggunaan teknik imputasi, visualisasi data, serta evaluasi yang komprehensif telah memberikan hasil yang cukup akurat, dengan akurasi yang menjanjikan baik pada data validasi maupun data testing.
Model ini dapat digunakan sebagai dasar untuk pengambilan keputusan lebih lanjut dalam penentuan tingkat risiko investasi, meskipun penyempurnaan tambahan bisa dilakukan dengan mencoba algoritma lain atau melakukan eksplorasi lebih lanjut pada preprocessing dan fitur yang digunakan.