Klasifikasi merupakan salah satu tugas utama dalam machine learning, yaitu memprediksi kategori suatu pengamatan berdasarkan sekumpulan variabel prediktor. Decision tree sering digunakan untuk tugas ini karena strukturnya mudah dipahami dan diinterpretasikan. Namun, satu pohon keputusan cenderung tidak stabil karena perubahan kecil pada data latih dapat menghasilkan struktur pohon yang berbeda, sehingga kemampuan generalisasinya dapat menurun. Salah satu pendekatan untuk mengatasi hal tersebut adalah ensemble learning, yaitu menggabungkan prediksi dari banyak model dasar sehingga diperoleh model gabungan dengan kemampuan prediksi yang lebih baik (Fransiska, 2026).
Random Forest (RF) yang diperkenalkan oleh Breiman (2001) merupakan salah satu metode ensemble berbasis decision tree yang banyak digunakan. RF merupakan pengembangan dari bagging, yaitu membangun banyak pohon dari sampel bootstrap dan, pada setiap node, hanya memilih sejumlah kecil prediktor secara acak sebagai kandidat pemisahan. Pengacakan prediktor ini mengurangi korelasi antarpohon, sehingga agregasi prediksi dapat menurunkan variance tanpa harus memangkas setiap pohon secara agresif. Pada kasus klasifikasi, prediksi akhir diperoleh melalui majority voting dari seluruh pohon (Fransiska, 2026).
Karena setiap pohon dibangun dari sampel bootstrap, sebagian observasi tidak terambil pada pohon tertentu. Observasi tersebut disebut Out-of-Bag (OOB) dan dapat dimanfaatkan untuk menghitung OOB error sebagai ukuran evaluasi internal model tanpa memerlukan data terpisah (Fransiska, 2026). Probst et al. (2019) juga menyatakan bahwa observasi OOB dapat digunakan dalam pemilihan parameter model. Di samping itu, kinerja model klasifikasi dievaluasi dengan membandingkan kelas aktual dan kelas prediksi melalui confusion matrix, yang dari sana dihitung ukuran seperti accuracy, precision, recall, specificity, dan F1-score (Fransiska, 2026).
Kinerja RF juga dipengaruhi oleh pengaturan parameter yang harus ditentukan oleh pengguna, dan nilai optimalnya bergantung pada data yang digunakan (Probst et al., 2019). Jumlah pohon, misalnya, perlu ditetapkan pengguna, dan masih perlu dipertimbangkan apakah jumlah tersebut sebaiknya sebesar mungkin yang layak secara komputasi atau jumlah yang lebih kecil sudah memadai (Probst & Boulesteix, 2018). Oleh karena itu, selain memahami cara kerja RF, diperlukan pula kemampuan membandingkan kinerja model pada beberapa pengaturan parameter. Pada perangkat lunak R, RF dapat diimplementasikan menggunakan package ranger, yaitu implementasi RF yang cepat (Wright & Ziegler, 2017) dan menghitung OOB error secara otomatis (Fransiska, 2026).
Berdasarkan uraian tersebut, praktikum ini dilakukan agar mahasiswa dapat memahami Random Forest Classification sebagai metode ensemble berbasis decision tree, mengimplementasikannya menggunakan program R, serta mengevaluasi performa model, memahami OOB error, dan membandingkan kinerja model Random Forest Classification.
Berdasarkan latar belakang, rumusan masalah yang dapat disimpulkan yaitu sebagai berikut:
Berdasarkan rumusan masalah, tujuan yang dapat disimpulkan yaitu sebagai berikut:
Adapun manfaat pada penelitian ini yaitu:
Bagi penulis:
Bagi pembaca:
Adapun batasan masalah pada penelitian ini yaitu, lakukan analisis
Random Forest secara lengkap mulai dari persiapan data,
pembentukan model, prediksi, evaluasi, visualisasi, dan interpretasi.
Gunakan set.seed(234) agar hasil dapat direproduksi.
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.
Adapun sistematika penulisan dari praktikum ini adalah:
BAB I PENDAHULUAN
Bab ini merupakan bab yang memuat latar belakang, rumusan masalah, tujuan dan manfaat, batasan masalah dan sistematika penulisan.
BAB II TINJAUAN PUSTAKA
Bab ini merupakan bab yang memuat pengertian dan teori yang diperlukan untuk rancangan penelitian pada bab-bab berikutnya.
BAB III METODE PENELITIAN
Bab ini merupakan bab yang memuat jenis dan sumber data, variabel penelitian, dan analisis data yang diperlukan untuk rancangan penelitian pada bab-bab berikutnya.
BAB IV HASIL DAN PEMBAHASAN
Bab ini merupakan bab yang memuat hasil dan pembahasan yang telah dilakukan pada program, kemudian diinterpretasikan untuk rancangan penelitian pada bab-bab berikutnya.
BAB V KESIMPULAN DAN SARAN
Bab ini merupakan bab yang memuat kesimpulan dan saran yang telah dilakukan.
DAFTAR PUSTAKA
Machine learning merupakan pendekatan komputasi yang memungkinkan sistem mempelajari pola dari data untuk menghasilkan prediksi atau keputusan tanpa harus diprogram secara eksplisit untuk setiap aturan. Dalam penelitian statistik dan ilmu data, machine learning digunakan untuk memodelkan hubungan antara variabel prediktor dan variabel respons, terutama ketika hubungan tersebut bersifat nonlinear atau melibatkan interaksi antarkomponen data. Penggunaan machine learning berkembang dalam berbagai bidang karena algoritmanya dapat digunakan untuk klasifikasi, regresi, pendeteksian pola, dan pengambilan keputusan berbasis data (Mienye & Sun, 2022; Zhang et al., 2022).
Secara umum, machine learning dapat dibedakan menjadi pembelajaran terawasi (supervised learning), pembelajaran tidak terawasi (unsupervised learning), dan pembelajaran semi-terawasi. Penelitian yang menggunakan Ran dom Forest umumnya termasuk dalam pembelajaran terawasi karena model dibangun berdasarkan data pelatihan yang memiliki variabel respons atau label. Pada pembelajaran terawasi, model mempelajari fungsi pemetaan antara himpunan prediktor dan respons. Untuk permasalahan klasifikasi, respons berbentuk kategori, sedangkan pada regresi respons berbentuk numerik kontinu.
Tujuan utama pemodelan machine learning bukan hanya memperoleh kecocokan yang baik terhadap data pelatihan, tetapi juga menghasilkan kemampuan generalisasi yang baik pada data baru. Model yang terlalu kompleks dapat mengalami overfitting, yaitu ketika model sangat sesuai dengan data pelatihan tetapi kurang mampu memprediksi data pengujian. Sebaliknya, model yang terlalu sederhana dapat mengalami underfitting. Oleh karena itu, pemilihan algoritma, pengaturan hiperparameter, pembagian data, dan validasi model merupakan bagian penting dalam penelitian machine learning (Zhao et al., 2025).
Random Forest (RF) merupakan metode ensemble yang menggabungkan banyak pohon keputusan untuk menghasilkan satu prediksi. Setiap pohon dibentuk melalui proses pengacakan data dan pengacakan variabel prediktor. Hasil klasifikasi diperoleh melalui suara mayoritas, sedangkan hasil regresi diperoleh melalui rata-rata prediksi seluruh pohon. Khairunnisa et al. (2024) menjelaskan bahwa RF menggunakan dua proses randomisasi utama, yaitu pengambilan sampel data dengan pengembalian (bootstrap sampling) dan pemilihan subset prediktor secara acak pada setiap simpul.
Misalkan terdapat sebanyak \(B\) pohon keputusan. Untuk masalah regresi, prediksi RF dapat dituliskan sebagai:
\[\hat{f}_{RF}(x) = \frac{1}{B}\sum_{b=1}^{B} T_b(x),\]
di mana \(T_b(x)\) merupakan prediksi pohon ke-\(b\) terhadap observasi dengan vektor prediktor \(x\). Untuk masalah klasifikasi, RF memilih kelas dengan frekuensi suara terbanyak dari seluruh pohon.
Pembentukan RF dimulai dengan mengambil beberapa sampel bootstrap dari data pelatihan. Setiap sampel digunakan untuk membentuk satu pohon keputusan. Pada setiap simpul, model tidak mengevaluasi seluruh variabel prediktor, tetapi hanya mengevaluasi sebagian prediktor yang dipilih secara acak. Prosedur ini mengurangi kemiripan antar pohon. Ketika pohon-pohon yang relatif berbeda digabungkan, kesalahan prediksi agregat dapat berkurang.
RF juga dapat menggunakan observasi yang tidak masuk ke dalam sampel bootstrap sebagai data out-of-bag (OOB). Data OOB dapat digunakan untuk memperoleh estimasi kinerja internal tanpa membentuk data validasi terpisah. Meskipun demikian, penggunaan OOB atau random cross-validation tidak otomatis menghasilkan evaluasi yang sahih untuk data spasial. RF memiliki beberapa kelebihan. Metode ini dapat memodelkan hubungan nonlinear, menangani interaksi antarvariabel, menggunakan prediktor numerik maupun kategorik, dan relatif tahan terhadap pencilan. RF juga tidak mensyaratkan bentuk hubungan tertentu antara prediktor dan respons. Karakteristik tersebut menjadikan RF sesuai untuk data lingkungan dan sosial yang kompleks.
Namun, RF memiliki keterbatasan. Prediksi RF sulit dijelaskan secara langsung karena dihasilkan dari banyak pohon keputusan. Model juga dapat mengalami underfitting ketika struktur pohon tidak cukup besar untuk merepresentasikan pola data. Selain itu, RF standar tidak secara eksplisit memodelkan ketergantungan spasial. Apabila variabel spasial atau strategi validasi tidak dirancang dengan tepat, model dapat menghasilkan estimasi kinerja yang terlalu tinggi atau peta prediksi yang tidak stabil.
Kinerja Classification dievaluasi dengan membandingkan kelas aktual dan kelas hasil prediksi pada data testing. Hasil perbandingan tersebut disajikan dalam confusion matrix (Fransiska, 2026), yaitu tabel yang memuat jumlah prediksi benar dan salah untuk setiap kelas.
| Prediksi Positif | Prediksi Negatif | |
|---|---|---|
| Aktual Positif | True Positive (TP) | False Negative (FN) |
| Aktual Negatif | False Positive (FP) | True Negative (TN) |
Keterangan: TP adalah pengamatan positif yang diprediksi positif, TN adalah pengamatan negatif yang diprediksi negatif, FP adalah pengamatan negatif yang salah diprediksi positif, dan FN adalah pengamatan positif yang salah diprediksi negatif. Berdasarkan confusion matrix, beberapa ukuran evaluasi yang digunakan adalah sebagai berikut.
\[ Accuracy=\frac{TP+TN}{TP+TN+FP+FN} \]
\[ Precision=\frac{TP}{TP+FP} \]
\[ Recall=\frac{TP}{TP+FN} \]
\[ Specificity=\frac{TN}{TN+FP} \]
\[ F1\text{-}Score=2\times\frac{Precision\times Recall}{Precision+Recall} \]
Accuracy mudah diinterpretasikan, tetapi dapat menyesatkan apabila proporsi kelas tidak seimbang, sehingga perlu dilengkapi dengan sensitivity, specificity, precision, dan F1-Score. Pada kasus medis seperti diagnosis kanker, nilai sensitivity menjadi perhatian utama karena kesalahan false negative (kasus positif yang terlewat) umumnya memiliki konsekuensi yang lebih serius daripada false positive.
Selain itu, kemampuan model membedakan kedua kelas pada berbagai ambang klasifikasi dapat dinilai menggunakan kurva Receiver Operating Characteristic (ROC). Kurva ini menggambarkan hubungan antara true positive rate (sensitivity) pada sumbu vertikal dan false positive rate (\(1-Specificity\)) pada sumbu horizontal (Fawcett, 2006). Ringkasan numeriknya adalah Area Under the Curve (AUC), yaitu luas di bawah kurva ROC. Nilai AUC berkisar antara 0 hingga 1; semakin mendekati 1, semakin baik kemampuan model membedakan kelas, sedangkan nilai 0,5 setara dengan tebakan acak (Fawcett, 2006).
Kinerja model regresi dapat dievaluasi menggunakan Mean Squared Error (MSE), yaitu rata-rata kuadrat selisih antara nilai aktual dan nilai prediksi. MSE dirumuskan sebagai berikut (Fransiska, 2026).
\[ MSE=\frac{1}{n}\sum_{i=1}^{n}(y_i-\hat{y}_i)^2 \] dengan \(n\) merupakan jumlah pengamatan, \(y_i\) merupakan nilai aktual, dan \(\hat{y}_i\) merupakan nilai prediksi. Nilai MSE yang lebih kecil menunjukkan tingkat kesalahan prediksi yang lebih rendah pada data evaluasi.
Jenis data yang digunakan dalam praktikum ini adalah data kuantitatif
dan data kategorik. Data kuantitatif berupa karakteristik sel yang
digunakan sebagai variabel prediktor, sedangkan data kategorik berupa
kondisi kanker payudara yang terdiri atas dua kelas, yaitu jinak
(benign) dan ganas (malignant). Sumber data
yang digunakan merupakan data sekunder dari dataset
BreastCancer dalam package mlbench
pada perangkat lunak R. Dataset ini memuat informasi karakteristik sel
untuk mengklasifikasikan kondisi kanker payudara. Data tersebut
digunakan dalam pemodelan Random Forest Classification.
Variabel penelitian terdiri atas variabel respons dan variabel
prediktor. Variabel respons yang digunakan adalah Class, yang
menunjukkan kondisi kanker payudara dalam kategori jinak
(benign) dan ganas (malignant). Sementara itu,
variabel prediktor meliputi Cl.thickness,
Cell.size, Cell.shape,
Marg.adhesion, Epith.c.size,
Bare.nuclei, Bl.cromatin,
Normal.nucleoli, dan Mitoses, yang
menggambarkan karakteristik sel untuk mengklasifikasikan kondisi kanker
payudara menggunakan metode Random Forest Classification.
Langkah-langkah analisis yang dilakukan dalam praktikum Random Forest Classification adalah sebagai berikut.
ranger,
mlbench, caret, dan tidyverse,
kemudian memuat dataset BreastCancer ke dalam
R.Id karena hanya berfungsi sebagai
pengenal, menghapus observasi yang mengandung missing value
menggunakan fungsi na.omit(), dan memastikan variabel
Class bertipe factor.createDataPartition() dengan
set.seed(234).mtry = 2, 3, 5 dan
num.trees = 200, 500, 1000,
dengan model acuan mtry = 3 dan
num.trees = 500 sesuai sintaks asisten.ranger() pada data training
dengan parameter lain dibuat tetap, dan menampilkan OOB error
masing-masing model.malignant sebagai kelas positif.mtry
dan num.trees terhadap kinerja model, dan
menginterpretasikan hasilnya.Tahap pertama adalah memanggil library yang dibutuhkan dan
memuat dataset BreastCancer dari package
mlbench. Package ranger digunakan
untuk membangun model Random Forest karena cepat dan
menyediakan estimasi Out-of-Bag (OOB) secara otomatis.
library(ranger)
library(mlbench)
library(caret)
library(tidyverse) # dimuat terakhir agar fungsi dplyr tidak tertutup package lain
# fungsi bantu: format angka dengan koma desimal untuk teks interpretasi
koma <- function(x, d = 4) format(round(x, d), decimal.mark = ",", nsmall = 0)
# A1. Memuat data
data(BreastCancer, package = "mlbench")
bc <- BreastCancer
dim(bc)## [1] 699 11
## '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
## Length :699 1 :145 1 :384 1 :353 1 :407
## N.unique :645 5 :130 10 : 67 2 : 59 2 : 58
## N.blank : 0 3 :108 3 : 52 10 : 58 3 : 58
## Min.nchar: 5 4 : 80 2 : 45 3 : 56 10 : 55
## Max.nchar: 8 10 : 69 4 : 40 4 : 44 4 : 33
## 2 : 50 5 : 30 5 : 34 8 : 25
## (Other):117 (Other): 81 (Other): 95 (Other): 63
## Epith.c.size Bare.nuclei Bl.cromatin Normal.nucleoli Mitoses
## 2 :386 1 :402 2 :166 1 :443 1 :579
## 3 : 72 10 :132 3 :165 10 : 61 2 : 35
## 4 : 48 2 : 30 1 :152 3 : 44 3 : 33
## 1 : 47 5 : 30 7 : 73 2 : 36 10 : 14
## 6 : 41 3 : 28 4 : 40 8 : 24 4 : 12
## 5 : 39 (Other): 61 5 : 34 6 : 22 7 : 9
## (Other): 66 NAs : 16 (Other): 69 (Other): 69 (Other): 17
## Class
## benign :458
## malignant:241
##
##
##
##
##
Dataset memiliki 699 observasi dan 11 variabel. Variabel
Id adalah nomor identitas pasien, Class adalah
variabel respons dengan dua kategori (benign dan
malignant), dan sembilan variabel lainnya
(Cl.thickness sampai Mitoses) adalah
karakteristik sel yang menjadi prediktor. Seluruh prediktor tersimpan
bertipe factor dengan 10 level (skor 1 sampai 10), yang
dapat langsung diproses oleh ranger. Ringkasan
summary() juga memperlihatkan adanya NA pada
Bare.nuclei.
Variabel Id dihapus karena hanya berfungsi sebagai
pengenal dan tidak membawa informasi untuk klasifikasi. Selanjutnya
dilakukan pengecekan missing value.
# A2. Persiapan data
bc$Id <- NULL
tabel_missing <- data.frame(
Variabel = names(bc),
Jumlah_NA = as.vector(colSums(is.na(bc))),
Persen_NA = round(as.vector(colMeans(is.na(bc))) * 100, 2)
)
knitr::kable(tabel_missing, align = "c", caption = "Jumlah dan persentase missing value per variabel")| Variabel | Jumlah_NA | Persen_NA |
|---|---|---|
| Cl.thickness | 0 | 0.00 |
| Cell.size | 0 | 0.00 |
| Cell.shape | 0 | 0.00 |
| Marg.adhesion | 0 | 0.00 |
| Epith.c.size | 0 | 0.00 |
| Bare.nuclei | 16 | 2.29 |
| Bl.cromatin | 0 | 0.00 |
| Normal.nucleoli | 0 | 0.00 |
| Mitoses | 0 | 0.00 |
| Class | 0 | 0.00 |
n_awal <- nrow(bc)
n_na <- sum(!complete.cases(bc))
# Menghapus observasi yang mengandung missing value
bc <- na.omit(bc)
# Memastikan respons berupa factor
bc$Class <- droplevels(as.factor(bc$Class))
cat("Jumlah observasi sebelum na.omit :", n_awal, "\n")## Jumlah observasi sebelum na.omit : 699
## Jumlah observasi dihapus : 16
## Jumlah observasi setelah na.omit : 683
Missing value hanya ditemukan pada Bare.nuclei,
sebanyak 16 observasi (2,29%). Karena proporsinya sangat kecil,
observasi tersebut dihapus menggunakan na.omit() sehingga
tersisa 683 observasi lengkap. Cara ini sederhana dan tidak memasukkan
nilai buatan, dengan konsekuensi ukuran sampel berkurang sedikit.
## [1] "benign" "malignant"
tabel_class <- data.frame(
Kelas = names(table(bc$Class)),
Jumlah = as.vector(table(bc$Class)),
Persen = round(as.vector(prop.table(table(bc$Class))) * 100, 2)
)
knitr::kable(tabel_class, align = "c", caption = "Distribusi kelas variabel Class")| Kelas | Jumlah | Persen |
|---|---|---|
| benign | 444 | 65.01 |
| malignant | 239 | 34.99 |
ggplot(tabel_class, aes(x = Kelas, y = Jumlah, fill = Kelas)) +
geom_col(color = "black", width = 0.6) +
geom_text(aes(label = Jumlah), vjust = -0.4) +
scale_fill_manual(values = c("#008080", "#E69F00")) +
labs(title = "Distribusi Kondisi Kanker Payudara", x = "Class", y = "Jumlah") +
theme_minimal() +
theme(legend.position = "none")Dari 683 observasi, sebanyak 444 observasi (65,01%) termasuk kelas
jinak (benign) dan 239 observasi (34,99%) termasuk kelas
ganas (malignant). Kelas jinak lebih banyak, tetapi
perbedaannya tidak terlalu ekstrem sehingga data masih tergolong cukup
seimbang untuk dimodelkan tanpa teknik penyeimbangan.
Data dibagi menjadi data training (70%) dan data
testing (30%) menggunakan createDataPartition()
dengan set.seed(234). Fungsi ini melakukan pengambilan
sampel acak terstratifikasi berdasarkan Class, sehingga
proporsi kelas tetap terjaga.
# A3. Membagi data training dan testing
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
perbandingan <- rbind(
Data_Asli = round(prop.table(table(bc$Class)) * 100, 2),
Data_Training = round(prop.table(table(bc.train$Class)) * 100, 2),
Data_Testing = round(prop.table(table(bc.test$Class)) * 100, 2)
)
knitr::kable(perbandingan, align = "c", caption = "Persentase kelas Class (%) pada tiap himpunan data")| benign | malignant | |
|---|---|---|
| Data_Asli | 65.01 | 34.99 |
| Data_Training | 64.93 | 35.07 |
| Data_Testing | 65.20 | 34.80 |
##
## benign malignant
## 311 168
##
## benign malignant
## 133 71
Data terbagi menjadi 479 observasi training dan 204 observasi testing (sekitar 70:30). Proporsi kelas pada data training dan testing hampir sama dengan data asli, sehingga kedua himpunan data mewakili kondisi data sebenarnya.
Sebelum membandingkan berbagai pengaturan, terlebih dahulu dibangun
satu model acuan sesuai sintaks asisten praktikum, yaitu
num.trees = 500 dan mtry = 3. Arti pengaturan
yang digunakan adalah sebagai berikut.
num.trees: jumlah pohon yang dibentuk pada
forest.mtry: jumlah prediktor yang dipilih secara acak sebagai
kandidat pemisahan pada setiap node. Pengacakan ini membuat
pohon tidak saling berkorelasi.min.node.size = 1: pohon dibiarkan tumbuh penuh
(fully grown) sehingga memiliki variance tinggi namun
bias rendah, yang kemudian diturunkan melalui agregasi.replace = TRUE dan sample.fraction = 1:
setiap pohon dibangun dari sampel bootstrap (pengambilan dengan
pengembalian) berukuran sama dengan data training.importance = "permutation": kepentingan variabel
dihitung dengan mengacak nilai suatu variabel pada data OOB dan melihat
penurunan akurasi.# A4. Membentuk Random Forest (model acuan)
set.seed(234)
rf.cls <- ranger(
Class ~ ., data = bc.train,
num.trees = 500,
mtry = 3,
min.node.size = 1,
replace = TRUE,
sample.fraction = 1,
importance = "permutation",
seed = 234
)
rf.cls## Ranger result
##
## Call:
## ranger(Class ~ ., data = bc.train, num.trees = 500, mtry = 3, 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 %
## [1] 0.02922756
## predicted
## true benign malignant
## benign 303 8
## malignant 6 162
## [1] benign benign malignant malignant benign benign
## Levels: benign malignant
Keluaran rf.cls menunjukkan model berjenis klasifikasi
dengan 500 pohon, ukuran sampel 479, 9 variabel prediktor, dan
mtry sebesar 3. Estimasi OOB prediction error
sebesar 0,0292 (2,92%), yang berarti akurasi OOB sebesar 97,08%. Nilai
ini dihitung hanya dari pohon-pohon yang tidak memakai observasi
bersangkutan saat dibentuk (sekitar 36,8% observasi tidak terambil pada
satu sampel bootstrap), sehingga berfungsi sebagai evaluasi
internal tanpa memerlukan data terpisah. Confusion matrix OOB
menunjukkan 14 observasi training yang salah diklasifikasikan
pada prediksi OOB.
mtry dan
num.treesSesuai ketentuan praktikum, dibandingkan tiga nilai mtry
(2, 3, dan 5) dengan tiga nilai num.trees (200, 500, dan
1000), sehingga terbentuk sembilan model. Seluruh pengaturan lain dan
seed dibuat sama agar perbedaan hasil hanya berasal dari
mtry dan num.trees.
grid_rf <- expand.grid(mtry = c(2, 3, 5), num.trees = c(200, 500, 1000))
grid_rf$Model <- paste0("mtry=", grid_rf$mtry, " | trees=", grid_rf$num.trees)
model_rf <- vector("list", nrow(grid_rf))
names(model_rf) <- grid_rf$Model
for (i in seq_len(nrow(grid_rf))) {
set.seed(234)
model_rf[[i]] <- ranger(
Class ~ ., data = bc.train,
num.trees = grid_rf$num.trees[i],
mtry = grid_rf$mtry[i],
min.node.size = 1,
replace = TRUE,
sample.fraction = 1,
importance = "permutation",
seed = 234
)
}
tabel_oob <- data.frame(
mtry = grid_rf$mtry,
num.trees = grid_rf$num.trees,
OOB_Error = sapply(model_rf, function(m) m$prediction.error),
OOB_Accuracy = 1 - sapply(model_rf, function(m) m$prediction.error)
)
rownames(tabel_oob) <- NULL
knitr::kable(tabel_oob, digits = 4, align = "c",
caption = "OOB prediction error untuk setiap kombinasi mtry dan num.trees")| mtry | num.trees | OOB_Error | OOB_Accuracy |
|---|---|---|---|
| 2 | 200 | 0.0292 | 0.9708 |
| 3 | 200 | 0.0271 | 0.9729 |
| 5 | 200 | 0.0292 | 0.9708 |
| 2 | 500 | 0.0292 | 0.9708 |
| 3 | 500 | 0.0292 | 0.9708 |
| 5 | 500 | 0.0292 | 0.9708 |
| 2 | 1000 | 0.0292 | 0.9708 |
| 3 | 1000 | 0.0271 | 0.9729 |
| 5 | 1000 | 0.0271 | 0.9729 |
Estimasi OOB error kesembilan model berkisar antara 2,71%
dan 2,92%, atau setara dengan akurasi OOB 97,08% sampai 97,29%. OOB
error terkecil diperoleh pada mtry = 3 dan
num.trees = 200.
Setiap model digunakan untuk memprediksi kelas pada data
testing. Kelas malignant ditetapkan sebagai kelas
positif karena kesalahan yang paling berbahaya secara klinis adalah
gagal mendeteksi sel ganas.
# A6. Prediksi data testing untuk setiap model
pred_rf <- lapply(model_rf, function(m) {
factor(predict(m, data = bc.test)$predictions, levels = levels(bc.test$Class))
})
# Perbandingan aktual dan prediksi (10 observasi pertama, model acuan)
head(data.frame(Aktual = bc.test$Class, Prediksi = pred_rf[["mtry=3 | trees=500"]]), 10)## Aktual Prediksi
## 1 benign malignant
## 2 benign benign
## 3 benign benign
## 4 benign benign
## 5 benign benign
## 6 malignant malignant
## 7 benign benign
## 8 benign benign
## 9 benign benign
## 10 malignant malignant
# A7. Ukuran evaluasi (mengikuti sintaks asisten praktikum)
hitung_metrik <- function(pred, aktual) {
tab <- table(Aktual = aktual, Prediksi = pred)
TN <- tab["benign", "benign"]
FP <- tab["benign", "malignant"]
FN <- tab["malignant", "benign"]
TP <- tab["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)
data.frame(TN = TN, FP = FP, FN = FN, TP = TP,
Accuracy = Accuracy, Precision = Precision, Recall = Recall,
Specificity = Specificity, F1_Score = F1)
}
tabel_rf <- do.call(rbind, lapply(seq_along(pred_rf), function(i) {
cbind(grid_rf[i, c("mtry", "num.trees")], hitung_metrik(pred_rf[[i]], bc.test$Class))
}))
tabel_rf$OOB_Error <- tabel_oob$OOB_Error
rownames(tabel_rf) <- NULL
knitr::kable(tabel_rf[, c("mtry", "num.trees", "TN", "FP", "FN", "TP")], align = "c",
caption = "Ringkasan confusion matrix pada data testing (kelas positif = malignant)")| mtry | num.trees | TN | FP | FN | TP |
|---|---|---|---|---|---|
| 2 | 200 | 130 | 3 | 1 | 70 |
| 3 | 200 | 130 | 3 | 3 | 68 |
| 5 | 200 | 129 | 4 | 4 | 67 |
| 2 | 500 | 129 | 4 | 1 | 70 |
| 3 | 500 | 130 | 3 | 3 | 68 |
| 5 | 500 | 129 | 4 | 4 | 67 |
| 2 | 1000 | 129 | 4 | 2 | 69 |
| 3 | 1000 | 129 | 4 | 3 | 68 |
| 5 | 1000 | 129 | 4 | 5 | 66 |
Tabel di atas memuat jumlah prediksi benar dan salah pada data
testing (204 observasi) untuk setiap model. Jumlah kesalahan
prediksi (false positive ditambah false negative)
berkisar antara 4 dan 9 observasi. False negative (sel ganas
yang diprediksi jinak) berkisar antara 1 dan 5 observasi, dan false
positive (sel jinak yang diprediksi ganas) antara 3 dan 4
observasi. Berikut confusion matrix lengkap untuk model terbaik
(mtry = 2, num.trees = 200), yaitu model
dengan akurasi tertinggi pada data testing (dengan
recall, OOB error, dan jumlah pohon sebagai
pertimbangan berikutnya bila akurasi sama).
cm.rf <- confusionMatrix(
data = pred_rf[[nama_best]],
reference = bc.test$Class,
positive = "malignant"
)
cm.rf## 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
##
Dari confusion matrix, dihitung lima metrik evaluasi, yaitu
Accuracy, Precision, Recall,
Specificity, dan F1-Score (perhitungannya terdapat
pada fungsi hitung_metrik). Hasil pada data
testing untuk seluruh model disajikan berikut.
knitr::kable(
tabel_rf[, c("mtry", "num.trees", "Accuracy", "Precision", "Recall", "Specificity", "F1_Score", "OOB_Error")],
digits = 4, align = "c",
caption = "Metrik evaluasi model Random Forest pada data testing dan OOB error"
)| mtry | num.trees | Accuracy | Precision | Recall | Specificity | F1_Score | OOB_Error |
|---|---|---|---|---|---|---|---|
| 2 | 200 | 0.9804 | 0.9589 | 0.9859 | 0.9774 | 0.9722 | 0.0292 |
| 3 | 200 | 0.9706 | 0.9577 | 0.9577 | 0.9774 | 0.9577 | 0.0271 |
| 5 | 200 | 0.9608 | 0.9437 | 0.9437 | 0.9699 | 0.9437 | 0.0292 |
| 2 | 500 | 0.9755 | 0.9459 | 0.9859 | 0.9699 | 0.9655 | 0.0292 |
| 3 | 500 | 0.9706 | 0.9577 | 0.9577 | 0.9774 | 0.9577 | 0.0292 |
| 5 | 500 | 0.9608 | 0.9437 | 0.9437 | 0.9699 | 0.9437 | 0.0292 |
| 2 | 1000 | 0.9706 | 0.9452 | 0.9718 | 0.9699 | 0.9583 | 0.0292 |
| 3 | 1000 | 0.9657 | 0.9444 | 0.9577 | 0.9699 | 0.9510 | 0.0271 |
| 5 | 1000 | 0.9559 | 0.9429 | 0.9296 | 0.9699 | 0.9362 | 0.0271 |
metrik_long <- tabel_rf %>%
dplyr::select(mtry, num.trees, Accuracy, Precision, Recall, Specificity, F1_Score) %>%
pivot_longer(c(Accuracy, Precision, Recall, Specificity, F1_Score),
names_to = "Metrik", values_to = "Nilai")
ggplot(metrik_long, aes(x = factor(num.trees), y = Nilai, color = factor(mtry), group = mtry)) +
geom_line(linewidth = 0.9) +
geom_point(size = 2) +
facet_wrap(~ Metrik, scales = "free_y") +
labs(title = "Metrik Evaluasi Random Forest pada Data Testing",
x = "Jumlah pohon (num.trees)", y = "Nilai metrik", color = "mtry") +
theme_minimal()Pada data testing, akurasi kesembilan model berkisar antara
95,59% dan 98,04%. Recall (kemampuan mendeteksi sel ganas)
berkisar antara 92,96% dan 98,59%, specificity (kemampuan
mengenali sel jinak) antara 96,99% dan 97,74%, precision antara
94,29% dan 95,89%, serta F1-Score antara 0,9362 dan 0,9722.
Untuk model acuan (mtry = 3, num.trees = 500),
akurasi sebesar 97,06%, recall 95,77%, specificity
97,74%, precision 95,77%, dan F1-Score 0,9577. Seluruh
metrik berada pada tingkat yang tinggi, yang menunjukkan bahwa
Random Forest mampu membedakan kondisi jinak dan ganas dengan
sangat baik.
Berdasarkan akurasi pada data testing, model terbaik adalah model dengan mtry = 2 dan num.trees = 200, dengan akurasi 98,04%, recall 98,59%, specificity 97,74%, precision 95,89%, dan F1-Score 0,9722.
OOB error dapat dibandingkan dengan error pada data testing untuk melihat apakah estimasi internal model sejalan dengan kinerja pada data baru.
oob_test <- tabel_rf %>%
transmute(mtry = factor(mtry), num.trees = num.trees,
Error_Testing = 1 - Accuracy, OOB_Error = OOB_Error) %>%
pivot_longer(c(Error_Testing, OOB_Error), names_to = "Ukuran", values_to = "Error")
ggplot(oob_test, aes(x = factor(num.trees), y = Error, color = mtry, group = mtry)) +
geom_line(linewidth = 0.9) +
geom_point(size = 2) +
facet_wrap(~ Ukuran) +
labs(title = "OOB Error dan Error Data Testing",
x = "Jumlah pohon (num.trees)", y = "Error klasifikasi", color = "mtry") +
theme_minimal()Rata-rata akurasi OOB (97,15%) dibandingkan rata-rata akurasi data testing (96,79%) berbeda sekitar 0,36 poin persentase. Selisih yang kecil ini menunjukkan bahwa OOB error merupakan estimasi yang baik terhadap kinerja pada data baru, sehingga dapat diandalkan sebagai evaluasi internal tanpa data testing terpisah. OOB error dihitung dari data training yang tidak terambil pada tiap pohon, sedangkan error pada data testing dihitung dari data yang sama sekali tidak dipakai membangun model. Karena data testing hanya terdiri dari 204 observasi, selisih satu observasi saja mengubah error sekitar 0,49 poin persentase, sehingga fluktuasi kecil antarmodel wajar terjadi.
Variable importance pada ranger dengan
importance = "permutation" menunjukkan seberapa besar
akurasi OOB menurun ketika nilai suatu variabel diacak. Semakin besar
nilainya, semakin penting variabel tersebut bagi prediksi. Nilai
mendekati nol berarti variabel hampir tidak berkontribusi.
# A8. Variable Importance model terbaik
importance.rf <- sort(model_rf[[nama_best]]$variable.importance, decreasing = TRUE)
importance.rf## Bare.nuclei Cell.size Cell.shape Cl.thickness Bl.cromatin
## 0.083924522 0.078718154 0.060967868 0.024489152 0.021478062
## Normal.nucleoli Marg.adhesion Epith.c.size Mitoses
## 0.020446839 0.019251533 0.011737675 0.003751688
par(mar = c(8, 4, 3, 1))
barplot(importance.rf, las = 2,
main = paste0("Variable Importance - Random Forest (", nama_best, ")"),
ylab = "Permutation Importance")imp_df <- do.call(rbind, lapply(seq_along(model_rf), function(i) {
v <- model_rf[[i]]$variable.importance
data.frame(Variabel = names(v), Importance = as.numeric(v),
mtry = grid_rf$mtry[i], num.trees = grid_rf$num.trees[i])
}))
ggplot(imp_df, aes(x = reorder(Variabel, Importance), y = Importance)) +
geom_col(fill = "cadetblue") +
coord_flip() +
facet_grid(mtry ~ num.trees, labeller = label_both) +
labs(title = "Variable Importance pada Seluruh Kombinasi mtry dan num.trees",
x = "", y = "Permutation Importance") +
theme_minimal()| mtry | num.trees | Peringkat_1 | Peringkat_2 | Peringkat_3 |
|---|---|---|---|---|
| 2 | 200 | Bare.nuclei | Cell.size | Cell.shape |
| 3 | 200 | Bare.nuclei | Cell.size | Cell.shape |
| 5 | 200 | Bare.nuclei | Cell.size | Cell.shape |
| 2 | 500 | Bare.nuclei | Cell.size | Cell.shape |
| 3 | 500 | Bare.nuclei | Cell.size | Cell.shape |
| 5 | 500 | Bare.nuclei | Cell.size | Cell.shape |
| 2 | 1000 | Bare.nuclei | Cell.size | Cell.shape |
| 3 | 1000 | Bare.nuclei | Cell.size | Cell.shape |
| 5 | 1000 | Bare.nuclei | Cell.size | Cell.shape |
Pada model terbaik, variabel dengan kepentingan tertinggi adalah
Bare.nuclei (0,0839), diikuti Cell.size (0,0787) dan Cell.shape (0,061).
Ketiganya menyumbang 68,85% dari total nilai kepentingan positif,
sedangkan variabel dengan kontribusi terkecil adalah Mitoses (0,0038).
Variabel paling penting konsisten sama, yaitu Bare.nuclei, pada seluruh
sembilan kombinasi mtry dan num.trees, sehingga kesimpulan tentang
variabel yang paling berpengaruh tidak bergantung pada pengaturan model.
Jika nilai mtry diperbesar, variabel yang kuat lebih sering
terpilih sebagai kandidat pemisahan sehingga pola kepentingannya dapat
bergeser, sedangkan penambahan jumlah pohon umumnya membuat estimasi
kepentingan lebih stabil.
mtry dan num.trees terhadap
Kinerja Modelrata_mtry <- tapply(tabel_rf$Accuracy, tabel_rf$mtry, mean)
rata_tree <- tapply(tabel_rf$Accuracy, tabel_rf$num.trees, mean)
oob_mtry <- tapply(tabel_rf$OOB_Error, tabel_rf$mtry, mean)
oob_tree <- tapply(tabel_rf$OOB_Error, tabel_rf$num.trees, mean)
tabel_pengaruh <- rbind(
data.frame(Faktor = "mtry", Nilai = names(rata_mtry),
Rata_Akurasi_Testing = as.numeric(rata_mtry), Rata_OOB_Error = as.numeric(oob_mtry)),
data.frame(Faktor = "num.trees", Nilai = names(rata_tree),
Rata_Akurasi_Testing = as.numeric(rata_tree), Rata_OOB_Error = as.numeric(oob_tree))
)
knitr::kable(tabel_pengaruh, digits = 4, align = "c",
caption = "Rata-rata akurasi testing dan OOB error menurut mtry dan num.trees")| Faktor | Nilai | Rata_Akurasi_Testing | Rata_OOB_Error |
|---|---|---|---|
| mtry | 2 | 0.9755 | 0.0292 |
| mtry | 3 | 0.9690 | 0.0278 |
| mtry | 5 | 0.9592 | 0.0285 |
| num.trees | 200 | 0.9706 | 0.0285 |
| num.trees | 500 | 0.9690 | 0.0292 |
| num.trees | 1000 | 0.9641 | 0.0278 |
Pengaruh mtry. Rata-rata akurasi data
testing untuk mtry = 2, 3, dan
5 berturut-turut sebesar 97,55%, 96,9%, dan 95,92%,
sedangkan rata-rata OOB error-nya sebesar 2,92%, 2,78%, dan
2,85%. Nilai mtry yang memberikan rata-rata akurasi tertinggi adalah
mtry = 2, sehingga jumlah prediktor kandidat memengaruhi kinerja model
pada data ini. Secara konsep, mtry yang kecil membuat pohon
lebih beragam dan kurang berkorelasi tetapi setiap pohon dapat menjadi
lebih lemah karena kandidat pemisahnya terbatas, sedangkan
mtry yang besar membuat pohon lebih kuat tetapi lebih mirip
satu sama lain (pada mtry sama dengan jumlah seluruh
prediktor, Random Forest menjadi setara dengan
Bagging).
Pengaruh num.trees. Rata-rata akurasi data
testing untuk num.trees = 200, 500,
dan 1000 berturut-turut sebesar 97,06%, 96,9%, dan 96,41%,
dengan rata-rata OOB error sebesar 2,85%, 2,92%, dan 2,78%.
Perbedaan yang sangat kecil ini menunjukkan bahwa kinerja model sudah
stabil pada 200 pohon, dan penambahan pohon hingga 500 atau 1000 tidak
memberikan peningkatan yang berarti. Hal ini sejalan dengan sifat
Random Forest: karena agregasi banyak pohon menurunkan
variance, kesalahan cenderung menurun lalu mendatar seiring
bertambahnya pohon, dan penambahan pohon tidak menyebabkan
overfitting, melainkan hanya menambah waktu komputasi.
Secara keseluruhan, selisih akurasi antara model terbaik dan terendah pada data testing hanya 2,45 poin persentase, sehingga seluruh pengaturan yang dibandingkan menghasilkan kinerja yang cukup berbeda. Karena data pengujian relatif kecil, perbedaan antarmodel perlu ditafsirkan dengan hati-hati, dan pengaturan yang lebih sederhana (misalnya jumlah pohon lebih sedikit) dapat dipilih apabila kinerjanya setara.
Random Forest merupakan metode ensemble berbasis
decision tree yang membangun banyak pohon dari sampel
bootstrap dan memilih sejumlah prediktor (mtry)
secara acak pada setiap node, kemudian menggabungkan prediksi
seluruh pohon melalui majority voting. Pengacakan prediktor
menurunkan korelasi antarpohon sehingga variance model
berkurang. Berdasarkan hasil penerapan Random Forest
Classification pada dataset BreastCancer, dapat
disimpulkan sebagai berikut:
Class, dengan 65,01% kelas jinak dan 34,99% kelas ganas.
Missing value hanya ditemukan pada Bare.nuclei
sebanyak 16 observasi dan ditangani dengan na.omit(),
sehingga tersisa 683 observasi.set.seed(234). Dibangun
sembilan model Random Forest dengan ranger untuk
kombinasi mtry = 2, 3, 5 dan num.trees = 200,
500, 1000.mtry = 3, num.trees = 500)
sebesar 2,92%. Hasil ini menunjukkan kesalahan klasifikasi yang rendah
dan estimasi OOB sejalan dengan kinerja pada data testing.mtry dan
num.trees terhadap kinerja pada data ini cukup
terlihat.mtry, min.node.size, dan
num.trees melalui tuning yang sistematis (misalnya
dengan caret::train atau tuneRanger).mice) dapat dicoba sebagai pembanding agar seluruh
observasi tetap digunakan.Breiman, L. (2001). Random forests. Machine Learning, 45(1), 5–32. https://doi.org/10.1023/A:1010933404324
Fawcett, T. (2006). An introduction to ROC analysis. Pattern Recognition Letters, 27(8), 861–874. https://doi.org/10.1016/j.patrec.2005.10.010
Fransiska, H. (2026). Modul Praktikum Machine Learning. Universitas Bengkulu.
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). https://doi.org/10.15294/sji.v11i1.48721
Mienye, I. D., & Sun, Y. (2022). A survey of ensemble learning: Concepts, algorithms, applications, and prospects. IEEE Access, 10. https://doi.org/10.1109/ACCESS.2022.3207287
Probst, P., & Boulesteix, A.-L. (2018). To tune or not to tune the number of trees in random forest. Journal of Machine Learning Research, 18(181), 1–18.
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
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
Zhang, Y., Liu, J., & Shen, W. (2022). A review of ensemble learning algorithms used in remote sensing applications. Applied Sciences, 12(17). https://doi.org/10.3390/app12178654
Zhao, H., Liu, W., Wang, Y., & Wu, L. (2025). Comparative analysis of algorithmic approaches in ensemble learning: Bagging vs. boosting. Scientific Reports, 15(1). https://doi.org/10.1038/s41598-025-15971-0