1)Mengaktifkan Package

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)

2)Memuat Dataset

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.

Load training dataset

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 :

  • X1 : rata-rata durasi melakukan panggilan per bulan (menit)
  • X2 : rata-rata penghasilan dari transaksi panggilan per bulan (Rp)
  • X3 : rata-rata frekuensi melakukan panggilan per bulan
  • X4 : persentase panggilan di jam kerja
  • X5 : persentase panggilan sesama operator
  • X6 : rata-rata penghasilan dari transaksi SMS per bulan (Rp)
  • X7 : persentase transaksi SMS sesama operator
  • X8 : rata-rata pemakaian data per bulan (MB)
  • X9 : rata-rata penghasilan dari transaksi pemakaian data per bulan (Rp)
  • X10 : rata-rata frekuensi melakukan recharge pulsa per bulan
  • X11 : rata-rata banyaknya wilayah yang dikunjungi per bulan

Load testing dataset

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

3)Eksplorasi Data

Proporsi Peubah Respon

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

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.

Distribusi Peubah Prediktor

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.

Boxplot

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.

4)Preprocessing Data

Preprocessing digunakan dengan package recipes. Pada tahap ini, beberapa Langkah dilakukan

  • Downsampling : Menggunakan fungsi step_downsample() untuk menyeimbangkan jumlah observasi antar kelas pada peubah respon
  • Normalisasi : Peubah prediktor numerik dinormalisasi ke skala yang seragam dengan fungsi step_normalize
  • step_tomek() : fungsi yang menghapus Tomek links dari dataset. Fitur ini digunakan untuk menangani masalah ketidakseimbangan kelas (class imbalance), terutama dalam konteks klasifikasi. Tomek links juga dapat digunakan sebagai metode pembersihan data dari noise.
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

Visualisasi Distribusi Target Setelah Undersampling

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

Visualisasi Boxplot Setelah Normalisasi

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.

5) Model XGBOOST

Membangun model XGBOOST

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.

Pembuatan Grid Pencarian untuk Tuning

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()

Validasi Silang

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.

Menggabungkan preprocessing dan model dalam workflow

xgb_workflow <- workflow() %>%
  add_recipe(basic_prep) %>%
  add_model(xgb_spec)

Pengaturan Parameter Tuning

control <- control_grid(save_workflow = TRUE)

control_grid() untuk Mengatur kontrol proses tuning parameter.

Melakukan tuning parameter menggunakan cross-validation

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.

Memilih Model Terbaik

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")

Menampilkan model terbaik

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>

Membuat plot performa dari hasil tuning

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)

Evaluasi model XGBOOST

train_predictions <- predict(best_mod, new_data = data_train, type = "class") %>%
  bind_cols(data_train %>% select(Y))  # Bind the true labels from training data

Confusion Matrix

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

Menghitung balanced accuracy

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.

Menyimpan Model dalam RDS

saveRDS(best_mod,file = "xgb_model.rds")
new_pred <- readRDS("xgb_model.rds") %>% 
  predict(new_data = data_test,type = "class")

Membuat prediksi

write.csv(new_pred, "submission_xgb3.csv",
          row.names = F)

Feature Importance

# 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.