Sebelum menjalankan program, perlu menginstall dan mengaktifkan
package-package yang akan diperlukan. Beberapa package yang digunakan
adalah tidyverse
untuk manipulasi data,
tidymodels
untuk framework pemodelan, xgboost
untuk membangun model XGBoost, serta package lainnya seperti
recipes
, themis
, dan DALEX
untuk
membantu analisis dan visualisasi hasil. Semua package ini harus
diinstal sebelumnya dengan menggunakan perintah
install.packages()
jika belum tersedia dan jika sudah
mengaktifkannya dengan printah ‘library’.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tidymodels)
## ── Attaching packages ────────────────────────────────────── tidymodels 1.2.0 ──
## ✔ broom 1.0.7 ✔ rsample 1.2.1
## ✔ dials 1.3.0 ✔ tune 1.2.1
## ✔ infer 1.0.7 ✔ workflows 1.1.4
## ✔ modeldata 1.4.0 ✔ workflowsets 1.1.0
## ✔ parsnip 1.2.1 ✔ yardstick 1.3.2
## ✔ recipes 1.1.0
## ── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
## ✖ scales::discard() masks purrr::discard()
## ✖ dplyr::filter() masks stats::filter()
## ✖ recipes::fixed() masks stringr::fixed()
## ✖ dplyr::lag() masks stats::lag()
## ✖ yardstick::spec() masks readr::spec()
## ✖ recipes::step() masks stats::step()
## • Use suppressPackageStartupMessages() to eliminate package startup messages
library(brulee)
library(themis)
library(tictoc)
library(DALEX)
## Welcome to DALEX (version: 2.4.3).
## Find examples and detailed introduction at: http://ema.drwhy.ai/
## Additional features will be available after installation of: ggpubr.
## Use 'install_dependencies()' to get all suggested dependencies
##
## Attaching package: 'DALEX'
##
## The following object is masked from 'package:dplyr':
##
## explain
library(DALEXtra)
library(xgboost)
##
## Attaching package: 'xgboost'
##
## The following object is masked from 'package:dplyr':
##
## slice
library(corrplot)
## corrplot 0.95 loaded
library(caret)
## Loading required package: lattice
##
## Attaching package: 'caret'
##
## The following objects are masked from 'package:yardstick':
##
## precision, recall, sensitivity, specificity
##
## The following object is masked from 'package:purrr':
##
## lift
library(recipes)
library(lubridate)
library(dplyr)
library(parsnip)
library(ggplot2)
Data yang digunakan merupakan data customer telekomuonikasi seluler. Di mana perusahaan akan melakukan Kerjasama dengan sebuah bank untuk meningkatkan angka recharge pelanggan pra-bayar melalui channel perbankan. Mereka ingin memperoleh model yang dapat digunakan untuk memprediksi pelanggan mana saja yang potensial untuk diajak menggunakan channel tersebut.
data_train <- read.csv("trainingdata.csv")
data_train$Y <- as.factor(data_train$Y) # Menjadikan kolom 'Y' factor
data_train <- data_train[, -1] # Menghapus kolom ID
str(data_train)
## 'data.frame': 45000 obs. of 12 variables:
## $ X1 : int 1 627 42 209 11 117 144 184 3 3 ...
## $ X2 : int 760 41160 19002 76895 12650 55057 29560 56162 9835 6603 ...
## $ X3 : int 1 97 38 262 10 121 66 57 7 4 ...
## $ X4 : num 0.5 0.707 0.75 0.772 0.604 ...
## $ X5 : num 1 0.998 0.964 0.978 0.376 ...
## $ X6 : int 3275 2864 2794 14061 16131 4222 2439 6953 16414 18458 ...
## $ X7 : num 0.962 0.723 0.748 0.675 0.145 ...
## $ X8 : int 2542 0 0 0 0 0 74 8 0 666 ...
## $ X9 : int 43544 0 0 0 0 0 120 13 0 1080 ...
## $ X10: num 1.3 9.3 4 24.7 10 8.7 4.3 4.3 8.7 5.7 ...
## $ X11: num 1.3 5 1 9.7 5.3 6 3.7 3 4 4 ...
## $ Y : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
Data training terdiri dari 45000 baris dengan 11 peubah prediktor dan
1 peubah target yang diubah menjadi tipe factor menggunakan fungsi
as.factor()
. Selain itu, kolom ID dihapus karena tidak
memberikan informasi relevan untuk pemodelan. Fungsi str()
digunakan untuk melihat struktur data. Hasilnya menunjukkan 11 peubah
numerik sebagai prediktor sementara peubah repson (Y) adalah data
kategori yang menjadi target klasifikasi. Adapun keterangan peubah
adalah sebagai berikut :
data_test <- read.csv("testingdata.csv")
data_test <- data_test[, -1]
str(data_test)
## 'data.frame': 5000 obs. of 11 variables:
## $ X1 : int 65 16 521 215 0 173 564 85 112 234 ...
## $ X2 : int 38253 2491 90652 25307 159 16631 23018 23755 71681 46011 ...
## $ X3 : int 43 3 166 42 0 76 58 17 125 73 ...
## $ X4 : num 0.779 0.464 0.764 0.727 1 ...
## $ X5 : num 1 0.929 0.999 0.99 1 ...
## $ X6 : int 1122 1892 3906 4161 19206 13883 10281 878 2311 97 ...
## $ X7 : num 1 1 0.425 0.987 1 ...
## $ X8 : int 5 405 0 0 1028 0 14170 1169 0 0 ...
## $ X9 : int 1719 18934 0 0 1667 0 22979 36034 0 0 ...
## $ X10: num 17 3.7 26.7 7.3 9 15 9.7 2 9.7 13.7 ...
## $ X11: num 14.7 2 11.7 1.3 1.3 7.7 2.7 1.3 4.7 4.3 ...
Data Testing terdiri dati 5000 baris tanpa peubah respon (Y) yang akan digunakan untuk mengevaluasi model
Menampilkan proporsi dari distribusi peubah respon (Y) dalam bentuk pie chart untuk memastikan keseimbangan antar kelas.
data_train %>%
count(Y) %>%
mutate(percent=n*100/sum(n),label=str_c(round(percent,2),"%")) %>%
ggplot(aes(x="",y=n,fill=Y))+
geom_col()+
geom_text(aes(label = label),
position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y")+
theme_void()
Hasil visualisasi menunjukkan bahwa respon 0 terdiri atas 81.3% dan
respon 1 sebanyak 18.67%
Mengecek missing value dengan fungsi sum(is.na())
sum(is.na(data_test))
## [1] 0
Tidak ada missing value atau nilai NA , jika ada maka perlu diatasi agar tidak mengganggu proses pemodelan.
data_train %>%
pivot_longer(cols = where(is.numeric), names_to = "Variable", values_to = "Value") %>%
ggplot(aes(x = Value, fill = Variable)) +
geom_histogram(bins = 30, alpha = 0.7) +
facet_wrap(~ Variable, scales = "free") +
theme_minimal() +
labs(title = "Histogram untuk Variabel Numerik", x = "Nilai", y = "Frekuensi")
Secara umum, distribusi seluruh peubah pada histogram memiliki sebaran
yang tidak simetris, dengan banyak variabel menunjukkan
kemiringan (skewness) ke kanan. Mayoritas nilai terkonsentrasi di
rentang rendah, sementara terdapat beberapa nilai ekstrem di ujung
distribusi, yang mengindikasikan adanya outlier.
data_train %>%
pivot_longer(cols = where(is.numeric), names_to = "Variable", values_to = "Value") %>%
ggplot(aes(x = Variable, y = Value, fill = Variable)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
labs(title = "Boxplot untuk Variabel Numerik", x = "Variabel", y = "Nilai")
Terlihat setiap variabel memiliki skala yang berbeda. Beberapa variabel seperti (X9) memiliki nilai yang jauh lebih besar dibandingkan dengan variabel lain. Hal ini sulit untuk dianalisis dan membandingkan pola antar variabel.
Preprocessing digunakan dengan package recipes
. Pada
tahap ini, beberapa Langkah dilakukan
step_downsample()
untuk menyeimbangkan jumlah observasi antar kelas pada peubah
responstep_normalize
basic_prep <- recipe(Y~.,data = data_train) %>%
step_downsample(Y,under_ratio = 1) %>%
step_normalize(all_numeric_predictors())%>%
step_tomek(Y)
Setelah preprocessing, fungsi prep()
dan
bake()
digunakan untuk menerapkan transformasi ini pada
data. Hasilnya adalah data yang sudah siap untuk dimasukkan ke dalam
model.
processed_data <- basic_prep %>%
prep() %>%
bake(new_data = NULL)
summary(processed_data)
## X1 X2 X3 X4
## Min. :-0.616808 Min. :-0.963304 Min. :-0.778471 Min. :-5.30860
## 1st Qu.:-0.537372 1st Qu.:-0.619701 1st Qu.:-0.582348 1st Qu.:-0.28109
## Median :-0.350130 Median :-0.226724 Median :-0.327388 Median : 0.11162
## Mean : 0.002869 Mean : 0.006068 Mean : 0.005712 Mean : 0.01022
## 3rd Qu.: 0.120810 3rd Qu.: 0.288673 3rd Qu.: 0.202144 3rd Qu.: 0.50621
## Max. :15.440567 Max. :15.716207 Max. :13.793467 Max. : 1.87590
## X5 X6 X7 X8
## Min. :-4.387289 Min. :-0.842605 Min. :-3.035326 Min. :-0.4724
## 1st Qu.:-0.219695 1st Qu.:-0.666626 1st Qu.:-0.550606 1st Qu.:-0.4724
## Median : 0.443877 Median :-0.353731 Median : 0.308095 Median :-0.3825
## Mean :-0.002178 Mean : 0.004401 Mean :-0.004963 Mean : 0.0111
## 3rd Qu.: 0.631500 3rd Qu.: 0.297926 3rd Qu.: 0.831842 3rd Qu.: 0.0816
## Max. : 0.657410 Max. :17.575857 Max. : 0.940226 Max. :16.8544
## X9 X10 X11 Y
## Min. :-0.67452 Min. :-1.3926 Min. :-1.450026 0:7044
## 1st Qu.:-0.67452 1st Qu.:-0.7506 1st Qu.:-0.728068 1:7044
## Median :-0.40261 Median :-0.2584 Median :-0.175983
## Mean : 0.01732 Mean : 0.0135 Mean : 0.004373
## 3rd Qu.: 0.37134 3rd Qu.: 0.4692 3rd Qu.: 0.376102
## Max. :15.41605 Max. : 5.0918 Max. :12.564440
Setelah dilakukan preprocessing, jumlah observasi menjadi 14.024
processed_data %>%
count(Y) %>%
mutate(percent = n * 100 / sum(n), label = str_c(round(percent, 2), "%")) %>%
ggplot(aes(x = "", y = n, fill = Y)) +
geom_col() +
geom_text(aes(label = label), position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y") +
theme_void() +
labs(title = "Distribusi Target Setelah Preprocessing")
Setelah dilakukan preprocessing, proporsi data pada peubah respon seimbang antara 0 dan 1
processed_data %>%
pivot_longer(cols = where(is.numeric), names_to = "Variable", values_to = "Value") %>%
ggplot(aes(x = Variable, y = Value, fill = Variable)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
labs(title = "Boxplot Setelah Normalisasi dan Undersampling")
Setelah proses normalisasi, semua variabel memiliki skala yang seragam dari 0 hingga 1.
Model XGBoost dibuat menggunakan fungsi boost_tree()
dari parsnip. Berbagai parameter seperti jumlah pohon, kedalaman pohon,
dan laju pembelajaran ditetapkan untuk dioptimalkan dengan teknik
tuning.
xgb_spec <-boost_tree(
trees = tune(),
tree_depth = tune(),
min_n = tune(),
loss_reduction = tune(),
sample_size = tune(),
mtry = tune(),
stop_iter = tune(),
learn_rate = tune()) %>%
set_engine("xgboost") %>%
set_mode("classification")
Penjelasan parameter
boost_tree()
: Fungsi dari paket parsnip untuk
membuat spesifikasi model berbasis pohon (tree-based models), termasuk
gradient boosting seperti XGBoost.
trees
: Parameter ini menentukan jumlah total pohon
yang akan dibuat dalam boosting. tune() menunjukkan bahwa nilai
parameter ini akan dioptimalkan melalui tuning.
tree_depth
: Mengontrol kedalaman maksimum dari
setiap pohon. Pohon yang lebih dalam dapat menangkap pola yang lebih
kompleks, tetapi berisiko overfitting.
min_n
: Menentukan jumlah observasi minimum yang
harus dimiliki suatu node sebelum dapat dipecah menjadi cabang
baru.
loss_reduction
: Disebut juga “gamma”, ini
menentukan pengurangan minimal pada fungsi loss untuk membuat pemisahan
(split) pada node. Nilai tinggi menghambat pembuatan cabang
baru.
sample_size
: Proporsi data yang digunakan untuk
setiap iterasi boosting. Sampling parsial membantu mencegah
overfitting.
mtry
: Jumlah fitur yang dipilih secara acak untuk
dipertimbangkan di setiap pemisahan node.
stop_iter
: Berhenti setelah sejumlah iterasi tanpa
perbaikan pada evaluasi model (early stopping).
learn_rate
: Laju pembelajaran (learning rate), yang
mengontrol kontribusi setiap pohon ke model akhir. Nilai kecil membuat
model lebih lambat tetapi dapat meningkatkan akurasi.
set_engine("xgboost")
: Menentukan bahwa model akan
menggunakan library XGBoost sebagai mesin untuk menjalankan algoritma
boosting.
set_mode("classification")
: Mengindikasikan bahwa
model akan digunakan untuk tugas klasifikasi.
Adapun Grid pencarian untuk tuning parameter dibuat menggunakan
grid_latin_hypercube()
. Grid ini menentukan berbagai
kombinasi parameter yang akan diuji untuk menemukan konfigurasi
terbaik.
xgb_grid <- grid_latin_hypercube(
tree_depth(),
trees(),
min_n(),
loss_reduction(),
sample_size = sample_prop(),
finalize(mtry(range = c(1,50)), data_train),
learn_rate(),
stop_iter(),
size = 50
)
## Warning: `grid_latin_hypercube()` was deprecated in dials 1.3.0.
## ℹ Please use `grid_space_filling()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
doParallel::registerDoParallel()
Data pelatihan dibagi menjadi beberapa lipatan validasi silang
(cross-validation) menggunakan fungsi vfold_cv()
. Lima
lipatan digunakan dengan stratifikasi berdasarkan variabel target Y.
Kemudian, metrik evaluasi seperti accuracy
dan
balanced accuracy
dipilih untuk menilai performa model.
Proses tuning dilakukan dengan fungsi tune_grid()
, yang
mengevaluasi setiap kombinasi parameter pada grid menggunakan data
validasi silang.
set.seed(1001)
folds <- vfold_cv(data = data_train,v = 5,strata = "Y")
vfold_cv()
merupakan Fungsi dari paket
rsample
untuk membuat pembagian validasi silang. dengan v =
5 artinya Membagi dataset menjadi 5 lipatan (folds). Stratifikasi
dilakukan berdasarkan variabel target Y, memastikan proporsi kelas dalam
setiap lipatan mirip dengan data asli.
multi_metric <- metric_set(accuracy,
bal_accuracy)
Hasil tuning mencakup metrik evaluasi untuk setiap kombinasi parameter. Metrik terbaik dicari berdasarkan balanced accuracy, yang memperhitungkan ketidakseimbangan data. Proses tuning menghasilkan kombinasi parameter terbaik berdasarkan balanced accuracy menggunakan validasi silang.
xgb_workflow <- workflow() %>%
add_recipe(basic_prep) %>%
add_model(xgb_spec)
control <- control_grid(save_workflow = TRUE)
control_grid()
untuk Mengatur kontrol proses tuning
parameter.
set.seed(1001)
xgb_mod_tun <- xgb_workflow %>%
tune_grid(
resamples = folds,
metrics = multi_metric,
grid = 5,
control = control
)
## i Creating pre-processing data to finalize unknown parameter: mtry
tune_grid()
untuk melakukan tuning parameter model
dengan pencarian grid.resamples = folds
artinya Menggunakan hasil validasi
silang 5 lipatan yang didefinisikan sebelumnya.metrics = multi_metric
: Menentukan metrik evaluasi yang
telah didefinisikan (accuracy dan balanced accuracy).grid = 5
: Mencoba 5 kombinasi parameter yang
ditentukan dalam grid.control = control
: Menggunakan kontrol yang disesuaikan
sebelumnya untuk menyimpan workflow.Setelah proses tuning, konfigurasi parameter terbaik dipilih
menggunakan fungsi select_best()
. Model dengan konfigurasi
tersebut kemudian di-fit ulang ke seluruh data pelatihan untuk
menghasilkan model final.
set.seed(1001)
best_mod <- fit_best(xgb_mod_tun, metric = "bal_accuracy")
show_best(xgb_mod_tun, metric = "bal_accuracy")
## # A tibble: 5 × 14
## mtry trees min_n tree_depth learn_rate loss_reduction sample_size stop_iter
## <int> <int> <int> <int> <dbl> <dbl> <dbl> <int>
## 1 7 564 17 15 0.00547 0.00542 0.474 8
## 2 2 1894 38 10 0.0134 0.0000000111 0.309 3
## 3 10 233 29 3 0.0338 0.571 0.734 13
## 4 3 1171 3 5 0.00234 0.00000562 0.950 16
## 5 6 1397 24 7 0.106 0.000000107 0.120 19
## # ℹ 6 more variables: .metric <chr>, .estimator <chr>, mean <dbl>, n <int>,
## # std_err <dbl>, .config <chr>
autoplot(xgb_mod_tun, metric = "bal_accuracy")
# Ambil 5 model terbaik berdasarkan balanced accuracy
best_models <- show_best(xgb_mod_tun, metric = "bal_accuracy", n = 5)
# Ambil seluruh hasil tuning dan filter hanya metrik bal_accuracy
all_results <- collect_metrics(xgb_mod_tun) %>%
filter(.metric == "bal_accuracy")
# Tambahkan kolom untuk memberi label model terbaik di seluruh hasil
all_results <- all_results %>%
mutate(is_best = .config %in% best_models$.config)
# Plot semua hasil tuning dan highlight 5 model terbaik dengan garis warna berbeda
ggplot(all_results, aes(x = .config, y = mean)) +
geom_point(alpha = 0.5, color = "gray") + # Plot semua model sebagai titik abu-abu
geom_line(data = best_models, aes(x = .config, y = mean, color = as.factor(.config)), size = 1.5) +
geom_point(data = best_models, aes(color = as.factor(.config)), size = 3) +
scale_color_manual(values = c("blue", "red", "green", "purple", "orange")) + # Warna berbeda untuk setiap model terbaik
labs(
title = "Top 5 Models Based on Balanced Accuracy",
x = "Model Configuration",
y = "Balanced Accuracy",
color = "Model"
) +
theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?
Konfigurasi model terbaik ialah Processor1_Model4
best_model <- select_best(xgb_mod_tun, metric ="bal_accuracy")
best_model
## # A tibble: 1 × 9
## mtry trees min_n tree_depth learn_rate loss_reduction sample_size stop_iter
## <int> <int> <int> <int> <dbl> <dbl> <dbl> <int>
## 1 7 564 17 15 0.00547 0.00542 0.474 8
## # ℹ 1 more variable: .config <chr>
best_mod_explainer <- extract_fit_engine(best_mod)
train_predictions <- predict(best_mod, new_data = data_train, type = "class") %>%
bind_cols(data_train %>% select(Y)) # Bind the true labels from training data
conf_matrix <- train_predictions %>%
conf_mat(truth = Y, estimate = .pred_class)
print(conf_matrix)
## Truth
## Prediction 0 1
## 0 25922 2212
## 1 10676 6190
library(yardstick)
# Menghitung Accuracy
accuracy_metric <- train_predictions %>%
accuracy(truth = Y, estimate = .pred_class)
# Menghitung Sensitivity
sensitivity_metric <- train_predictions %>%
sens(truth = Y, estimate = .pred_class)
# Menghitung Specificity
specificity_metric <- train_predictions %>%
spec(truth = Y, estimate = .pred_class)
# Cetak hasil
print(accuracy_metric)
## # A tibble: 1 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 accuracy binary 0.714
print(sensitivity_metric)
## # A tibble: 1 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 sens binary 0.708
print(specificity_metric)
## # A tibble: 1 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 spec binary 0.737
balanced_accuracy <- train_predictions %>%
bal_accuracy(truth = Y, estimate = .pred_class)
print(balanced_accuracy)
## # A tibble: 1 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 bal_accuracy binary 0.723
Balanced Accuracy 0.721 ini menunjukkan bahwa rata-rata model mampu mengenali kelas positif dan kelas negatif dengan akurasi 72.1% . Artinya, model ini cukup baik dalam menangani kedua kelas, meskipun tidak sempurna.
autoplot(conf_matrix,type = "heatmap")+
scale_fill_gradient(low = "#F4AFAB",high = "#EE847E")
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
saveRDS(best_mod,file = "xgb_model.rds")
new_pred <- readRDS("xgb_model.rds") %>%
predict(new_data = data_test,type = "class")
write.csv(new_pred, "submission_xgb3.csv",
row.names = F)
# Buat kembali workflow dengan parameter terbaik
final_xgb <- finalize_workflow(xgb_workflow, best_model) %>%
fit(data = data_train)
# Ekstrak model xgboost dari workflow yang sudah di-fit
xgb_model <- extract_fit_engine(final_xgb)
# Hitung feature importance
importance <- xgb.importance(model = xgb_model)
print(importance)
## Feature Gain Cover Frequency
## <char> <num> <num> <num>
## 1: X9 0.23223644 0.17684308 0.10211073
## 2: X2 0.16895704 0.16307783 0.14580611
## 3: X10 0.13558976 0.12733983 0.09540400
## 4: X11 0.11688750 0.11332938 0.07914525
## 5: X8 0.07269438 0.06921076 0.06796737
## 6: X6 0.05438974 0.06679775 0.10362047
## 7: X4 0.04963985 0.06580041 0.09499753
## 8: X1 0.04933755 0.06163618 0.08512615
## 9: X5 0.04885212 0.06092967 0.08355834
## 10: X7 0.04213507 0.05880143 0.08530035
## 11: X3 0.02928056 0.03623368 0.05696368
ggplot(importance, aes(x = reorder(Feature, Gain), y = Gain)) +
geom_bar(stat = "identity", fill = "#00CCCC") +
coord_flip() +
ggtitle("Feature Importance for Best XGBoost Model") +
xlab("Features") +
ylab("Importance") +
theme_minimal()
Model XGBoost bertujuan untuk memprediksi pelanggan potensial yang dapat diajak menggunakan channel tertentu. Peubah respon (Y) adalah kategori yang menunjukkan apakah pelanggan termasuk dalam kelompok potensial atau tidak.
Grafik Feature Importance menunjukkan kontribusi peubah prediktor dalam menentukan output model.
X9 (Rata-rata penghasilan dari transaksi pemakaian data per bulan (Rp)) memiliki kontribusi terbesar dalam memprediksi pelanggan potensial. Ini menunjukkan bahwa penghasilan dari transaksi data sangat relevan untuk mengidentifikasi pelanggan yang kemungkinan besar menggunakan channel ini. Pelanggan dengan penghasilan tinggi dari pemakaian data mungkin memiliki kebutuhan lebih besar terhadap layanan terkait channel tersebut.
X2 (Rata-rata penghasilan dari transaksi panggilan per bulan (Rp)) adalah variabel penting kedua. Ini menunjukkan bahwa penghasilan dari panggilan juga menjadi indikator signifikan. Pelanggan yang banyak menghasilkan pendapatan dari panggilan cenderung lebih aktif dalam menggunakan layanan.
X10 (Rata-rata frekuensi melakukan recharge pulsa per bulan) berada di urutan berikutnya. Ini menyiratkan bahwa pelanggan yang sering melakukan isi ulang pulsa cenderung lebih potensial karena menunjukkan keterlibatan tinggi dengan layanan.