BAB I PENDAHULUAN

1.1 Latar Belakang Masalah

Perkembangan teknologi pengolahan data mendorong penggunaan metode machine learning untuk menghasilkan prediksi dan klasifikasi yang lebih akurat. Salah satu pendekatan yang banyak digunakan adalah metode ensemble learning, yaitu teknik yang menggabungkan beberapa model untuk meningkatkan kemampuan prediksi. Salah satu metode ensemble berbasis decision tree yang dapat digunakan untuk klasifikasi dan regresi adalah Random Forest (Hasanah et al., 2024).

Metode Random Forest dikembangkan dengan menggabungkan sejumlah pohon keputusan yang dibentuk melalui proses bootstrap sampling dan pemilihan atribut secara acak untuk menghasilkan prediksi akhir. Pengembangan dari metode tersebut adalah Double Random Forest, yang menerapkan proses bootstrap pada setiap simpul pohon sehingga dapat menghasilkan pohon keputusan yang lebih besar dan beragam. Kedua metode tersebut dapat digunakan untuk membangun model prediksi serta dibandingkan berdasarkan kemampuan dan karakteristik masing-masing dalam menangani data (Khairunnisa et al., 2024).

Penerapan Random Forest dan Double Random Forest memerlukan tahapan implementasi yang disesuaikan dengan tujuan analisis, baik untuk klasifikasi maupun regresi. Evaluasi performa model dilakukan menggunakan ukuran ketepatan prediksi, sedangkan Out-of-Bag (OOB) error digunakan untuk memperkirakan kesalahan prediksi melalui data yang tidak terpilih dalam proses bootstrap. Oleh karena itu, pemahaman mengenai konsep, implementasi, evaluasi, serta perbandingan kedua metode diperlukan untuk mengetahui kemampuan masing-masing model dalam menghasilkan prediksi yang optimal (Purwanto et al., 2025).

1.2 Rumusan Masalah

Berdasarkan latar belakang di atas, masalah yang dapat disimpulkan adalah:

  1. Apa yang dimaksud dengan Random Forest dan Double Random Forest sebagai metode ensemble berbasis decision tree?

  2. Bagaimana mengimplementasikan Random Forest untuk klasifikasi dan regresi, serta Double Random Forest untuk klasifikasi dan regresi?

  3. Bagaimana mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan Random Forest dengan Double Random Forest?

1.3 Tujuan

Berdasarkan rumusan masalah pada penelitian ini, tujuan yang dapat disimpulkan adalah:

  1. Mahasiswa dapat memahami Random Forest dan Double Random Forest sebagai metode ensemble berbasis decision tree.

  2. Mahasiswa dapat mengimplementasikan Random Forest untuk klasifikasi dan regresi, serta Double Random Forest untuk klasifikasi dan regresi.

  3. Mahasiswa dapat mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan Random Forest dengan Double Random Forest.

BAB II TINJAUAN PUSTAKA

2.1 Random Forest

Random Forest merupakan salah satu metode ensemble learning berbasis decision tree yang digunakan untuk menyelesaikan permasalahan klasifikasi dan regresi. Metode ini bekerja dengan membentuk sejumlah pohon keputusan (decision tree) menggunakan sampel data dan pemilihan variabel prediktor secara acak. Hasil prediksi dari seluruh pohon kemudian digabungkan untuk memperoleh prediksi akhir yang lebih stabil dibandingkan penggunaan satu pohon keputusan (Khairunnisa et al., 2024).

Secara sederhana, proses Random Forest dilakukan sebagai berikut (Fransiska, 2026):

  1. Mengambil sampel bootstrap dari data latih untuk membentuk data bagi tree ke-b.

  2. Pada setiap node, memilih mtry prediktor secara acak dari seluruh p prediktor.

  3. Menentukan split terbaik hanya dari mtry prediktor yang terpilih.

  4. Menumbuhkan decision tree hingga memenuhi aturan penghentian, misalnya minimum node size.

  5. Mengulangi proses sampai diperoleh B tree, kemudian menggabungkan prediksi seluruh tree.

Untuk klasifikasi, hasil akhir diperoleh melalui majority voting:

\[ \widehat{G}_{RF}(x)= \operatorname{mode} \{G_1(x),G_2(x),\ldots,G_B(x)\} \] Untuk regresi, hasil akhir diperoleh dengan merata-ratakan prediksi semua tree:

\[ { \hat{f}_{RF}(x)= \left(\frac{1}{B}\right) \sum_{b=1}^{B}T_b(x) } \] Dengan demikian, Random Forest tetap merupakan metode parallel ensemble, dengan setiap tree dapat dibentuk secara relatif independen, berbeda dari Boosting yang bersifat sequential.

2.2 Out-of-Bag (OOB) Error

Pada proses bootstrap dengan pengembalian, sebagian observasi dapat terambil lebih dari satu kali, sedangkan sebagian lainnya tidak terambil. Observasi yang tidak terpilih dalam pembentukan suatu pohon disebut Out-of-Bag (OOB) observations, dengan proporsi rata-rata sekitar 36,8% dari keseluruhan observasi. Prediksi OOB diperoleh dari pohon-pohon yang tidak menggunakan observasi tersebut dalam proses pembentukannya. Prediksi ini digunakan untuk menghitung OOB error sebagai ukuran evaluasi internal pada metode Random Forest. Pada pemrograman R menggunakan paket ranger, OOB error dihitung secara otomatis, yaitu berupa proporsi kesalahan klasifikasi (prediction.error) untuk klasifikasi dan nilai OOB Mean Squared Error (MSE) untuk regresi (Fransiska, 2026).

2.3 Double Random Forest (DRF)

Double Random Forest (DRF) merupakan pengembangan dari metode Random Forest yang digunakan untuk meningkatkan kemampuan model dalam menghasilkan prediksi. Metode ini menerapkan proses bootstrap sampling tidak hanya pada awal pembentukan pohon, tetapi juga pada setiap simpul (node) selama proses pembentukan pohon keputusan. Penggunaan pengambilan sampel secara berulang tersebut bertujuan menghasilkan pohon-pohon yang lebih beragam dan mengatasi permasalahan underfitting yang dapat terjadi pada metode Random Forest (Purwanto et al., 2025).

Pada Random Forest standar, setiap tree dibentuk menggunakan satu bootstrap sample pada awal tree. Karena satu bootstrap sample hanya mengandung sekitar 63,2% observasi unik, jumlah observasi unik yang tersedia untuk membentuk tree lebih sedikit dari pada seluruh data training. Setiap tree DRF dibangun menggunakan seluruh data training, sedangkan bootstrap digunakan sementara pada setiap node untuk mencari aturan split.

Secara sederhana, proses Double Random Forest dilakukan sebagai berikut (Fransiska, 2026):

  1. Memulai setiap tree dengan seluruh data training, bukan satu bootstrap sample untuk seluruh tree.

  2. Pada node yang sedang diproses, mengambil bootstrap sample dari observasi yang mencapai node tersebut.

  3. Memilih mtry prediktor secara acak dan mencari split terbaik menggunakan bootstrap sample pada node.

  4. Setelah split terbaik ditemukan, bootstrap sample tidak diteruskan. Split tersebut diterapkan kembali pada data asli yang mencapai node, kemudian observasi asli dikirim ke child nodes.

  5. Mengulangi proses pada node berikutnya sampai aturan penghentian tercapai, lalu mengulangi untuk seluruh tree.

  6. Menggabungkan prediksi seluruh tree. Pada klasifikasi, hasil akhir diperoleh melalui majority voting, sedangkan pada regresi prediksi akhir diperoleh dengan merata-ratakan prediksi seluruh tree.

BAB III METODE PENELITIAN

3.1 Sumber Data

Jenis data pada penelitian ini adalah data kuantitatif dan data kualitatif. Data kuantitatif merupakan data atau informasi yang didapatkan dalam bentuk angka atau numerik. Data kuantitatif dapat diproses menggunakan rumus matematika atau dapat juga dianalisis dengan sistem statistik. Data kualitatif adalah suatu data yang tidak bisa diukur dengan angka. Data kualitatif adalah data yang dinyatakan dalam bentuk deskriptif atau naratif, bukan dalam bentuk angka.

Sumber data yang digunakan oleh penulis merupakan data sekunder. Data sekunder adalah sumber data yang diperoleh secara tidak langsung atau melalui media perantara. Data yang digunakan pada batasan masalah laporan ini merupakan data BreastCancer yang diperoleh langsung dari program R.

3.2 Variabel Penelitian

Variabel penelitian adalah karakter atau segala sesuatu yang menjadi perhatian dalam suatu penelitian. Pada laporan ini terdapat 10 variabel yang digunakan pada data. Variabel tersebut, yaitu Cl.thickness, Cell.size, Cell.shape, Marg.adhesion, Epith.c.size, Bare.nuclei, Bl,cromatin, Normal.nucleoli, Mitoses sebagai variabel prediktor, dan Class sebagai variabel respon.

3.3 Langkah-langkah Analisis

  1. Input data.

  2. Preprocessing data.

  3. Pembagian data training dan data testing.

  4. Menentukan kombinasi parameter mtry dan num.trees yang akan digunakan.

  5. Membentuk model Random Forest dengan sembilan kombinasi parameter yang berbeda.

  6. Menghitung nilai Out-of-Bag (OOB) error pada setiap model.

  7. Melakukan prediksi menggunakan data testing dan membentuk confusion matrix.

  8. Menghitung metrik evaluasi.

  9. Membandingkan performa model, menentukan model terbaik, serta menganalisis variable importance.

  10. Output dan interpretasi.

BAB IV HASIL DAN PEMBAHASAN

4.1 Input Package dan Dataset

Langkah pertama yang dilakukan adalah memanggil library dan meng-import data

knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE)

packages <- c("ranger", "mlbench", "caret", "knitr",
              "ggplot2", "dplyr", "tidyr")

for (p in packages) {
  if (!requireNamespace(p, quietly = TRUE)) {
    install.packages(p, repos = "https://cloud.r-project.org")
  }
}

library(ranger)
library(mlbench)
library(caret)
## Loading required package: ggplot2
## Loading required package: lattice
library(knitr)
library(ggplot2)
library(dplyr)
## 
## 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(tidyr)

data("BreastCancer", package = "mlbench")
bc <- BreastCancer

# Menghapus variabel identitas
bc$Id <- NULL

# Menghapus observasi dengan missing value
bc <- na.omit(bc)

# Mengubah variabel prediktor menjadi numerik
kolom_prediktor <- setdiff(names(bc), "Class")

bc[kolom_prediktor] <- lapply(bc[kolom_prediktor], function(x) {
  as.numeric(as.character(x))
})

# Menetapkan urutan kategori variabel respon
bc$Class <- factor(as.character(bc$Class),
                   levels = c("benign", "malignant"))

# Pemeriksaan awal data
ringkasan_data <- data.frame(
  Keterangan = c("Jumlah observasi setelah pembersihan",
                 "Jumlah prediktor",
                 "Jumlah nilai hilang setelah pembersihan"),
  Nilai = c(nrow(bc),
            length(kolom_prediktor),
            sum(is.na(bc)))
)

kable(ringkasan_data,
      caption = "Ringkasan Dataset BreastCancer")
Ringkasan Dataset BreastCancer
Keterangan Nilai
Jumlah observasi setelah pembersihan 683
Jumlah prediktor 9
Jumlah nilai hilang setelah pembersihan 0
# Distribusi kelas
tabel_kelas <- as.data.frame(table(Class = bc$Class))
names(tabel_kelas)[2] <- "Jumlah"

kable(tabel_kelas,
      caption = "Distribusi Kelas pada Dataset BreastCancer")
Distribusi Kelas pada Dataset BreastCancer
Class Jumlah
benign 444
malignant 239

Berdasarkan hasil statistik deskriptif pada data BreastCancer, diperoleh sebanyak 683 observasi dan 10 variabel yang terdiri atas 9 variabel prediktor dan 1 variabel respon, yaitu Class. Data telah melalui proses pembersihan dengan menghapus kolom ID dan observasi yang memiliki missing value, sehingga tidak terdapat nilai yang hilang pada seluruh variabel. Variabel respon Class terdiri atas 444 data benign (jinak) atau sebesar 65,01% dan 239 data malignant (ganas) atau sebesar 34,99%. Hasil tersebut menunjukkan bahwa data didominasi oleh kelas benign. Data ini selanjutnya digunakan untuk membangun model Random Forest Classification dengan variasi mtry = 2, 3, dan 5 dan num.trees = 200, 500, dan 1000 untuk membandingkan kinerja klasifikasi berdasarkan metrik evaluasi, yaitu Accuracy, Precision, Recall, Specificity, dan F1-Score.

4.2 Membagi Data Training dan Testing

set.seed(234)

idx_train <- createDataPartition(
  bc$Class,
  p = 0.70,
  list = FALSE
)

bc.train <- bc[idx_train, , drop = FALSE]
bc.test <- bc[-idx_train, , drop = FALSE]

# Ringkasan pembagian data
ringkasan_split <- data.frame(
  Data = c("Training", "Testing", "Total"),
  Jumlah_Observasi = c(
    nrow(bc.train),
    nrow(bc.test),
    nrow(bc)
  )
)

kable(ringkasan_split,
      caption = "Pembagian Data Training dan Testing")
Pembagian Data Training dan Testing
Data Jumlah_Observasi
Training 479
Testing 204
Total 683
# Distribusi kelas data training
distribusi_train <- as.data.frame(
  table(Kelas = bc.train$Class)
)

names(distribusi_train) <- c("Kelas", "Jumlah")

kable(distribusi_train,
      caption = "Distribusi Kelas pada Data Training")
Distribusi Kelas pada Data Training
Kelas Jumlah
benign 311
malignant 168
# Distribusi kelas data testing
distribusi_test <- as.data.frame(
  table(Kelas = bc.test$Class)
)

names(distribusi_test) <- c("Kelas", "Jumlah")

kable(distribusi_test,
      caption = "Distribusi Kelas pada Data Testing")
Distribusi Kelas pada Data Testing
Kelas Jumlah
benign 133
malignant 71

Berdasarkan hasil pembagian data BreastCancer, diperoleh sebanyak 479 observasi sebagai data training (70%) dan 204 observasi sebagai data testing (30%) dari total 683 observasi. Pada data testing, terdapat 133 observasi kelas benign (jinak) atau sebesar 65,20% dan 71 observasi kelas malignant (ganas) atau sebesar 34,80%. Hasil tersebut menunjukkan bahwa kelas benign memiliki proporsi lebih besar dibandingkan kelas malignant pada data testing. Data training ini digunakan untuk membangun model Random Forest Classification, sedangkan data testing digunakan untuk mengevaluasi kinerja model.

4.3 Membentuk Model Random Forest dan Menghitung OOB Error

# Kombinasi parameter model
kombinasi <- expand.grid(
  mtry = c(2, 3, 5),
  num.trees = c(200, 500, 1000),
  KEEP.OUT.ATTRS = FALSE,
  stringsAsFactors = FALSE
)

# Membentuk sembilan model Random Forest
model_rf <- vector("list", nrow(kombinasi))

nama_model <- paste0(
  "mtry", kombinasi$mtry,
  "_trees", kombinasi$num.trees
)

names(model_rf) <- nama_model

for (i in seq_len(nrow(kombinasi))) {
  model_rf[[i]] <- ranger(
    formula = Class ~ .,
    data = bc.train,
    num.trees = kombinasi$num.trees[i],
    mtry = kombinasi$mtry[i],
    min.node.size = 1,
    replace = TRUE,
    sample.fraction = 1,
    importance = "permutation",
    seed = 234
  )
}

# Menghitung OOB Error setiap model
hasil_oob <- data.frame(
  Model = names(model_rf),
  mtry = kombinasi$mtry,
  Num_Trees = kombinasi$num.trees,
  OOB_Error = vapply(
    model_rf,
    function(m) as.numeric(m$prediction.error),
    numeric(1)
  )
)

kable(hasil_oob, digits = 4,
      caption = "Perbandingan OOB Error pada Sembilan Model")
Perbandingan OOB Error pada Sembilan Model
Model mtry Num_Trees OOB_Error
mtry2_trees200 mtry2_trees200 2 200 0.0292
mtry3_trees200 mtry3_trees200 3 200 0.0271
mtry5_trees200 mtry5_trees200 5 200 0.0292
mtry2_trees500 mtry2_trees500 2 500 0.0292
mtry3_trees500 mtry3_trees500 3 500 0.0292
mtry5_trees500 mtry5_trees500 5 500 0.0292
mtry2_trees1000 mtry2_trees1000 2 1000 0.0292
mtry3_trees1000 mtry3_trees1000 3 1000 0.0271
mtry5_trees1000 mtry5_trees1000 5 1000 0.0271

Berdasarkan tabel perbandingan Out-of-Bag (OOB) Error pada sembilan model Random Forest, diperoleh nilai OOB Error yang berkisar antara 0,0271 hingga 0,0292. Nilai OOB Error terendah sebesar 0,0271 diperoleh pada model mtry3_trees200, mtry3_trees1000, dan mtry5_trees1000, sedangkan nilai tertinggi sebesar 0,0292 diperoleh pada enam model lainnya. Hal ini menunjukkan bahwa ketiga model dengan nilai OOB Error sebesar 0,0271 memiliki tingkat kesalahan prediksi yang lebih rendah dibandingkan model lainnya berdasarkan evaluasi OOB. Sehingga model mtry3_trees200, mtry3_trees1000, dan mtry5_trees1000 menjadi kandidat model terbaik berdasarkan nilai OOB Error, meskipun penentuan model terbaik secara keseluruhan tetap perlu mempertimbangkan hasil evaluasi pada data pengujian.

4.4 Confusion Matrix dan Metrik Evaluasi Data Testing

# Fungsi menghitung metrik evaluasi
hitung_evaluasi <- function(aktual, prediksi) {

  aktual <- factor(
    aktual,
    levels = c("benign", "malignant")
  )

  prediksi <- factor(
    prediksi,
    levels = c("benign", "malignant")
  )

  tab <- table(
    Aktual = aktual,
    Prediksi = prediksi
  )

  TN <- unname(tab["benign", "benign"])
  FP <- unname(tab["benign", "malignant"])
  FN <- unname(tab["malignant", "benign"])
  TP <- unname(tab["malignant", "malignant"])

  pembagi <- function(a, b) {
    if (b == 0) NA_real_ else a / b
  }

  precision <- pembagi(TP, TP + FP)
  recall <- pembagi(TP, TP + FN)
  specificity <- pembagi(TN, TN + FP)

  f1 <- if (is.na(precision) ||
            is.na(recall) ||
            precision + recall == 0) {
    NA_real_
  } else {
    2 * precision * recall / (precision + recall)
  }

  list(
    confusion = tab,
    metrics = data.frame(
      Accuracy = (TP + TN) / sum(tab),
      Precision = precision,
      Recall = recall,
      Specificity = specificity,
      F1_Score = f1
    )
  )
}

# Menyiapkan tempat penyimpanan hasil
prediksi_rf <- vector("list", length(model_rf))
names(prediksi_rf) <- names(model_rf)

confusion_rf <- vector("list", length(model_rf))
names(confusion_rf) <- names(model_rf)

daftar_evaluasi <- vector("list", length(model_rf))

# Prediksi dan evaluasi seluruh model
for (i in seq_along(model_rf)) {

  pred <- predict(
    model_rf[[i]],
    data = bc.test
  )$predictions

  pred <- factor(
    as.character(pred),
    levels = c("benign", "malignant")
  )

  prediksi_rf[[i]] <- pred

  ev <- hitung_evaluasi(bc.test$Class, pred)

  confusion_rf[[i]] <- ev$confusion

  daftar_evaluasi[[i]] <- data.frame(
    Model = names(model_rf)[i],
    mtry = kombinasi$mtry[i],
    Num_Trees = kombinasi$num.trees[i],
    ev$metrics,
    check.names = FALSE
  )
}

# Menggabungkan hasil evaluasi
hasil_metrik <- bind_rows(daftar_evaluasi)

kolom_metrik <- c(
  "Accuracy", "Precision", "Recall",
  "Specificity", "F1_Score"
)

hasil_metrik[kolom_metrik] <- lapply(
  hasil_metrik[kolom_metrik],
  as.numeric
)

# Menyusun confusion matrix seluruh model
tabel_confusion <- bind_rows(
  lapply(names(confusion_rf), function(nm) {

    tab <- confusion_rf[[nm]]

    data.frame(
      Model = nm,
      Aktual = rownames(tab),
      Prediksi_benign = as.integer(tab[, "benign"]),
      Prediksi_malignant = as.integer(tab[, "malignant"]),
      row.names = NULL
    )
  })
)

kable(
  tabel_confusion,
  caption = "Confusion Matrix Seluruh Model (baris = kelas aktual)"
)
Confusion Matrix Seluruh Model (baris = kelas aktual)
Model Aktual Prediksi_benign Prediksi_malignant
mtry2_trees200 benign 130 3
mtry2_trees200 malignant 1 70
mtry3_trees200 benign 130 3
mtry3_trees200 malignant 3 68
mtry5_trees200 benign 129 4
mtry5_trees200 malignant 4 67
mtry2_trees500 benign 129 4
mtry2_trees500 malignant 1 70
mtry3_trees500 benign 130 3
mtry3_trees500 malignant 3 68
mtry5_trees500 benign 129 4
mtry5_trees500 malignant 4 67
mtry2_trees1000 benign 129 4
mtry2_trees1000 malignant 2 69
mtry3_trees1000 benign 129 4
mtry3_trees1000 malignant 3 68
mtry5_trees1000 benign 129 4
mtry5_trees1000 malignant 5 66
# Tabel metrik evaluasi
kable(
  hasil_metrik,
  digits = 4,
  caption = "Perbandingan Metrik Evaluasi pada Data Testing"
)
Perbandingan Metrik Evaluasi pada Data Testing
Model mtry Num_Trees Accuracy Precision Recall Specificity F1_Score
mtry2_trees200 2 200 0.9804 0.9589 0.9859 0.9774 0.9722
mtry3_trees200 3 200 0.9706 0.9577 0.9577 0.9774 0.9577
mtry5_trees200 5 200 0.9608 0.9437 0.9437 0.9699 0.9437
mtry2_trees500 2 500 0.9755 0.9459 0.9859 0.9699 0.9655
mtry3_trees500 3 500 0.9706 0.9577 0.9577 0.9774 0.9577
mtry5_trees500 5 500 0.9608 0.9437 0.9437 0.9699 0.9437
mtry2_trees1000 2 1000 0.9706 0.9452 0.9718 0.9699 0.9583
mtry3_trees1000 3 1000 0.9657 0.9444 0.9577 0.9699 0.9510
mtry5_trees1000 5 1000 0.9559 0.9429 0.9296 0.9699 0.9362

Berdasarkan hasil confusion matrix dan evaluasi model, model mtry2_trees200 menunjukkan kinerja klasifikasi terbaik dibandingkan delapan model lainnya. Model tersebut berhasil mengklasifikasikan 130 data benign dan 70 data malignant dengan benar, serta hanya menghasilkan 4 kesalahan klasifikasi. Hal ini ditunjukkan oleh nilai accuracy sebesar 0,9804, precision sebesar 0,9589, recall sebesar 0,9859, specificity sebesar 0,9774, dan F1-score sebesar 0,9722. Nilai OOB Error model tersebut sebesar 0,0292, sedikit lebih tinggi dibandingkan beberapa model lain yang memiliki OOB Error sebesar 0,0271. Meskipun demikian, berdasarkan evaluasi pada data pengujian, mtry2_trees200 tetap menjadi model terbaik karena menghasilkan nilai accuracy, precision, recall, dan F1-score tertinggi, sehingga dipilih sebagai model dengan kinerja klasifikasi paling baik.

4.5 Perbandingan Kinerja Model

# Membuat label konfigurasi model
hasil_metrik$Konfigurasi <- paste0(
  "mtry=", hasil_metrik$mtry,
  ", trees=", hasil_metrik$Num_Trees
)

# Mengubah data menjadi format long
hasil_long <- tidyr::pivot_longer(
  hasil_metrik,
  cols = all_of(kolom_metrik),
  names_to = "Metrik",
  values_to = "Nilai"
)

# Membuat grafik perbandingan
ggplot(
  hasil_long,
  aes(x = Konfigurasi, y = Nilai)
) +
  geom_point(size = 2) +
  facet_wrap(~ Metrik, scales = "free_y") +
  labs(
    title = "Perbandingan Metrik Random Forest pada Data Testing",
    x = "Konfigurasi Model",
    y = "Nilai Metrik"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(
      angle = 45,
      hjust = 1
    )
  )

Berdasarkan grafik perbandingan metrik evaluasi pada data testing, model mtry2_trees200 menunjukkan kinerja terbaik dengan nilai accuracy sebesar 0,9804, precision sebesar 0,9589, recall sebesar 0,9859, specificity sebesar 0,9774, dan F1-score sebesar 0,9722. Model tersebut memiliki nilai accuracy, precision, recall, dan F1-score tertinggi dibandingkan model lainnya, sedangkan nilai specificity-nya juga termasuk yang tertinggi. Secara umum, peningkatan jumlah pohon (num.trees) tidak selalu menghasilkan peningkatan kinerja model, begitu pula penggunaan nilai mtry yang lebih besar cenderung menghasilkan nilai metrik yang lebih rendah pada beberapa konfigurasi. Hal ini menunjukkan bahwa pemilihan kombinasi parameter mtry dan num.trees berpengaruh terhadap hasil klasifikasi. Sehingga model mtry2_trees200 dipilih sebagai model terbaik karena memberikan kinerja klasifikasi paling optimal berdasarkan keseluruhan metrik evaluasi pada data testing.

4.6 Variable Importance

# Menggabungkan permutation importance seluruh model
importance_all <- bind_rows(
  lapply(names(model_rf), function(nm) {

    imp <- model_rf[[nm]]$variable.importance

    data.frame(
      Model = nm,
      Variabel = names(imp),
      Permutation_Importance = as.numeric(imp),
      row.names = NULL
    )
  })
)

# Menampilkan tabel variable importance
kable(
  importance_all %>%
    arrange(Model, desc(Permutation_Importance)),
  digits = 4,
  caption = "Permutation Variable Importance untuk Seluruh Model"
)
Permutation Variable Importance untuk Seluruh Model
Model Variabel Permutation_Importance
mtry2_trees1000 Bare.nuclei 0.0817
mtry2_trees1000 Cell.size 0.0779
mtry2_trees1000 Cell.shape 0.0626
mtry2_trees1000 Cl.thickness 0.0263
mtry2_trees1000 Bl.cromatin 0.0205
mtry2_trees1000 Normal.nucleoli 0.0199
mtry2_trees1000 Marg.adhesion 0.0189
mtry2_trees1000 Epith.c.size 0.0140
mtry2_trees1000 Mitoses 0.0033
mtry2_trees200 Bare.nuclei 0.0839
mtry2_trees200 Cell.size 0.0787
mtry2_trees200 Cell.shape 0.0610
mtry2_trees200 Cl.thickness 0.0245
mtry2_trees200 Bl.cromatin 0.0215
mtry2_trees200 Normal.nucleoli 0.0204
mtry2_trees200 Marg.adhesion 0.0193
mtry2_trees200 Epith.c.size 0.0117
mtry2_trees200 Mitoses 0.0038
mtry2_trees500 Bare.nuclei 0.0805
mtry2_trees500 Cell.size 0.0773
mtry2_trees500 Cell.shape 0.0630
mtry2_trees500 Cl.thickness 0.0267
mtry2_trees500 Bl.cromatin 0.0219
mtry2_trees500 Normal.nucleoli 0.0218
mtry2_trees500 Marg.adhesion 0.0191
mtry2_trees500 Epith.c.size 0.0132
mtry2_trees500 Mitoses 0.0031
mtry3_trees1000 Bare.nuclei 0.1003
mtry3_trees1000 Cell.size 0.0855
mtry3_trees1000 Cell.shape 0.0593
mtry3_trees1000 Cl.thickness 0.0248
mtry3_trees1000 Marg.adhesion 0.0195
mtry3_trees1000 Bl.cromatin 0.0192
mtry3_trees1000 Normal.nucleoli 0.0165
mtry3_trees1000 Epith.c.size 0.0119
mtry3_trees1000 Mitoses 0.0032
mtry3_trees200 Bare.nuclei 0.0972
mtry3_trees200 Cell.size 0.0917
mtry3_trees200 Cell.shape 0.0628
mtry3_trees200 Cl.thickness 0.0278
mtry3_trees200 Marg.adhesion 0.0191
mtry3_trees200 Bl.cromatin 0.0180
mtry3_trees200 Normal.nucleoli 0.0160
mtry3_trees200 Epith.c.size 0.0099
mtry3_trees200 Mitoses 0.0037
mtry3_trees500 Bare.nuclei 0.0991
mtry3_trees500 Cell.size 0.0853
mtry3_trees500 Cell.shape 0.0651
mtry3_trees500 Cl.thickness 0.0260
mtry3_trees500 Marg.adhesion 0.0193
mtry3_trees500 Bl.cromatin 0.0188
mtry3_trees500 Normal.nucleoli 0.0148
mtry3_trees500 Epith.c.size 0.0109
mtry3_trees500 Mitoses 0.0032
mtry5_trees1000 Bare.nuclei 0.1214
mtry5_trees1000 Cell.size 0.0911
mtry5_trees1000 Cell.shape 0.0438
mtry5_trees1000 Cl.thickness 0.0227
mtry5_trees1000 Normal.nucleoli 0.0208
mtry5_trees1000 Marg.adhesion 0.0189
mtry5_trees1000 Bl.cromatin 0.0162
mtry5_trees1000 Epith.c.size 0.0097
mtry5_trees1000 Mitoses 0.0032
mtry5_trees200 Bare.nuclei 0.1259
mtry5_trees200 Cell.size 0.0898
mtry5_trees200 Cell.shape 0.0427
mtry5_trees200 Cl.thickness 0.0233
mtry5_trees200 Normal.nucleoli 0.0217
mtry5_trees200 Marg.adhesion 0.0209
mtry5_trees200 Bl.cromatin 0.0142
mtry5_trees200 Epith.c.size 0.0086
mtry5_trees200 Mitoses 0.0026
mtry5_trees500 Bare.nuclei 0.1243
mtry5_trees500 Cell.size 0.0909
mtry5_trees500 Cell.shape 0.0460
mtry5_trees500 Cl.thickness 0.0217
mtry5_trees500 Normal.nucleoli 0.0203
mtry5_trees500 Marg.adhesion 0.0195
mtry5_trees500 Bl.cromatin 0.0153
mtry5_trees500 Epith.c.size 0.0093
mtry5_trees500 Mitoses 0.0030
# Membuat grafik variable importance
ggplot(
  importance_all,
  aes(
    x = reorder(Variabel, Permutation_Importance),
    y = Permutation_Importance
  )
) +
  geom_col() +
  coord_flip() +
  facet_wrap(~ Model, scales = "free_y") +
  labs(
    title = "Variable Importance pada Sembilan Model Random Forest",
    x = "Variabel",
    y = "Permutation Importance"
  ) +
  theme_minimal()

Berdasarkan grafik Variable Importance pada sembilan model Random Forest, terlihat bahwa variabel Bare.nuclei memiliki tingkat kepentingan tertinggi pada seluruh model, diikuti oleh Cell.size dan Cell.shape. Hal ini menunjukkan bahwa ketiga variabel tersebut memberikan kontribusi paling besar dalam proses klasifikasi kelas benign dan malignant, karena perubahan atau pengacakan nilai pada variabel tersebut menyebabkan penurunan kinerja model yang relatif lebih besar. Variabel Cl.thickness, Marg.adhesion, Normal.nucleoli, dan Bl.cromatin memiliki tingkat kepentingan yang lebih rendah, sedangkan Epith.c.size dan Mitoses cenderung menjadi variabel dengan tingkat kepentingan paling rendah. Pola tingkat kepentingan variabel tersebut relatif konsisten pada kesembilan model, meskipun terdapat perbedaan besarnya nilai permutation importance. Sehingga, Bare.nuclei, Cell.size, dan Cell.shape merupakan variabel yang paling berkontribusi dalam membedakan kelas kanker pada dataset BreastCancer.

4.7 Menentukan Model Terbaik

# Menggabungkan hasil metrik dan OOB Error
peringkat <- hasil_metrik %>%
  left_join(
    hasil_oob %>% select(Model, OOB_Error),
    by = "Model"
  ) %>%
  mutate(
    Rank_Accuracy = rank(-Accuracy, ties.method = "min"),
    Rank_Precision = rank(-Precision, ties.method = "min"),
    Rank_Recall = rank(-Recall, ties.method = "min"),
    Rank_Specificity = rank(-Specificity, ties.method = "min"),
    Rank_F1 = rank(-F1_Score, ties.method = "min"),
    Rank_OOB = rank(OOB_Error, ties.method = "min"),

    Rata_Rata_Peringkat = rowMeans(
      cbind(
        Rank_Accuracy,
        Rank_Precision,
        Rank_Recall,
        Rank_Specificity,
        Rank_F1,
        Rank_OOB
      ),
      na.rm = TRUE
    )
  ) %>%
  arrange(
    Rata_Rata_Peringkat,
    desc(Recall),
    OOB_Error
  )

# Menampilkan peringkat seluruh model
kable(
  peringkat,
  digits = 4,
  caption = "Peringkat Model Berdasarkan Metrik Testing dan OOB Error"
)
Peringkat Model Berdasarkan Metrik Testing dan OOB Error
Model mtry Num_Trees Accuracy Precision Recall Specificity F1_Score Konfigurasi OOB_Error Rank_Accuracy Rank_Precision Rank_Recall Rank_Specificity Rank_F1 Rank_OOB Rata_Rata_Peringkat
mtry2_trees200 2 200 0.9804 0.9589 0.9859 0.9774 0.9722 mtry=2, trees=200 0.0292 1 1 1 1 1 4 1.5000
mtry3_trees200 3 200 0.9706 0.9577 0.9577 0.9774 0.9577 mtry=3, trees=200 0.0271 3 2 4 1 4 1 2.5000
mtry2_trees500 2 500 0.9755 0.9459 0.9859 0.9699 0.9655 mtry=2, trees=500 0.0292 2 4 1 4 2 4 2.8333
mtry3_trees500 3 500 0.9706 0.9577 0.9577 0.9774 0.9577 mtry=3, trees=500 0.0292 3 2 4 1 4 4 3.0000
mtry2_trees1000 2 1000 0.9706 0.9452 0.9718 0.9699 0.9583 mtry=2, trees=1000 0.0292 3 5 3 4 3 4 3.6667
mtry3_trees1000 3 1000 0.9657 0.9444 0.9577 0.9699 0.9510 mtry=3, trees=1000 0.0271 6 6 4 4 6 1 4.5000
mtry5_trees200 5 200 0.9608 0.9437 0.9437 0.9699 0.9437 mtry=5, trees=200 0.0292 7 7 7 4 7 4 6.0000
mtry5_trees500 5 500 0.9608 0.9437 0.9437 0.9699 0.9437 mtry=5, trees=500 0.0292 7 7 7 4 7 4 6.0000
mtry5_trees1000 5 1000 0.9559 0.9429 0.9296 0.9699 0.9362 mtry=5, trees=1000 0.0271 9 9 9 4 9 1 6.8333
# Menentukan model terbaik
model_pilihan <- peringkat[1, ]

cat(
  "Berdasarkan rata-rata peringkat seluruh metrik testing dan OOB error, konfigurasi dengan peringkat pertama adalah ",
  model_pilihan$Model,
  " (mtry = ", model_pilihan$mtry,
  ", num.trees = ", model_pilihan$Num_Trees,
  "). Penetapan ini merupakan ringkasan perbandingan dari sembilan konfigurasi yang diuji.",
  sep = ""
)
## Berdasarkan rata-rata peringkat seluruh metrik testing dan OOB error, konfigurasi dengan peringkat pertama adalah mtry2_trees200 (mtry = 2, num.trees = 200). Penetapan ini merupakan ringkasan perbandingan dari sembilan konfigurasi yang diuji.
# Mengidentifikasi lima variabel terpenting
importance_pilihan <- importance_all %>%
  filter(Model == model_pilihan$Model) %>%
  arrange(desc(Permutation_Importance))

kable(
  head(importance_pilihan, 5),
  digits = 4,
  caption = paste(
    "Lima Variabel Terpenting pada Model",
    model_pilihan$Model
  )
)
Lima Variabel Terpenting pada Model mtry2_trees200
Model Variabel Permutation_Importance
mtry2_trees200 Bare.nuclei 0.0839
mtry2_trees200 Cell.size 0.0787
mtry2_trees200 Cell.shape 0.0610
mtry2_trees200 Cl.thickness 0.0245
mtry2_trees200 Bl.cromatin 0.0215

Berdasarkan tabel Permutation Importance pada model terbaik mtry2_trees200, variabel Bare.nuclei memiliki tingkat kepentingan tertinggi dengan nilai sebesar 0,0839, diikuti oleh Cell.size sebesar 0,0787 dan Cell.shape sebesar 0,0610. Selanjutnya, variabel Cl.thickness dan Bl.cromatin memiliki nilai kepentingan masing-masing sebesar 0,0245 dan 0,0215. Hasil tersebut menunjukkan bahwa Bare.nuclei, Cell.size, dan Cell.shape merupakan tiga variabel yang paling berkontribusi dalam proses klasifikasi pada model terbaik. Sedangkan, Bl.cromatin menjadi variabel dengan tingkat kepentingan terendah di antara lima variabel yang ditampilkan. Semakin tinggi nilai Permutation Importance, semakin besar kontribusi variabel tersebut terhadap kemampuan model dalam melakukan klasifikasi.

BAB V KESIMPULAN

5.1 Kesimpulan

Random Forest dan Double Random Forest merupakan metode ensemble learning berbasis decision tree yang menggabungkan sejumlah pohon keputusan untuk menghasilkan prediksi yang lebih baik. Kedua metode tersebut memanfaatkan proses pengacakan dalam pembentukan model untuk mengurangi kesalahan prediksi. Perbedaannya terletak pada mekanisme pembentukan pohon dan penerapan pengacakan dalam proses pemodelannya.

Implementasi Random Forest dan Double Random Forest dapat dilakukan untuk permasalahan klasifikasi maupun regresi dengan menyesuaikan jenis variabel respon dan hasil prediksi yang diharapkan. Pada klasifikasi, hasil prediksi ditentukan berdasarkan suara mayoritas pohon, sedangkan pada regresi diperoleh melalui rata-rata prediksi seluruh pohon. Penerapan kedua metode dilakukan melalui tahapan persiapan data, pembentukan model, prediksi, dan evaluasi.

Evaluasi performa model dapat dilakukan menggunakan metrik yang sesuai dengan jenis permasalahan, seperti accuracy, precision, recall, specificity, dan F1-score untuk klasifikasi serta metrik kesalahan prediksi untuk regresi. Nilai Out-of-Bag (OOB) error digunakan untuk memperkirakan tingkat kesalahan model menggunakan data yang tidak terpilih dalam proses pembentukan setiap pohon. Perbandingan nilai evaluasi dan OOB error dapat digunakan untuk menentukan metode yang memberikan performa prediksi lebih baik.

Berdasarkan hasil analisis dapat disimpulkan bahwa model Random Forest terbaik diperoleh pada konfigurasi mtry2_trees200 dengan nilai accuracy sebesar 98,04%, Precision sebesar 95,89%, Recall sebesar 98,59%, Specificity sebesar 97,74%, dan F1-score sebesar 97,22%. Model tersebut juga mampu menghasilkan tingkat kesalahan klasifikasi yang rendah serta menunjukkan kinerja yang baik dalam mengklasifikasikan kelas benign dan malignant. Variabel yang paling berkontribusi terhadap hasil klasifikasi adalah Bare.nuclei, Cell.size, dan Cell.shape.

DAFTAR PUSTAKA

Fransiska, H. (2026). Modul Praktikum Machine Learning dan Modern Prediction. Laboratorium Matematika Fakultas Matematika dan Ilmu Pengetahuan Alam Universitas Bengkulu.

Hasanah, U., Soleh, A. M., & Sadik, K. (2024). Pengaruh Random Undersampling, Oversampling, dan SMOTE terhadap Kinerja Model Prediksi Penyakit Kardiovaskular. Jurnal Matematika, Statistika Dan Komputasi, 21(1), 88–102. https://doi.org/10.20956/j.v21i1.35552

Khairunnisa, A., Notodiputro, K. A., & Sartono, B. (2024). A Comparative Study of Random Forest and Double Random Forest Models from View Points of Their Interpretability. Scientific Journal of Informatics, 11(1), 207–218. https://doi.org/10.15294/sji.v11i1.48721

Purwanto, A., Sartono, B., & Notodiputro, K. A. (2025). a Comparison of Random Forest and Double Random Forest: Dropout Rates of Madrasah Students in Indonesia. Barekeng, 19(1), 227–236. https://doi.org/10.30598/barekengvol19iss1pp227-236