Pada praktikum sebelumnya, kondisi kanker payudara diklasifikasikan menggunakan dua metode ensemble, yaitu Bagging yang membangun banyak pohon secara paralel dari sampel bootstrap dan Boosting yang membangun pohon sederhana secara berurutan. Bagging mampu menurunkan variance, tetapi manfaatnya terbatas apabila pohon-pohon yang dibangun saling mirip. Hal ini sering terjadi ketika terdapat beberapa variabel prediktor yang sangat kuat, karena hampir semua pohon akan memilih variabel tersebut pada pemisahan-pemisahan awal sehingga prediksinya saling berkorelasi (Hastie dkk., 2009; James dkk., 2021).
Random Forest yang diperkenalkan oleh Breiman (2001) mengatasi masalah tersebut dengan menambahkan pengacakan pada pemilihan variabel prediktor. Pada setiap simpul, hanya sebanyak mtry prediktor yang dipilih secara acak untuk dipertimbangkan sebagai kandidat pemisah, sehingga pohon-pohon dalam forest menjadi lebih beragam dan korelasi antarpohon berkurang. Selanjutnya, Han dkk. (2020) mengembangkan Double Random Forest (DRF) untuk situasi ketika Random Forest masih mengalami underfitting. Pada DRF, setiap pohon dibangun dari seluruh data training, sedangkan bootstrap dilakukan pada setiap simpul ketika mencari aturan pemisahan.
Kanker payudara merupakan kanker yang paling banyak didiagnosis di dunia pada tahun 2020 dengan sekitar 2,3 juta kasus baru (Sung dkk., 2021), sehingga model yang mampu membedakan tumor jinak (benign) dan ganas (malignant) dengan baik tetap penting untuk dikaji. Dataset BreastCancer pada paket mlbench yang digunakan pada pertemuan sebelumnya kembali digunakan pada praktikum ini. Performa Random Forest dipengaruhi oleh beberapa hyperparameter, terutama mtry yang mengatur tingkat pengacakan prediktor dan num.trees yang mengatur banyaknya pohon (Probst dkk., 2019). Oleh karena itu, pada praktikum ini dibandingkan sembilan kombinasi model, yaitu mtry = 2, 3, dan 5 dengan num.trees = 200, 500, dan 1000. Kemampuan model dievaluasi menggunakan confusion matrix, accuracy, precision, recall, specificity, dan F1-Score pada data testing (Sokolova & Lapalme, 2009), serta out-of-bag (OOB) error sebagai evaluasi internal model. Berdasarkan hal tersebut, pada praktikum Pertemuan 5 ini dilakukan Random Forest Classification untuk mengklasifikasikan kondisi kanker payudara menggunakan paket ranger di RStudio (Wright & Ziegler, 2017).
Berdasarkan latar belakang di atas, rumusan masalah dalam praktikum ini adalah sebagai berikut:
Berdasarkan rumusan masalah di atas, tujuan praktikum ini adalah sebagai berikut:
Adapun manfaat pada penelitian ini yaitu:
Adapun batasan masalah pada praktikum ini adalah lakukan Random Forest Classification pada data BreastCancer. Bandingkan mtry = 2, 3, dan 5 dengan num.trees = 200, 500, dan 1000. Bandingkan performa data testing berdasarkan confusion matrix, accuracy, precision, recall, specificity, F1-Score, dan variable importance. Tampilkan pula OOB error sebagai evaluasi internal model. Gunakan set.seed(234) agar hasil dapat direproduksi.
Adapun sistematika penulisan dari praktikum ini adalah:
BAB IPENDAHULUAN
Bab I terdiri dari latar belakang, rumusan masalah, tujuan penelitian, manfaat penelitian, batasan masalah, dan sistematika penulisan.
BAB IITINJAUAN PUSTAKA
Bab ini berisi kajian pustaka dari jurnal, buku, dan modul praktikum tentang Random Forest, Double Random Forest, out-of-bag error, variable importance, dan evaluasi model klasifikasi.
BAB IIIMETODE PENELITIAN
Bab ini terdiri dari sumber data, variabel penelitian, langkah-langkah analisis, dan diagram alir.
BAB IVHASIL DAN PEMBAHASAN
Bab ini merupakan tahapan pencapaian hasil yang diperoleh dari analisis data yang dilakukan serta penjelasan dari hasil tersebut di bagian pembahasan.
BAB VKESIMPULAN DAN SARAN
Bab ini merupakan bagian penutup dalam laporan ini berupa penarikan kesimpulan mengenai hasil analisis dari penelitian serta penyampaian saran oleh penulis.
DAFTAR PUSTAKA
LAMPIRAN
Random Forest adalah algoritma ensemble learning berbasis pohon yang membangun banyak decision tree kemudian menggabungkan prediksinya untuk meningkatkan akurasi dan mengurangi overfitting. Random Forest merupakan pengembangan dari Bagging (Breiman, 1996), yaitu sama-sama membentuk banyak pohon dari sampel bootstrap lalu menggabungkan hasil prediksinya (James dkk., 2021). Perbedaannya, Random Forest menambahkan pengacakan pada pemilihan prediktor di setiap simpul, sehingga pohon-pohon tidak hanya dibangun dari sampel yang berbeda, tetapi juga tidak selalu mempertimbangkan prediktor yang sama ketika mencari pemisahan terbaik (Breiman, 2001).
Tujuan pengacakan prediktor adalah mengurangi korelasi antarpohon. Jika \(B\) pohon masing-masing memiliki variance \(\sigma^2\) dan korelasi antarpasangan sebesar \(\rho\), maka variance rata-rata prediksinya adalah \[ \text{Var}\left(\bar{f}\right) = \rho\,\sigma^2 + \frac{1 - \rho}{B}\,\sigma^2 \tag{2.1} \] Suku kedua pada Persamaan (2.1) mengecil ketika \(B\) bertambah, tetapi suku pertama tidak dapat diturunkan dengan menambah pohon. Suku pertama hanya dapat diturunkan dengan mengurangi korelasi \(\rho\), dan itulah yang dilakukan oleh Random Forest (Hastie dkk., 2009). Perbedaan Bagging dan Random Forest dapat dilihat pada Tabel 1.
| Aspek | Bagging | Random Forest |
|---|---|---|
| Data tiap pohon | Umumnya sampel bootstrap | Umumnya sampel bootstrap |
| Prediktor pada pemisahan | Semua prediktor dapat dipertimbangkan | Hanya mtry prediktor yang dipilih secara acak |
| Korelasi antarpohon | Dapat relatif tinggi | Ditekan melalui random feature selection |
| Agregasi klasifikasi | Majority voting | Majority voting |
| Agregasi regresi | Rata-rata prediksi | Rata-rata prediksi |
| Fokus utama | Mengurangi variance melalui agregasi | Mengurangi variance sekaligus mendekorelasi pohon |
Misalkan tersedia data training \(D = \{(x_i, y_i)\}\), \(i = 1, 2, \ldots, n\), dengan \(p\) variabel prediktor, dan akan dibentuk \(B\) pohon. Proses Random Forest dilakukan sebagai berikut (Breiman, 2001; Laboratorium Matematika FMIPA Universitas Bengkulu, 2026).
Pada kasus klasifikasi, prediksi akhir diperoleh melalui majority voting, yaitu \[ \hat{G}_{RF}(x) = \text{mode}\left\{G_1(x), G_2(x), \ldots, G_B(x)\right\} \tag{2.2} \] dengan \(G_b(x)\) adalah kelas hasil prediksi pohon ke-\(b\). Proporsi pohon yang memilih suatu kelas dapat digunakan sebagai skor atau tingkat keyakinan prediksi. Pada kasus regresi, prediksi akhir adalah rata-rata prediksi seluruh pohon, yaitu \[ \hat{f}_{RF}(x) = \frac{1}{B}\sum_{b=1}^{B} T_b(x) \tag{2.3} \] dengan \(T_b(x)\) adalah nilai prediksi pohon ke-\(b\). Dengan demikian, Random Forest tetap merupakan metode parallel ensemble, yaitu setiap pohon dibentuk secara relatif independen, berbeda dengan Boosting yang bersifat sekuensial. Alur kerja Random Forest dapat dilihat pada Gambar 1.
Gambar 1. Alur kerja Random Forest Classification
Pada Gambar 1, setiap pohon dibangun dari sampel bootstrap yang berbeda, dan pada setiap simpul hanya mtry prediktor acak yang dipertimbangkan. Ketika ada data baru, setiap pohon memberikan prediksinya sendiri, lalu prediksi akhir ditentukan berdasarkan suara terbanyak.
Pada sampel bootstrap berukuran \(n\) yang diambil dengan pengembalian dari \(n\) observasi, peluang suatu observasi tidak terambil adalah \[ \left(1 - \frac{1}{n}\right)^{n} \approx e^{-1} \approx 0{,}368 \tag{2.4} \] untuk \(n\) yang besar, sehingga proporsi observasi unik dalam satu sampel bootstrap mendekati \(1 - e^{-1} \approx 0{,}632\) (Efron & Tibshirani, 1993). Artinya, sekitar 36,8% observasi tidak digunakan untuk membentuk suatu pohon dan disebut observasi out-of-bag (OOB). Untuk setiap observasi, prediksi OOB diperoleh hanya dari pohon-pohon yang tidak menggunakan observasi tersebut saat dibentuk, sehingga OOB error untuk klasifikasi dapat dihitung sebagai \[ \text{Err}_{\text{OOB}} = \frac{1}{n}\sum_{i=1}^{n} I\left(y_i \neq \hat{G}_{\text{OOB}}(x_i)\right) \tag{2.5} \] dengan \(I(\cdot)\) adalah fungsi indikator. OOB error merupakan ukuran evaluasi internal Random Forest yang dapat memperkirakan galat pada data baru tanpa memerlukan data uji terpisah (Breiman, 2001). Pada paket ranger, OOB error dihitung secara otomatis dan disimpan pada komponen prediction.error. Untuk klasifikasi, nilai ini menyatakan proporsi salah klasifikasi OOB, sedangkan untuk regresi menyatakan OOB Mean Squared Error (Wright & Ziegler, 2017).
Double Random Forest (DRF) adalah metode yang diperkenalkan oleh Han dkk. (2020) untuk situasi ketika Random Forest masih mengalami underfitting karena pohon yang dihasilkan belum cukup besar. Pada Random Forest standar, setiap pohon dibentuk dari satu sampel bootstrap yang hanya mengandung sekitar 63,2% observasi unik, sehingga observasi yang tersedia untuk membentuk pohon lebih sedikit daripada seluruh data training. Pada DRF, setiap pohon dibangun menggunakan seluruh data training, sedangkan bootstrap digunakan sementara pada setiap simpul untuk mencari aturan pemisahan. Proses DRF secara sederhana adalah sebagai berikut (Laboratorium Matematika FMIPA Universitas Bengkulu, 2026).
Alur kerja DRF dapat dilihat pada Gambar 2.
Gambar 2. Alur kerja Double Random Forest
Karena setiap pohon menggunakan seluruh data training, DRF cenderung menghasilkan pohon yang lebih besar. Pada saat yang sama, bootstrap pada setiap simpul dan pemilihan prediktor acak tetap menambahkan keragaman pada aturan pemisahan. Konsekuensinya, DRF umumnya membutuhkan waktu komputasi lebih besar karena proses bootstrap dilakukan berulang pada banyak simpul. Perbedaan Random Forest dan DRF dapat dilihat pada Tabel 2.
| Aspek | Random Forest | Double Random Forest |
|---|---|---|
| Data tiap pohon | Sampel bootstrap yang berbeda-beda dari data training | Seluruh data training yang sama |
| Observasi unik per pohon | Sekitar \(1 - e^{-1} \approx 0{,}632\) dari data training | Seluruh data training, bootstrap hanya sementara di setiap simpul |
| Proses pemisahan | Random feature subset | Bootstrap sampling pada setiap simpul dan random feature subset |
| Ukuran pohon | Relatif lebih kecil | Cenderung lebih besar dan beragam |
| Waktu komputasi | Lebih cepat | Lebih lama |
| Prediksi akhir | Majority voting dari \(B\) pohon | Majority voting dari \(B\) pohon |
Pada kasus klasifikasi, pemisahan terbaik pada setiap simpul dipilih berdasarkan penurunan indeks Gini (Breiman dkk., 1984), yaitu \[ \text{Gini}(t) = 1 - \sum_{k=1}^{K} p(k \mid t)^2 \tag{2.6} \] dengan \(p(k \mid t)\) adalah proporsi observasi kelas ke-\(k\) pada simpul \(t\). Nilai Gini semakin kecil ketika simpul semakin murni.
Variable importance mengukur seberapa besar kontribusi suatu prediktor terhadap kemampuan prediksi model. Pada permutation importance, nilai suatu prediktor pada data OOB diacak sehingga hubungannya dengan respon terputus, kemudian dihitung kenaikan galat prediksi akibat pengacakan tersebut (Breiman, 2001; Wright & Ziegler, 2017). Untuk prediktor ke-\(j\), \[ VI_j = \frac{1}{B}\sum_{b=1}^{B}\left(\text{Err}_{b}^{(j)} - \text{Err}_{b}\right) \tag{2.7} \] dengan \(\text{Err}_b\) adalah galat klasifikasi pohon ke-\(b\) pada data OOB-nya dan \(\text{Err}_b^{(j)}\) adalah galat yang sama setelah nilai prediktor ke-\(j\) diacak. Semakin besar \(VI_j\), semakin penting prediktor tersebut. Nilai yang mendekati nol menunjukkan bahwa prediktor tersebut hampir tidak membantu prediksi.
Random Forest pada praktikum ini dijalankan menggunakan fungsi ranger() dari paket ranger (Wright & Ziegler, 2017). Argumen yang digunakan dan perannya dapat dilihat pada Tabel 3.
| Argumen | Nilai | Peran |
|---|---|---|
| num.trees | 200, 500, 1000 | Banyaknya pohon yang dibentuk dalam ensemble |
| mtry | 2, 3, 5 | Banyaknya prediktor kandidat yang dipilih secara acak pada setiap simpul |
| min.node.size | 1 | Ukuran minimum simpul akhir, sehingga pohon dibiarkan tumbuh dalam |
| replace dan sample.fraction | TRUE dan 1 | Sampel bootstrap diambil dengan pengembalian sebanyak \(n\) observasi |
| splitrule | “gini” (default) | Aturan pemisahan berdasarkan indeks Gini pada Persamaan (2.6) |
| importance | “permutation” | Variable importance dihitung dengan permutation importance pada Persamaan (2.7) |
| seed | 234 | Mengatur pengacakan agar hasil dapat direproduksi |
Nilai mtry yang kecil membuat pohon lebih beragam tetapi setiap pohon cenderung kurang akurat, sedangkan mtry yang besar membuat setiap pohon lebih kuat tetapi lebih mirip satu sama lain. Jika mtry sama dengan banyaknya prediktor, Random Forest menjadi sama dengan Bagging. Untuk klasifikasi, nilai default yang umum digunakan adalah \(\lfloor\sqrt{p}\,\rfloor\) (Breiman, 2001; Probst dkk., 2019). Sementara itu, menambah num.trees tidak menyebabkan overfitting, tetapi manfaatnya semakin kecil setelah jumlah pohon cukup besar dan waktu komputasi terus bertambah (Breiman, 2001; Probst dkk., 2019).
Salah satu cara sederhana untuk menangani missing value adalah listwise deletion, yaitu menghapus observasi yang memiliki data kosong pada salah satu variabel (van Buuren, 2018). Cara ini mudah dilakukan, tetapi mengurangi ukuran data sehingga sebaiknya digunakan ketika jumlah data kosong relatif sedikit. Setelah data lengkap, data dibagi menjadi data training untuk melatih model dan data testing untuk menguji model pada data yang belum pernah dilihat (Muraina, 2022). Pembagian dilakukan secara stratified menggunakan fungsi createDataPartition() dari paket caret agar proporsi kelas pada data training dan testing sama dengan data awal (Kuhn, 2008).
Evaluasi model klasifikasi dilakukan dengan membandingkan kelas aktual dan kelas hasil prediksi dalam confusion matrix (Sokolova & Lapalme, 2009) seperti pada Tabel 4.
| Predicted Positive | Predicted Negative | |
|---|---|---|
| Actual Positive | True Positive (TP) | False Negative (FN) |
| Actual Negative | False Positive (FP) | True Negative (TN) |
Ukuran evaluasi yang digunakan adalah sebagai berikut. \[ \text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN} \tag{2.8} \] \[ \text{Precision} = \frac{TP}{TP + FP} \tag{2.9} \] \[ \text{Recall} = \frac{TP}{TP + FN} \tag{2.10} \] \[ \text{Specificity} = \frac{TN}{TN + FP} \tag{2.11} \] \[ \text{F1-Score} = 2\left(\frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}\right) \tag{2.12} \]
Accuracy adalah proporsi prediksi yang benar, precision adalah proporsi prediksi positif yang benar-benar positif, recall adalah kemampuan model mengenali kelas positif, specificity adalah kemampuan model mengenali kelas negatif, dan F1-Score adalah rata-rata harmonik dari precision dan recall. Semakin besar nilai kelima ukuran tersebut, semakin baik model. Kelas positif yang digunakan adalah malignant (ganas), sehingga False Negative berarti tumor ganas yang diprediksi jinak dan False Positive berarti tumor jinak yang diprediksi ganas.
Data yang digunakan adalah data sekunder berupa dataset BreastCancer yang tersedia pada paket mlbench di R (Leisch & Dimitriadou, 2010). Data ini berasal dari penelitian Wolberg dan Mangasarian (1990) yang dikumpulkan di University of Wisconsin Hospitals, Madison. Data terdiri dari 699 observasi dan 11 variabel, yaitu satu variabel pengenal, sembilan variabel karakteristik sel, dan satu variabel kelas.
Variabel yang digunakan terdiri dari satu variabel target dan sembilan variabel prediktor. Variabel target (Y) adalah Class yang terdiri dari dua kategori, yaitu benign (jinak) dan malignant (ganas). Variabel prediktor (X) berupa hasil penilaian karakteristik sel dengan skor 1 sampai 10 yang pada R terbaca sebagai data kategorik (factor). Variabel Id hanya berupa kode pengenal sampel sehingga tidak digunakan dalam analisis. Rincian variabel dapat dilihat pada Tabel 5.
| Variabel | Keterangan | Peran |
|---|---|---|
| Id | Kode sampel | Tidak digunakan |
| Cl.thickness | Ketebalan gumpalan sel (clump thickness) | Prediktor (X1) |
| Cell.size | Keseragaman ukuran sel | Prediktor (X2) |
| Cell.shape | Keseragaman bentuk sel | Prediktor (X3) |
| Marg.adhesion | Adhesi marginal (marginal adhesion) | Prediktor (X4) |
| Epith.c.size | Ukuran sel epitel tunggal | Prediktor (X5) |
| Bare.nuclei | Inti sel telanjang (bare nuclei) | Prediktor (X6) |
| Bl.cromatin | Kromatin halus (bland chromatin) | Prediktor (X7) |
| Normal.nucleoli | Nukleolus normal | Prediktor (X8) |
| Mitoses | Mitosis | Prediktor (X9) |
| Class | Kondisi tumor: benign atau malignant | Target (Y) |
Langkah-langkah analisis yang dilakukan adalah sebagai berikut.
Gambar 3. Diagram alir penelitian
Pada Gambar 3, data BreastCancer terlebih dahulu dipersiapkan dan dibagi menjadi data training dan testing. Selanjutnya dibentuk grid sembilan kombinasi mtry dan num.trees. Untuk setiap kombinasi, model Random Forest dibangun, OOB error dihitung sebagai evaluasi internal, lalu model digunakan untuk memprediksi data testing dan dihitung confusion matrix, ukuran evaluasi, serta variable importance-nya. Proses tersebut diulang sampai kesembilan model terbentuk, kemudian seluruh model dibandingkan untuk menentukan model terbaik.
Library yang digunakan adalah ranger, mlbench, caret, dan ggplot2. Paket ranger digunakan untuk membangun model Random Forest, mlbench untuk mengambil dataset, caret untuk membagi data dan membuat confusion matrix, serta ggplot2 untuk visualisasi.
## 'data.frame': 699 obs. of 11 variables:
## $ Id : chr "1000025" "1002945" "1015425" "1016277" ...
## $ Cl.thickness : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 5 5 3 6 4 8 1 2 2 4 ...
## $ Cell.size : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 1 4 1 8 1 10 1 1 1 2 ...
## $ Cell.shape : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 1 4 1 8 1 10 1 2 1 1 ...
## $ Marg.adhesion : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 1 5 1 1 3 8 1 1 1 1 ...
## $ Epith.c.size : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 2 7 2 3 2 7 2 2 2 2 ...
## $ Bare.nuclei : Factor w/ 10 levels "1","2","3","4",..: 1 10 2 4 1 10 10 1 1 1 ...
## $ Bl.cromatin : Factor w/ 10 levels "1","2","3","4",..: 3 3 3 3 3 9 3 3 1 2 ...
## $ Normal.nucleoli: Factor w/ 10 levels "1","2","3","4",..: 1 2 1 7 1 7 1 1 1 1 ...
## $ Mitoses : Factor w/ 9 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 5 1 ...
## $ Class : Factor w/ 2 levels "benign","malignant": 1 1 1 1 1 2 1 1 1 1 ...
## Id Cl.thickness Cell.size Cell.shape Marg.adhesion
## 0 0 0 0 0
## Epith.c.size Bare.nuclei Bl.cromatin Normal.nucleoli Mitoses
## 0 16 0 0 0
## Class
## 0
Data terdiri dari 699 observasi dan 11 variabel. Variabel Id bertipe karakter, sembilan variabel karakteristik sel bertipe kategorik (Ord.factor atau Factor) dengan skor 1 sampai 10, dan Class memiliki dua level, yaitu benign dan malignant. Missing value hanya terdapat pada variabel Bare.nuclei sebanyak 16 data. Pada fungsi ranger(), variabel factor diperlakukan sebagai variabel berurutan sesuai urutan levelnya, sehingga skor 1 sampai 10 tetap dibaca sesuai urutan tingkatannya.
Persiapan data dilakukan sesuai sintaks modul, yaitu menghapus variabel Id, menghapus observasi yang mengandung missing value, dan memastikan variabel respon bertipe factor.
## [1] 683 10
## [1] "benign" "malignant"
##
## benign malignant
## 444 239
##
## benign malignant
## 65.01 34.99
Setelah variabel Id dan 16 observasi yang mengandung missing value dihapus, data tersisa 683 observasi dan 10 variabel. Observasi yang dihapus hanya sekitar 2,29% dari data awal, sehingga pengurangan ukuran data akibat listwise deletion tergolong kecil. Data terdiri dari 444 observasi benign (65,01%) dan 239 observasi malignant (34,99%).
set.seed(234)
idx.cls <- createDataPartition(bc$Class, p = 0.70, list = FALSE)
bc.train <- bc[idx.cls, ]
bc.test <- bc[-idx.cls, ]
dim(bc.train)## [1] 479 10
## [1] 204 10
##
## benign malignant
## 311 168
##
## benign malignant
## 133 71
Data dibagi menjadi 479 data training (311 benign dan 168 malignant) dan 204 data testing (133 benign dan 71 malignant). Proporsi kelas pada data training (64,93% dan 35,07%) dan data testing (65,20% dan 34,80%) hampir sama dengan data awal, sehingga pembagian secara stratified berhasil menjaga komposisi kelas. Kesembilan model dilatih dan diuji menggunakan data yang sama, sehingga perbedaan hasilnya hanya berasal dari nilai mtry dan num.trees.
Model dibangun menggunakan fungsi ranger() dengan pengaturan yang sama seperti sintaks modul. Kombinasi mtry = 2, 3, 5 dan num.trees = 200, 500, 1000 dibentuk menggunakan expand.grid(), sehingga diperoleh sembilan model.
grid <- expand.grid(mtry = c(2, 3, 5), num.trees = c(200, 500, 1000))
grid$Model <- paste0("mtry=", grid$mtry, ", ntree=", grid$num.trees)
grid## mtry num.trees Model
## 1 2 200 mtry=2, ntree=200
## 2 3 200 mtry=3, ntree=200
## 3 5 200 mtry=5, ntree=200
## 4 2 500 mtry=2, ntree=500
## 5 3 500 mtry=3, ntree=500
## 6 5 500 mtry=5, ntree=500
## 7 2 1000 mtry=2, ntree=1000
## 8 3 1000 mtry=3, ntree=1000
## 9 5 1000 mtry=5, ntree=1000
set.seed(234)
rf <- lapply(seq_len(nrow(grid)), function(i) {
ranger(Class ~ ., data = bc.train,
num.trees = grid$num.trees[i],
mtry = grid$mtry[i],
min.node.size = 1,
replace = TRUE,
sample.fraction = 1,
importance = "permutation",
seed = 234)
})
names(rf) <- grid$Model
# contoh output untuk mtry = 3 dan num.trees = 500 (pengaturan pada sintaks modul)
rf[["mtry=3, ntree=500"]]## Ranger result
##
## Call:
## ranger(Class ~ ., data = bc.train, num.trees = grid$num.trees[i], mtry = grid$mtry[i], min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation", seed = 234)
##
## Type: Classification
## Number of trees: 500
## Sample size: 479
## Number of independent variables: 9
## Mtry: 3
## Target node size: 1
## Variable importance mode: permutation
## Splitrule: gini
## OOB prediction error: 2.92 %
Output model mtry = 3 dan num.trees = 500 menunjukkan bahwa model bertipe klasifikasi dengan 479 data training, 9 variabel prediktor, ukuran simpul minimum 1, aturan pemisahan Gini, dan permutation importance. Nilai mtry = 3 sama dengan \(\lfloor\sqrt{9}\,\rfloor\), yaitu nilai default untuk klasifikasi, sedangkan mtry = 2 dan 5 masing-masing mewakili pengacakan yang lebih kuat dan lebih lemah. OOB prediction error model ini sebesar 2,92%.
OOB error digunakan sebagai evaluasi internal model karena dihitung dari data training yang tidak terambil pada setiap sampel bootstrap, sesuai Persamaan (2.5).
oob <- data.frame(grid[, c("mtry", "num.trees")],
OOB_error = sapply(rf, function(m) m$prediction.error), row.names = NULL)
oob$Salah_OOB <- round(oob$OOB_error * nrow(bc.train))
oob## mtry num.trees OOB_error Salah_OOB
## 1 2 200 0.02922756 14
## 2 3 200 0.02713987 13
## 3 5 200 0.02922756 14
## 4 2 500 0.02922756 14
## 5 3 500 0.02922756 14
## 6 5 500 0.02922756 14
## 7 2 1000 0.02922756 14
## 8 3 1000 0.02713987 13
## 9 5 1000 0.02713987 13
# confusion matrix OOB pada model mtry = 2 dan num.trees = 200
rf[["mtry=2, ntree=200"]]$confusion.matrix## predicted
## true benign malignant
## benign 303 8
## malignant 6 162
OOB error kesembilan model sangat mirip, yaitu antara 0,0271 dan 0,0292. Nilai ini setara dengan 13 atau 14 dari 479 data training yang salah diklasifikasikan, atau akurasi OOB sekitar 97,08% sampai 97,29%. OOB error terkecil (0,0271) diperoleh model mtry = 3 dengan num.trees = 200, mtry = 3 dengan num.trees = 1000, dan mtry = 5 dengan num.trees = 1000, sedangkan model lainnya memiliki OOB error 0,0292. Karena selisihnya hanya satu observasi, OOB error menunjukkan bahwa kesembilan model memiliki kemampuan yang hampir sama. Sebagai contoh, confusion matrix OOB model mtry = 2 dan num.trees = 200 menunjukkan 8 tumor jinak diprediksi ganas dan 6 tumor ganas diprediksi jinak, sehingga total 14 observasi salah diklasifikasikan.
Prediksi dilakukan menggunakan predict() seperti sintaks modul (A6). Karena banyaknya pohon yang digunakan genap, dapat terjadi suara seri antarkelas. Oleh karena itu, hasil prediksi setiap pohon juga diambil dengan argumen predict.all = TRUE untuk menghitung proporsi pohon yang memilih malignant pada setiap observasi.
pred.rf.cls <- lapply(rf, function(m)
factor(predict(m, data = bc.test, seed = 234)$predictions, levels = levels(bc.test$Class)))
hasil.rf.cls <- data.frame(Aktual = bc.test$Class, pred.rf.cls[c(1, 2, 3)], check.names = FALSE)
head(hasil.rf.cls, 10)## Aktual mtry=2, ntree=200 mtry=3, ntree=200 mtry=5, ntree=200
## 1 benign malignant malignant malignant
## 2 benign benign benign benign
## 3 benign benign benign malignant
## 4 benign benign benign benign
## 5 benign benign benign benign
## 6 malignant malignant malignant malignant
## 7 benign benign benign benign
## 8 benign benign benign benign
## 9 benign benign benign benign
## 10 malignant malignant malignant malignant
# proporsi pohon yang memilih malignant pada setiap observasi testing
prop.mal <- lapply(rf, function(m) {
suara <- predict(m, data = bc.test, predict.all = TRUE)$predictions
rowMeans(suara == match("malignant", m$forest$levels))
})
# banyaknya observasi testing dengan suara seri (50% : 50%)
sapply(prop.mal, function(s) sum(s == 0.5))## mtry=2, ntree=200 mtry=3, ntree=200 mtry=5, ntree=200 mtry=2, ntree=500
## 0 1 0 0
## mtry=3, ntree=500 mtry=5, ntree=500 mtry=2, ntree=1000 mtry=3, ntree=1000
## 0 0 0 0
## mtry=5, ntree=1000
## 0
Pada 10 observasi pertama data testing, model mtry = 2 dan 3 dengan num.trees = 200 memprediksi 9 observasi dengan benar, sedangkan model mtry = 5 hanya memprediksi 8 observasi dengan benar. Observasi pertama sebenarnya benign, tetapi diprediksi malignant oleh ketiga model, dan observasi ketiga yang juga benign diprediksi malignant oleh model mtry = 5. Pada model mtry = 3 dan num.trees = 200 terdapat satu observasi yang mendapat suara seri, yaitu 100 pohon memilih benign dan 100 pohon memilih malignant. Fungsi predict() pada ranger menentukan kelas observasi yang seri secara acak, sehingga argumen seed = 234 ditambahkan agar hasil prediksi selalu sama setiap kali dijalankan. Suara seri hanya mungkin terjadi karena jumlah pohon genap, dan pada delapan model lainnya tidak ditemukan suara seri.
Ukuran evaluasi dihitung dengan cara yang sama seperti sintaks modul (A7), yaitu mengambil nilai TN, FP, FN, dan TP dari tabel aktual dan prediksi, kemudian menghitung ukuran evaluasi sesuai Persamaan (2.8) sampai (2.12). Karena terdapat sembilan model, perhitungan tersebut dibuat dalam fungsi evaluasi() agar dapat diterapkan pada setiap model.
evaluasi <- function(p) {
tab.rf <- table(Aktual = bc.test$Class, Prediksi = p)
TN <- tab.rf["benign", "benign"]
FP <- tab.rf["benign", "malignant"]
FN <- tab.rf["malignant", "benign"]
TP <- tab.rf["malignant", "malignant"]
Accuracy <- (TP + TN) / (TP + TN + FP + FN)
Precision <- TP / (TP + FP)
Recall <- TP / (TP + FN)
Specificity <- TN / (TN + FP)
F1 <- 2 * (Precision * Recall) / (Precision + Recall)
c(TN = TN, FP = FP, FN = FN, TP = TP, Accuracy = Accuracy, Precision = Precision,
Recall = Recall, Specificity = Specificity, F1_Score = F1)
}
evaluasi.rf <- t(sapply(pred.rf.cls, evaluasi))
# komponen confusion matrix setiap model
evaluasi.rf[, c("TN", "FP", "FN", "TP")]## TN FP FN TP
## mtry=2, ntree=200 130 3 1 70
## mtry=3, ntree=200 130 3 2 69
## mtry=5, ntree=200 129 4 4 67
## mtry=2, ntree=500 129 4 1 70
## mtry=3, ntree=500 130 3 3 68
## mtry=5, ntree=500 129 4 4 67
## mtry=2, ntree=1000 129 4 2 69
## mtry=3, ntree=1000 129 4 3 68
## mtry=5, ntree=1000 129 4 5 66
# ukuran evaluasi setiap model
round(evaluasi.rf[, c("Accuracy", "Precision", "Recall", "Specificity", "F1_Score")], 4)## Accuracy Precision Recall Specificity F1_Score
## mtry=2, ntree=200 0.9804 0.9589 0.9859 0.9774 0.9722
## mtry=3, ntree=200 0.9755 0.9583 0.9718 0.9774 0.9650
## mtry=5, ntree=200 0.9608 0.9437 0.9437 0.9699 0.9437
## mtry=2, ntree=500 0.9755 0.9459 0.9859 0.9699 0.9655
## mtry=3, ntree=500 0.9706 0.9577 0.9577 0.9774 0.9577
## mtry=5, ntree=500 0.9608 0.9437 0.9437 0.9699 0.9437
## mtry=2, ntree=1000 0.9706 0.9452 0.9718 0.9699 0.9583
## mtry=3, ntree=1000 0.9657 0.9444 0.9577 0.9699 0.9510
## mtry=5, ntree=1000 0.9559 0.9429 0.9296 0.9699 0.9362
cm.df <- do.call(rbind, lapply(names(pred.rf.cls), function(nm) {
d <- as.data.frame(table(Aktual = bc.test$Class, Prediksi = pred.rf.cls[[nm]]))
d$Model <- nm
d
}))
cm.df$Model <- factor(cm.df$Model, levels = names(pred.rf.cls))
cm.df$Benar <- cm.df$Aktual == cm.df$Prediksi
ggplot(cm.df, aes(Prediksi, Aktual, fill = Benar)) +
geom_tile(colour = "white", linewidth = 1) +
geom_text(aes(label = Freq), size = 4.6, fontface = "bold") +
facet_wrap(~ Model, ncol = 3) +
scale_fill_manual(values = c("TRUE" = "#A5D6A7", "FALSE" = "#F4B6B6"), labels = c("Salah", "Benar")) +
scale_y_discrete(limits = rev(levels(bc.test$Class))) +
labs(x = "Kelas prediksi", y = "Kelas aktual", fill = "") +
theme_minimal() +
theme(legend.position = "bottom", panel.grid = element_blank())Gambar 4. Confusion matrix kesembilan model Random Forest pada data testing
Berdasarkan Gambar 4, seluruh model memprediksi 129 atau 130 dari 133 tumor jinak dengan benar, sehingga False Positive hanya 3 atau 4 dan specificity berkisar antara 0,9699 dan 0,9774. Perbedaan yang lebih jelas terdapat pada False Negative. Model dengan mtry = 2 hanya melewatkan 1 sampai 2 tumor ganas, model dengan mtry = 3 melewatkan 2 sampai 3 tumor ganas, sedangkan model dengan mtry = 5 melewatkan 4 sampai 5 tumor ganas. Akibatnya, recall model mtry = 2 (0,9718 sampai 0,9859) lebih tinggi daripada model mtry = 5 (0,9296 sampai 0,9437).
Model dengan performa terbaik adalah mtry = 2 dan num.trees = 200 dengan 130 tumor jinak dan 70 tumor ganas diprediksi benar, 3 False Positive, dan hanya 1 False Negative. Model ini memiliki accuracy 0,9804, precision 0,9589, recall 0,9859, specificity 0,9774, dan F1-Score 0,9722. Output lengkap confusionMatrix() untuk model tersebut adalah sebagai berikut.
cm.best <- confusionMatrix(data = pred.rf.cls[["mtry=2, ntree=200"]],
reference = bc.test$Class, positive = "malignant")
cm.best## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 130 1
## malignant 3 70
##
## Accuracy : 0.9804
## 95% CI : (0.9506, 0.9946)
## No Information Rate : 0.652
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.9571
##
## Mcnemar's Test P-Value : 0.6171
##
## Sensitivity : 0.9859
## Specificity : 0.9774
## Pos Pred Value : 0.9589
## Neg Pred Value : 0.9924
## Prevalence : 0.3480
## Detection Rate : 0.3431
## Detection Prevalence : 0.3578
## Balanced Accuracy : 0.9817
##
## 'Positive' Class : malignant
##
# proporsi suara malignant pada observasi yang salah diklasifikasikan oleh model terbaik
salah <- which(pred.rf.cls[["mtry=2, ntree=200"]] != bc.test$Class)
data.frame(Aktual = bc.test$Class[salah], Prediksi = pred.rf.cls[["mtry=2, ntree=200"]][salah],
Prop_malignant = round(prop.mal[["mtry=2, ntree=200"]][salah], 3))## Aktual Prediksi Prop_malignant
## 1 benign malignant 0.820
## 2 benign malignant 0.925
## 3 malignant benign 0.335
## 4 benign malignant 0.560
Pada output fungsi confusionMatrix(), baris menunjukkan kelas prediksi (Prediction) dan kolom menunjukkan kelas aktual (Reference). Accuracy model terbaik sebesar 0,9804 dengan selang kepercayaan 95% antara 0,9506 dan 0,9946, jauh di atas No Information Rate sebesar 0,652. Sensitivity dan Pos Pred Value pada output ini sama dengan recall dan precision. Dari empat observasi yang salah diklasifikasikan, satu tumor ganas diprediksi jinak dengan proporsi suara malignant 0,335, sedangkan tiga tumor jinak diprediksi ganas dengan proporsi suara 0,560, 0,820, dan 0,925. Dua tumor jinak dengan proporsi suara di atas 0,8 berarti lebih dari 80% pohon yakin bahwa tumor tersebut ganas, sehingga karakteristik sel kedua observasi ini kemungkinan memang menyerupai tumor ganas dan sulit dibedakan oleh model.
ringkasan <- data.frame(grid[, c("mtry", "num.trees")], OOB_error = oob$OOB_error,
evaluasi.rf[, c("Accuracy", "Precision", "Recall", "Specificity", "F1_Score")],
row.names = NULL)
knitr::kable(ringkasan, digits = 4, align = "c", format.args = list(decimal.mark = ","),
col.names = c("mtry", "num.trees", "OOB error", "Accuracy", "Precision", "Recall",
"Specificity", "F1-Score"),
caption = "Tabel 6. Perbandingan hasil *Random Forest* untuk setiap kombinasi *mtry* dan *num.trees*")| mtry | num.trees | OOB error | Accuracy | Precision | Recall | Specificity | F1-Score |
|---|---|---|---|---|---|---|---|
| 2 | 200 | 0,0292 | 0,9804 | 0,9589 | 0,9859 | 0,9774 | 0,9722 |
| 3 | 200 | 0,0271 | 0,9755 | 0,9583 | 0,9718 | 0,9774 | 0,9650 |
| 5 | 200 | 0,0292 | 0,9608 | 0,9437 | 0,9437 | 0,9699 | 0,9437 |
| 2 | 500 | 0,0292 | 0,9755 | 0,9459 | 0,9859 | 0,9699 | 0,9655 |
| 3 | 500 | 0,0292 | 0,9706 | 0,9577 | 0,9577 | 0,9774 | 0,9577 |
| 5 | 500 | 0,0292 | 0,9608 | 0,9437 | 0,9437 | 0,9699 | 0,9437 |
| 2 | 1000 | 0,0292 | 0,9706 | 0,9452 | 0,9718 | 0,9699 | 0,9583 |
| 3 | 1000 | 0,0271 | 0,9657 | 0,9444 | 0,9577 | 0,9699 | 0,9510 |
| 5 | 1000 | 0,0271 | 0,9559 | 0,9429 | 0,9296 | 0,9699 | 0,9362 |
# rata-rata ukuran evaluasi berdasarkan mtry dan berdasarkan num.trees
round(aggregate(cbind(Accuracy, Recall, F1_Score) ~ mtry, data = ringkasan, FUN = mean), 4)## mtry Accuracy Recall F1_Score
## 1 2 0.9755 0.9812 0.9654
## 2 3 0.9706 0.9624 0.9579
## 3 5 0.9592 0.9390 0.9412
## num.trees Accuracy Recall F1_Score
## 1 200 0.9722 0.9671 0.9603
## 2 500 0.9690 0.9624 0.9556
## 3 1000 0.9641 0.9531 0.9485
ev.df <- data.frame(mtry = factor(rep(ringkasan$mtry, 6)),
num.trees = factor(rep(ringkasan$num.trees, 6)),
Ukuran = factor(rep(c("Accuracy", "Precision", "Recall", "Specificity", "F1_Score", "OOB_error"),
each = nrow(ringkasan)),
levels = c("Accuracy", "Precision", "Recall", "Specificity", "F1_Score", "OOB_error")),
Nilai = c(ringkasan$Accuracy, ringkasan$Precision, ringkasan$Recall,
ringkasan$Specificity, ringkasan$F1_Score, ringkasan$OOB_error))
ggplot(ev.df, aes(num.trees, Nilai, colour = mtry, group = mtry)) +
geom_line(linewidth = 0.8) +
geom_point(size = 2.2) +
facet_wrap(~ Ukuran, scales = "free_y", ncol = 3) +
scale_colour_manual(values = c("2" = "#008080", "3" = "#7B5EA7", "5" = "#E07B00")) +
labs(x = "num.trees", y = NULL, colour = "mtry") +
theme_minimal() +
theme(legend.position = "bottom")Gambar 5. Perbandingan ukuran evaluasi data testing dan OOB error
Berdasarkan Tabel 6 dan Gambar 5, mtry memberikan pengaruh yang lebih jelas daripada num.trees. Pada setiap nilai num.trees, model dengan mtry = 2 selalu memiliki accuracy, recall, dan F1-Score tertinggi, sedangkan model dengan mtry = 5 selalu terendah. Rata-rata accuracy untuk mtry = 2, 3, dan 5 berturut-turut adalah 0,9755, 0,9706, dan 0,9592, sedangkan rata-rata recall-nya adalah 0,9812, 0,9624, dan 0,9390. Hal ini sesuai dengan Persamaan (2.1). Data ini memiliki beberapa prediktor yang sangat kuat, terutama Bare.nuclei dan Cell.size. Dengan mtry = 5, prediktor kuat tersebut hampir selalu ikut menjadi kandidat sehingga pohon-pohon cenderung mirip, sedangkan dengan mtry = 2 prediktor lain lebih sering mendapat kesempatan sehingga pohon lebih beragam dan hasil voting lebih baik.
Pengaruh num.trees jauh lebih kecil. Rata-rata accuracy untuk num.trees = 200, 500, dan 1000 berturut-turut adalah 0,9722, 0,9690, dan 0,9641. Penurunan ini hanya sekitar satu observasi data testing untuk setiap kenaikan num.trees, sehingga lebih tepat dipandang sebagai variasi acak daripada overfitting. Secara teori, menambah pohon tidak menyebabkan overfitting, tetapi membuat hasil voting semakin stabil (Breiman, 2001; Probst dkk., 2019). OOB error juga tidak menunjukkan pola yang konsisten terhadap num.trees. Berdasarkan data testing, model terbaik adalah mtry = 2 dan num.trees = 200. Namun, karena perbedaan antara num.trees = 200, 500, dan 1000 sangat kecil, kesimpulan yang lebih kuat adalah bahwa mtry = 2 merupakan pilihan terbaik untuk data ini, sedangkan banyaknya pohon dapat dipilih dengan mempertimbangkan kestabilan hasil dan waktu komputasi.
importance.rf <- sort(rf[["mtry=2, ntree=200"]]$variable.importance, decreasing = TRUE)
round(importance.rf, 4)## Bare.nuclei Cell.size Cell.shape Cl.thickness Bl.cromatin
## 0.0839 0.0787 0.0610 0.0245 0.0215
## Normal.nucleoli Marg.adhesion Epith.c.size Mitoses
## 0.0204 0.0193 0.0117 0.0038
# perbandingan importance untuk mtry = 2, 3, dan 5 pada num.trees = 500
imp.rf <- sapply(rf, function(m) m$variable.importance)
round(imp.rf[order(imp.rf[, "mtry=2, ntree=200"], decreasing = TRUE),
c("mtry=2, ntree=500", "mtry=3, ntree=500", "mtry=5, ntree=500")], 4)## mtry=2, ntree=500 mtry=3, ntree=500 mtry=5, ntree=500
## Bare.nuclei 0.0805 0.0991 0.1243
## Cell.size 0.0773 0.0853 0.0909
## Cell.shape 0.0630 0.0651 0.0460
## Cl.thickness 0.0267 0.0260 0.0217
## Bl.cromatin 0.0219 0.0188 0.0153
## Normal.nucleoli 0.0218 0.0148 0.0203
## Marg.adhesion 0.0191 0.0193 0.0195
## Epith.c.size 0.0132 0.0109 0.0093
## Mitoses 0.0031 0.0032 0.0030
imp.df <- data.frame(Variabel = rep(rownames(imp.rf), ncol(imp.rf)), Importance = as.vector(imp.rf),
mtry = factor(rep(grid$mtry, each = nrow(imp.rf))),
num.trees = factor(rep(grid$num.trees, each = nrow(imp.rf))))
imp.df$Variabel <- factor(imp.df$Variabel, levels = names(sort(importance.rf)))
ggplot(imp.df, aes(Importance, Variabel, colour = mtry, shape = num.trees)) +
geom_point(size = 2.8, alpha = 0.85, position = position_dodge(width = 0.6)) +
scale_colour_manual(values = c("2" = "#008080", "3" = "#7B5EA7", "5" = "#E07B00")) +
labs(x = "Permutation importance (penurunan akurasi OOB)", y = NULL, colour = "mtry", shape = "num.trees") +
theme_minimal() +
theme(legend.position = "bottom")Gambar 6. Permutation importance kesembilan model Random Forest
Berdasarkan permutation importance model terbaik, tiga variabel paling penting adalah Bare.nuclei (0,0839), Cell.size (0,0787), dan Cell.shape (0,0610). Artinya, jika nilai Bare.nuclei diacak, rata-rata akurasi OOB setiap pohon turun sekitar 8,39 poin persen. Variabel lain memiliki importance yang jauh lebih kecil, yaitu Cl.thickness (0,0245), Bl.cromatin (0,0215), Normal.nucleoli (0,0204), Marg.adhesion (0,0193), dan Epith.c.size (0,0117), sedangkan Mitoses (0,0038) hampir tidak berpengaruh. Pada Gambar 6, urutan tiga variabel teratas sama pada kesembilan model. Perbedaan yang terlihat adalah Bare.nuclei semakin dominan ketika mtry semakin besar, yaitu sekitar 0,080 sampai 0,084 pada mtry = 2 dan sekitar 0,121 sampai 0,126 pada mtry = 5. Sebaliknya, importance Cell.shape turun dari sekitar 0,061 sampai 0,063 menjadi 0,043 sampai 0,046. Hal ini memperkuat pembahasan pada subbab 4.8, yaitu mtry yang besar membuat model lebih bergantung pada satu prediktor terkuat, sedangkan mtry yang kecil membuat kontribusi prediktor lebih merata.
Random Forest adalah metode ensemble berbasis decision tree yang membangun banyak pohon dari sampel bootstrap dan hanya mempertimbangkan mtry prediktor acak pada setiap simpul, sehingga korelasi antarpohon berkurang dan variance model lebih kecil daripada Bagging. Prediksi akhir diperoleh melalui majority voting pada klasifikasi dan rata-rata pada regresi. Double Random Forest merupakan pengembangan Random Forest yang membangun setiap pohon dari seluruh data training dan melakukan bootstrap pada setiap simpul, sehingga pohon yang dihasilkan cenderung lebih besar dan cocok untuk mengatasi underfitting, tetapi membutuhkan waktu komputasi yang lebih lama.
Random Forest untuk klasifikasi diimplementasikan di RStudio menggunakan fungsi ranger() dengan argumen num.trees untuk banyaknya pohon, mtry untuk banyaknya prediktor acak, dan importance = “permutation” untuk menghitung variable importance. OOB error diperoleh dari komponen prediction.error, prediksi dilakukan dengan predict(), dan ukuran evaluasi dihitung menggunakan confusionMatrix() serta dari nilai TN, FP, FN, dan TP pada tabel aktual dan prediksi.
Berdasarkan hasil praktikum, OOB error kesembilan model sangat mirip, yaitu 0,0271 sampai 0,0292. Pada data testing, mtry memberikan pengaruh yang lebih jelas daripada num.trees, yaitu model dengan mtry = 2 selalu lebih baik daripada mtry = 3 dan 5 terutama pada recall. Model terbaik adalah mtry = 2 dan num.trees = 200 dengan accuracy 0,9804, precision 0,9589, recall 0,9859, specificity 0,9774, dan F1-Score 0,9722, serta hanya satu tumor ganas yang diprediksi jinak. Perbedaan akibat num.trees hanya sekitar satu observasi sehingga tidak bermakna. Variabel yang paling penting dalam klasifikasi adalah Bare.nuclei, Cell.size, dan Cell.shape.
Pada praktikum Machine Learning berikutnya, disarankan agar praktikan lebih teliti dalam penggunaan sintaks dan interpretasi output di RStudio, terutama dalam membaca output confusionMatrix() yang menempatkan kelas prediksi pada baris dan kelas aktual pada kolom. Jumlah pohon genap dapat menghasilkan suara seri, sehingga sebaiknya digunakan argumen seed pada predict() agar hasil prediksi dapat direproduksi. Pemilihan mtry dan num.trees sebaiknya tidak hanya didasarkan pada satu pembagian data testing, tetapi dapat menggunakan validasi silang atau OOB error dengan rentang nilai yang lebih luas. Selain itu, hasil Random Forest dapat dibandingkan dengan Double Random Forest pada data yang sama untuk melihat apakah pohon yang lebih besar dapat meningkatkan performa klasifikasi.
Breiman, L. (1996). Bagging predictors. Machine Learning, 24(2), 123–140. https://doi.org/10.1007/BF00058655
Breiman, L. (2001). Random forests. Machine Learning, 45(1), 5–32. https://doi.org/10.1023/A:1010933404324
Breiman, L., Friedman, J. H., Olshen, R. A., & Stone, C. J. (1984). Classification and regression trees. Wadsworth.
Efron, B., & Tibshirani, R. J. (1993). An introduction to the bootstrap. Chapman & Hall/CRC.
Han, S., Kim, H., & Lee, Y.-S. (2020). Double random forest. Machine Learning, 109(8), 1569–1586.
Hastie, T., Tibshirani, R., & Friedman, J. (2009). The elements of statistical learning: Data mining, inference, and prediction (2nd ed.). Springer.
James, G., Witten, D., Hastie, T., & Tibshirani, R. (2021). An introduction to statistical learning: With applications in R (2nd ed.). Springer.
Kuhn, M. (2008). Building predictive models in R using the caret package. Journal of Statistical Software, 28(5), 1–26. https://doi.org/10.18637/jss.v028.i05
Laboratorium Matematika FMIPA Universitas Bengkulu. (2026). Modul praktikum machine learning pertemuan V: Random forest dan double random forest. Universitas Bengkulu.
Leisch, F., & Dimitriadou, E. (2010). mlbench: Machine learning benchmark problems [R package]. The Comprehensive R Archive Network.
Muraina, I. O. (2022). Ideal dataset splitting ratios in machine learning algorithms: General concerns for data scientists and data analysts. Dalam Proceedings of the 7th International Mardin Artuklu Scientific Research Conference (hlm. 496–504).
Probst, P., Wright, M. N., & Boulesteix, A.-L. (2019). Hyperparameters and tuning strategies for random forest. WIREs Data Mining and Knowledge Discovery, 9(3), e1301. https://doi.org/10.1002/widm.1301
Sokolova, M., & Lapalme, G. (2009). A systematic analysis of performance measures for classification tasks. Information Processing & Management, 45(4), 427–437. https://doi.org/10.1016/j.ipm.2009.03.002
Sung, H., Ferlay, J., Siegel, R. L., Laversanne, M., Soerjomataram, I., Jemal, A., & Bray, F. (2021). Global cancer statistics 2020: GLOBOCAN estimates of incidence and mortality worldwide for 36 cancers in 185 countries. CA: A Cancer Journal for Clinicians, 71(3), 209–249. https://doi.org/10.3322/caac.21660
van Buuren, S. (2018). Flexible imputation of missing data (2nd ed.). CRC Press.
Wolberg, W. H., & Mangasarian, O. L. (1990). Multisurface method of pattern separation for medical diagnosis applied to breast cytology. Proceedings of the National Academy of Sciences, 87(23), 9193–9196. https://doi.org/10.1073/pnas.87.23.9193
Wright, M. N., & Ziegler, A. (2017). ranger: A fast implementation of random forests for high dimensional data in C++ and R. Journal of Statistical Software, 77(1), 1–17. https://doi.org/10.18637/jss.v077.i01