Perkembangan metode pembelajaran mesin (machine learning) mendorong penggunaan berbagai metode prediksi yang mampu menghasilkan model dengan tingkat akurasi yang baik. Salah satu metode yang banyak digunakan adalah ensemble learning, yaitu pendekatan yang menggabungkan beberapa model untuk memperoleh hasil prediksi yang lebih baik dibandingkan model tunggal. Salah satu metode ensemble berbasis pohon keputusan (decision tree) adalah random forest, yang membangun banyak pohon keputusan dari sampel bootstrap yang berbeda dan menggabungkan seluruh hasil prediksi pohon tersebut (Breiman, 2001).
Random forest merupakan pengembangan dari metode bagging (bootstrap aggregating) yang bertujuan mengurangi variasi (variance) pada model prediksi yang tidak stabil, seperti decision tree. Pada penerapannya, random forest menggunakan pengacakan prediktor dengan memilih sebagian variabel secara acak pada setiap pemisahan simpul. Proses tersebut dapat mengurangi korelasi antarpohon sehingga menghasilkan model yang lebih stabil dan meningkatkan kemampuan prediksi (Hastie dkk., 2009).
Selain random forest, terdapat pengembangan metode double random forest yang menerapkan pengacakan dalam proses pembentukan model untuk memperoleh hasil prediksi yang lebih baik. Pendekatan ini menarik untuk dipelajari karena memungkinkan perbandingan kemampuan pemodelan dengan metode random forest dalam menangani permasalahan klasifikasi maupun regresi. Dengan demikian, pemahaman terhadap kedua metode diperlukan untuk mengetahui karakteristik dan penerapannya dalam berbagai permasalahan prediksi. Oleh karena itu pada praktikum kali ini dibahas mengenai “random forest dan double random forest”.
Berdasarkan latar belakang, rumusan masalah pada penelitian ini, yaitu:
Bagaimana konsep random forest dan double random forest sebagai metode ensemble berbasis decision tree?
Bagaimana cara mengimplementasikan random forest untuk klasifikasi dan regresi, serta double random forest untuk klasifikasi dan regresi
Bagaimana cara mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan random forest dengan double random forest?
Berdasarkan rumusan masalah di atas, tujuan pada penelitian ini, yaitu:
Mahasiswa dapat memahami random forest dan double random forest sebagai metode ensemble berbasis decision tree.
Mahasiswa dapat mengimplementasikan random forest untuk klasifikasi dan regresi, serta double random forest untuk klasifikasi dan regresi.
Mahasiswa dapat mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan random forest dengan double random forest.
Adapun manfaat pada penelitian ini, yaitu:
Dapat memberikan informasi serta pengetahuan tentang random forest dan double random forest menggunakan program RStudio.
Mengembangkan dan menerapkan wawasan ilmu yang telah diperoleh khususnya tentang random forest dan double random forest di RStudio.
Lakukan random forest regression pada data Friedman. Bandingkan mtry = 2, 3, 5 dengan num.trees = 200, 500, 1000. Bandingkan performa data testing berdasarkan MSE, RMSE, MAE, R2, residual plot, dan variable importance. Tampilkan pula OOB MSE sebagai evaluasi internal model.
Adapun sistematika penulisan dari praktikum ini adalah:
BAB I PENDAHULUAN
Bab I terdiri dari latar belakang, rumusan masalah, batasan masalah, tujuan penelitian, manfaat penelitian, dan sistematika penulisan.
BAB II TINJAUAN PUSTAKA
Bab ini berisi tentang kajian pustaka yang terdiri dari jurnal-jurnal, buku-buku, dan informasi pendukung tentang Machine Learning pada program R.
BAB III METODE PENELITIAN
Bab ini terdiri dari analisis jenis dan sumber data, variabel penelitian, algoritma penelitian, dan diagram alur.
BAB IV HASIL DAN PEMBAHASAN
Bab ini merupakan tahapan pencapaian hasil yang diperoleh dari analisis data yang dilakukan serta penjelasan dari hasil tersebut di bagian pembahasan.
BAB V KESIMPULAN 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 metode ensemble yang membangun banyak pohon keputusan secara paralel dari sampel bootstrap yang berbeda, kemudian menggabungkan prediksi seluruh pohon (Breiman, 2001). Pada kasus regresi, prediksi akhir diperoleh dengan merata-ratakan prediksi seluruh pohon, sedangkan pada kasus klasifikasi digunakan suara terbanyak (majority vote). Metode ini merupakan pengembangan dari bagging (bootstrap aggregating) yang diperkenalkan oleh Breiman (1996). Bagging menurunkan variance dari model yang tidak stabil seperti pohon keputusan, tetapi pohon-pohon yang dihasilkan masih saling berkorelasi karena semua pohon memiliki kecenderungan memilih prediktor kuat yang sama pada pemisahan awal.
Random Forest mengatasi masalah tersebut dengan menambahkan pengacakan pada tingkat prediktor, yaitu pada setiap pemisahan simpul hanya sebagian prediktor yang dipilih secara acak sebagai kandidat (Breiman, 2001). Pengacakan ini menurunkan korelasi antarpohon sehingga variance model akhir lebih kecil dibandingkan bagging biasa (Hastie dkk., 2009). Misalkan terdapat \(B\) pohon yang masing-masing memiliki variance \(\sigma^2\) dan korelasi berpasangan \(\rho\), maka variance dari rata-rata ke-\(B\) pohon tersebut adalah:
\[ Var\left(\frac{1}{B}\sum_{b=1}^{B} T_b(x)\right) = \rho\,\sigma^2 + \frac{1-\rho}{B}\,\sigma^2 \]
Suku kedua mengecil seiring bertambahnya \(B\), sedangkan suku pertama hanya dapat diturunkan dengan memperkecil korelasi \(\rho\) antarpohon. Hal ini menjelaskan peran pemilihan prediktor secara acak pada Random Forest.
Model dasar pada Random Forest adalah pohon regresi, yaitu pohon keputusan yang memartisi ruang prediktor menjadi \(J\) wilayah terminal \(R_1, R_2, \dots, R_J\) yang saling lepas (Breiman dkk., 1984). Pada setiap wilayah, prediksi berupa konstanta, yaitu rata-rata respon pada wilayah tersebut:
\[ T(x) = \sum_{j=1}^{J} \gamma_j \, I(x \in R_j), \qquad \gamma_j = \frac{1}{n_j}\sum_{x_i \in R_j} y_i \]
dengan \(I(\cdot)\) adalah fungsi indikator dan \(n_j\) adalah jumlah observasi pada wilayah \(R_j\). Pohon dibangun dengan pemisahan biner rekursif (recursive binary splitting). Pada setiap simpul, dipilih prediktor \(j\) dan titik pemisah \(s\) yang meminimumkan jumlah kuadrat galat (sum of squared errors) pada kedua simpul anak (Hastie dkk., 2009):
\[ \min_{j,\,s}\left[\sum_{x_i \in R_1(j,s)} (y_i - \gamma_1)^2 + \sum_{x_i \in R_2(j,s)} (y_i - \gamma_2)^2\right] \]
dengan \(R_1(j,s) = \{x \mid x_j \leq s\}\) dan \(R_2(j,s) = \{x \mid x_j > s\}\) serta \(\gamma_1\) dan \(\gamma_2\) adalah rata-rata respon pada masing-masing wilayah. Berbeda dengan boosting, pohon pada Random Forest umumnya dibiarkan tumbuh dalam, tanpa pemangkasan (pruning), sehingga setiap pohon memiliki bias yang rendah tetapi variance yang tinggi, yang kemudian diturunkan melalui perataan banyak pohon (Hastie dkk., 2009). Kedalaman pohon dikendalikan secara tidak langsung oleh jumlah observasi minimum pada simpul terminal.
Bootstrap adalah metode pengambilan sampel acak berukuran \(n\) dengan pengembalian dari data berukuran \(n\) (Efron & Tibshirani, 1993). Peluang suatu observasi tidak terpilih dalam satu sampel bootstrap adalah:
\[ \left(1 - \frac{1}{n}\right)^n \xrightarrow{\,n \to \infty\,} e^{-1} \approx 0{,}368 \]
Dengan demikian, setiap sampel bootstrap memuat sekitar 63,2% observasi unik dari data training, sedangkan sekitar 36,8% observasi sisanya tidak terpilih dan disebut observasi out-of-bag (OOB) (Breiman, 2001; James dkk., 2021). Observasi OOB dapat dimanfaatkan sebagai data validasi untuk pohon yang bersangkutan sehingga galat prediksi dapat diperkirakan tanpa memisahkan data testing. Misalkan \(C_i\) adalah himpunan pohon yang tidak memuat observasi ke-\(i\) dalam sampel bootstrap-nya. Prediksi OOB untuk observasi ke-\(i\) dan OOB MSE dihitung sebagai berikut:
\[ \hat{y}_i^{OOB} = \frac{1}{|C_i|}\sum_{b \in C_i} T_b(x_i), \qquad OOB\ MSE = \frac{1}{n}\sum_{i=1}^{n}\left(y_i - \hat{y}_i^{OOB}\right)^2 \]
Breiman (2001) menunjukkan bahwa galat OOB merupakan penduga yang baik bagi galat generalisasi model.
Algoritma Random Forest Regression adalah sebagai berikut (Breiman, 2001; Hastie dkk., 2009).
Untuk \(b = 1, 2, \dots, B\):
Ambil sampel bootstrap \(D_b^*\) berukuran \(n\) dari data training.
Bangun pohon regresi \(T_b\) dari \(D_b^*\) dengan mengulangi langkah berikut pada setiap simpul hingga jumlah observasi pada simpul mencapai batas minimum (\(n.minobsinnode\)):
Pilih \(m_{try}\) prediktor secara acak dari \(p\) prediktor yang tersedia.
Pilih prediktor dan titik pemisah terbaik di antara \(m_{try}\) prediktor tersebut dengan meminimumkan jumlah kuadrat galat.
Pisahkan simpul menjadi dua simpul anak.
Keluarkan kumpulan pohon \(\{T_b\}_{b=1}^{B}\).
Prediksi untuk observasi baru \(x\) adalah rata-rata prediksi seluruh pohon:
\[ \hat{f}_{RF}(x) = \frac{1}{B}\sum_{b=1}^{B} T_b(x) \]
Pada algoritma ini, pengacakan terjadi pada dua tingkat, yaitu pada pengambilan sampel bootstrap untuk setiap pohon dan pada pemilihan kandidat prediktor untuk setiap pemisahan simpul.
Kinerja Random Forest dipengaruhi oleh beberapa parameter berikut (Breiman, 2001; Probst dkk., 2019; Wright & Ziegler, 2017).
Random Forest menyediakan ukuran kepentingan variabel (variable importance) yang berguna untuk menafsirkan model. Salah satu ukuran yang umum digunakan adalah permutation importance (Breiman, 2001). Untuk prediktor \(x_j\), kepentingan variabel dihitung dari kenaikan galat prediksi pada observasi OOB ketika nilai \(x_j\) diacak (dipermutasi) sehingga hubungannya dengan respon terputus:
\[ VI(x_j) = \frac{1}{B}\sum_{b=1}^{B}\left(MSE_b^{OOB,\,perm(j)} - MSE_b^{OOB}\right) \]
dengan \(MSE_b^{OOB}\) adalah MSE pohon ke-\(b\) pada observasi OOB dan \(MSE_b^{OOB,\,perm(j)}\) adalah MSE pohon yang sama setelah nilai \(x_j\) pada observasi OOB dipermutasi. Semakin besar nilai \(VI(x_j)\), semakin penting prediktor tersebut. Nilai yang mendekati nol atau sedikit negatif menunjukkan bahwa prediktor tidak berkontribusi terhadap ketepatan prediksi (Wright & Ziegler, 2017).
Double Random Forest (DRF) diperkenalkan oleh Han dkk. (2020) untuk memperbaiki kinerja Random Forest pada data yang cenderung mengalami underfitting. Pengamatan awal penelitian tersebut menunjukkan bahwa pada banyak himpunan data (34 dari 58), akurasi terbaik Random Forest dicapai ketika pohon dibiarkan tumbuh sepenuhnya dengan ukuran simpul minimum. Hal ini mengindikasikan bahwa pohon terbesar yang dapat dibentuk Random Forest mungkin masih belum cukup besar untuk mencapai akurasi terbaik. Penyebabnya adalah setiap pohon pada Random Forest dibangun dari sampel bootstrap yang hanya memuat sekitar 63,2% observasi unik dari data training, sehingga pohon yang terbentuk lebih kecil dibandingkan pohon yang dibangun dari seluruh data (Han dkk., 2020).
DRF mengatasi hal tersebut melalui dua perbedaan utama dibandingkan Random Forest (Han dkk., 2020).
Dengan cara ini, aturan pemisahan memiliki unsur acak yang berasal dari sampel bootstrap dan subset prediktor, sehingga pohon-pohon dalam hutan lebih beragam meskipun semuanya dibangun dari data training yang sama (Han dkk., 2020). Karena sampel bootstrap pada simpul yang mendekati simpul terminal hanya memuat sedikit observasi unik, pengambilan sampel bootstrap pada simpul hanya dilakukan selama jumlah observasi pada simpul masih cukup besar, yaitu lebih dari proporsi tertentu dari jumlah data training (Han dkk., 2020; Ganaie dkk., 2021).
Double Random Forest pertama kali dikembangkan untuk klasifikasi (Han dkk., 2020). Pada kajian regresi, algoritma yang sama dapat digunakan dengan mengganti kriteria pemisahan menjadi jumlah kuadrat galat, nilai simpul terminal menjadi rata-rata respon, dan penggabungan prediksi menjadi rata-rata seluruh pohon. Misalkan \(D\) adalah data training berukuran \(n\), \(D_d\) adalah data yang mencapai simpul \(d\) dengan jumlah observasi \(n_d\), dan \(\tau\) adalah ambang batas proporsi jumlah observasi untuk pengambilan sampel bootstrap pada simpul. Algoritma Double Random Forest adalah sebagai berikut (Han dkk., 2020; Ganaie dkk., 2021).
Untuk \(b = 1, 2, \dots, B\), bangun pohon \(T_b\) dari seluruh data training \(D\) (tanpa sampel bootstrap pada simpul akar) dengan mengulangi langkah berikut pada setiap simpul \(d\) dengan data \(D_d\):
Jika \(n_d > \tau n\), ambil sampel bootstrap \(D_d^*\) berukuran \(n_d\) dari \(D_d\). Jika tidak, gunakan \(D_d^* = D_d\).
Pilih \(m_{try}\) prediktor secara acak dari \(p\) prediktor yang tersedia.
Tentukan prediktor \(j\) dan titik pemisah \(s\) terbaik berdasarkan \(D_d^*\) dengan meminimumkan jumlah kuadrat galat:
\[ (j^*, s^*) = \arg\min_{j,\,s}\left[\sum_{x_i \in R_1^*(j,s)} (y_i - \gamma_1^*)^2 + \sum_{x_i \in R_2^*(j,s)} (y_i - \gamma_2^*)^2\right] \]
dengan \(R_1^*\) dan \(R_2^*\) adalah wilayah yang terbentuk pada \(D_d^*\), serta \(\gamma_1^*\) dan \(\gamma_2^*\) adalah rata-rata respon pada masing-masing wilayah.
Pisahkan data asli \(D_d\) (bukan \(D_d^*\)) menjadi dua simpul anak menggunakan aturan \(x_{j^*} \leq s^*\).
Ulangi langkah a sampai d hingga jumlah observasi pada simpul mencapai batas minimum (\(n.minobsinnode\)).
\[ \hat{f}_{DRF}(x) = \frac{1}{B}\sum_{b=1}^{B} T_b(x) \]
Karena setiap pohon dibangun dari seluruh data training, tidak terdapat observasi OOB pada tingkat pohon seperti pada Random Forest, sehingga estimasi galat OOB tidak tersedia secara langsung dan evaluasi kinerja dilakukan menggunakan data testing.
Perbedaan utama antara Random Forest dan Double Random Forest dirangkum pada tabel berikut (Breiman, 2001; Han dkk., 2020).
| Aspek | Random Forest | Double Random Forest |
|---|---|---|
| Data pembangun pohon | Sampel bootstrap dari data training (diambil satu kali pada simpul akar) | Seluruh data training |
| Peran sampel bootstrap | Menjadi data pembangun seluruh pohon | Hanya digunakan untuk mencari aturan pemisahan pada setiap simpul |
| Pengacakan | Sampel bootstrap pada akar dan subset prediktor pada setiap simpul | Sampel bootstrap dan subset prediktor pada setiap simpul |
| Ukuran pohon | Cenderung lebih kecil | Cenderung lebih besar |
| Estimasi galat OOB | Tersedia | Tidak tersedia secara langsung |
Kinerja model regresi pada data testing dievaluasi menggunakan beberapa ukuran berikut (Hastie dkk., 2009; James dkk., 2021). Misalkan \(y_i\) adalah nilai aktual, \(\hat{y}_i\) nilai prediksi, dan \(n\) jumlah observasi data testing.
\[ MSE = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2 \]
\[ RMSE = \sqrt{MSE} \]
\[ MAE = \frac{1}{n}\sum_{i=1}^{n}\left|y_i - \hat{y}_i\right| \]
\[ R^2 = 1 - \frac{\sum_{i=1}^{n}(y_i - \hat{y}_i)^2}{\sum_{i=1}^{n}(y_i - \bar{y})^2} \]
Nilai MSE, RMSE, dan MAE yang lebih kecil serta \(R^2\) yang lebih besar menunjukkan kinerja model yang lebih baik. Selain itu, pada Random Forest digunakan juga OOB MSE
Jenis data pada penelitian ini adalah data kuantitatif. Data kuantitatif adalah jenis data yang berbentuk angka atau bilangan dan dapat diukur atau dihitung secara langsung. Laporan ini memiliki satu batasan masalah yang menggunakan sumber data sekunder. Data sekunder adalah data yang diperoleh secara tidak langsung melalui media perantara. Data didapatkan dari program R secara langsung.
Variabel penelitian adalah karakter atau segala sesuatu yang menjadi perhatian dalam suatu penelitian. Pada batasan masalah terdapat 11 variabel. Variabel tersebut terdiri dari 1 variabel respon dan 10 variabel prediktor.
## Loading required package: ggplot2
## Loading required package: lattice
Package yang digunakan terdiri atas ranger untuk membangun model Random Forest Regression melalui fungsi ranger(), mlbench untuk membangkitkan data Friedman, dan caret untuk membagi data menjadi training dan testing melalui fungsi createDataPartition().
## 'data.frame': 200 obs. of 11 variables:
## $ x.1 : num 0.7456 0.7817 0.02 0.7761 0.0669 ...
## $ x.2 : num 0.575 0.316 0.765 0.229 0.172 ...
## $ x.3 : num 0.0289 0.9375 0.7978 0.668 0.5974 ...
## $ x.4 : num 0.72 0.185 0.534 0.553 0.755 ...
## $ x.5 : num 0.875 0.704 0.952 0.478 0.533 ...
## $ x.6 : num 0.276 0.643 0.987 0.843 0.733 ...
## $ x.7 : num 0.9332 0.4018 0.0874 0.893 0.1024 ...
## $ x.8 : num 0.60746 0.00369 0.0106 0.44639 0.83494 ...
## $ x.9 : num 0.756 0.405 0.247 0.144 0.187 ...
## $ x.10: num 0.718 0.534 0.667 0.68 0.595 ...
## $ y : num 24.35 18.05 12.02 12.1 9.91 ...
## x.1 x.2 x.3 x.4
## Min. :0.001198 Min. :0.004583 Min. :0.01021 Min. :0.00707
## 1st Qu.:0.274097 1st Qu.:0.255644 1st Qu.:0.24506 1st Qu.:0.20772
## Median :0.541847 Median :0.436813 Median :0.48965 Median :0.50295
## Mean :0.509759 Mean :0.465323 Mean :0.48570 Mean :0.48821
## 3rd Qu.:0.741416 3rd Qu.:0.651439 3rd Qu.:0.73476 3rd Qu.:0.76599
## Max. :0.993590 Max. :0.999850 Max. :0.99985 Max. :0.99761
## x.5 x.6 x.7 x.8
## Min. :0.008246 Min. :0.005504 Min. :0.001884 Min. :0.002496
## 1st Qu.:0.267523 1st Qu.:0.194431 1st Qu.:0.226788 1st Qu.:0.249826
## Median :0.522081 Median :0.446060 Median :0.491332 Median :0.480306
## Mean :0.503282 Mean :0.468544 Mean :0.503754 Mean :0.482050
## 3rd Qu.:0.751688 3rd Qu.:0.746035 3rd Qu.:0.780325 3rd Qu.:0.696675
## Max. :0.994604 Max. :0.999021 Max. :0.993044 Max. :0.995613
## x.9 x.10 y
## Min. :0.004483 Min. :0.005544 Min. : 3.082
## 1st Qu.:0.203254 1st Qu.:0.329160 1st Qu.:10.593
## Median :0.453476 Median :0.592614 Median :13.810
## Mean :0.471873 Mean :0.540708 Mean :14.270
## 3rd Qu.:0.742412 3rd Qu.:0.765353 3rd Qu.:18.063
## Max. :0.997436 Max. :0.998141 Max. :26.146
## [1] 200 11
Data dibangkitkan menggunakan fungsi mlbench.friedman1() dengan jumlah observasi sebanyak 200. Data terdiri atas sepuluh variabel prediktor, yaitu x.1 sampai x.10, dan satu variabel respon y. Seluruh prediktor berdistribusi uniform pada interval 0 sampai 1. Variabel respon dibentuk dari fungsi nonlinear yang hanya melibatkan x.1 sampai x.5 ditambah error acak, sedangkan x.6 sampai x.10 merupakan variabel noise. Berdasarkan output, variabel respon y memiliki nilai minimum 3,082, median 13,810, rata-rata 14,270, dan maksimum 26,146. Seluruh variabel bertipe numerik dan tidak ada nilai hilang.
set.seed(234)
# Pembagian data: 70% training dan 30% testing
idx.reg <- createDataPartition(reg.data$y, p = 0.70, list = FALSE)
reg.train <- reg.data[idx.reg, ]
reg.test <- reg.data[-idx.reg, ]
# Memeriksa ukuran data
dim(reg.train)## [1] 140 11
## [1] 60 11
Pembagian data dilakukan dengan proporsi 70% untuk data training dan 30% untuk data testing. Berdasarkan output, data training terdiri atas 140 observasi, sedangkan data testing terdiri atas 60 observasi. Data training digunakan untuk membangun model Random Forest, sedangkan data testing digunakan untuk mengevaluasi kemampuan model memprediksi data baru.
# Kombinasi mtry dan jumlah pohon yang akan dibandingkan
kombinasi <- expand.grid(mtry = c(2, 3, 5),
num.trees = c(200, 500, 1000))
kombinasi## mtry num.trees
## 1 2 200
## 2 3 200
## 3 5 200
## 4 2 500
## 5 3 500
## 6 5 500
## 7 2 1000
## 8 3 1000
## 9 5 1000
Random Forest membangun banyak pohon regresi dari sampel bootstrap yang berbeda, lalu merata-ratakan prediksi seluruh pohon. Dua parameter yang dibandingkan adalah mtry (jumlah prediktor yang dipertimbangkan secara acak pada setiap pemisahan simpul) dan num.trees (jumlah pohon dalam hutan). Nilai mtry yang kecil membuat pohon lebih beragam sehingga korelasi antarpohon rendah, tetapi pohon lebih sering terpaksa memilih prediktor yang kurang informatif. Nilai mtry yang besar membuat pohon lebih sering memilih prediktor yang kuat. Pada tahap ini ditetapkan tiga nilai mtry, yaitu 2, 3, dan 5, serta tiga nilai num.trees, yaitu 200, 500, dan 1000. Kombinasi keduanya menghasilkan 9 model Random Forest.
# Tempat penyimpanan hasil
hasil.model <- list()
evaluasi <- data.frame()
for (i in 1:nrow(kombinasi)) {
set.seed(234)
m <- kombinasi$mtry[i]
nt <- kombinasi$num.trees[i]
# Membentuk model
rf.reg <- ranger(
y ~ .,
data = reg.train,
num.trees = nt,
mtry = m,
min.node.size = 5,
replace = TRUE,
sample.fraction = 1,
importance = "permutation",
seed = 234)
# Menyimpan model
nama.model <- paste0("mtry_", m, "_trees_", nt)
hasil.model[[nama.model]] <- rf.reg
# Prediksi data testing
pred <- predict(rf.reg, data = reg.test)$predictions
aktual <- reg.test$y
residual <- aktual - pred
# Evaluasi data testing
MSE <- mean(residual^2)
RMSE <- sqrt(MSE)
MAE <- mean(abs(residual))
R2 <- 1 - sum(residual^2) / sum((aktual - mean(aktual))^2)
# Evaluasi OOB
OOB_MSE <- rf.reg$prediction.error
# Menyimpan hasil evaluasi
evaluasi <- rbind(
evaluasi,
data.frame(
Model = nama.model,
mtry = m,
num.trees = nt,
OOB_MSE = OOB_MSE,
MSE = MSE,
RMSE = RMSE,
MAE = MAE,
R2 = R2))
}Model dibangun menggunakan fungsi ranger() dengan formula y ~ . untuk setiap kombinasi mtry dan num.trees. Parameter lain dibuat sama pada seluruh model, yaitu min.node.size = 5 (jumlah observasi minimum pada simpul terminal), replace = TRUE dan sample.fraction = 1 (setiap pohon dibangun dari sampel bootstrap seukuran data training), serta importance = “permutation” untuk menghitung kepentingan variabel dengan metode permutasi. Fungsi set.seed(234) dan argumen seed = 234 digunakan agar hasil dapat direproduksi. Setiap model digunakan untuk memprediksi data testing, lalu dihitung lima ukuran evaluasi: OOB MSE (galat prediksi dari observasi out-of-bag pada data training), MSE, RMSE, Mean Absolute Error (MAE), dan R² pada data testing.
# Mengurutkan model berdasarkan MSE testing terkecil
evaluasi <- evaluasi[order(evaluasi$MSE), ]
print(evaluasi)## Model mtry num.trees OOB_MSE MSE RMSE MAE
## 9 mtry_5_trees_1000 5 1000 6.825960 7.192453 2.681875 2.205419
## 6 mtry_5_trees_500 5 500 6.874982 7.382590 2.717092 2.231178
## 3 mtry_5_trees_200 5 200 7.063163 7.659604 2.767599 2.272636
## 8 mtry_3_trees_1000 3 1000 7.354733 7.778006 2.788908 2.299634
## 2 mtry_3_trees_200 3 200 7.709709 7.813901 2.795336 2.298086
## 5 mtry_3_trees_500 3 500 7.442423 7.827849 2.797829 2.305786
## 1 mtry_2_trees_200 2 200 8.222172 7.870017 2.805355 2.341396
## 7 mtry_2_trees_1000 2 1000 8.055346 8.118135 2.849234 2.379363
## 4 mtry_2_trees_500 2 500 8.126738 8.177383 2.859612 2.383159
## R2
## 9 0.6999483
## 6 0.6920163
## 3 0.6804599
## 8 0.6755205
## 2 0.6740230
## 5 0.6734412
## 1 0.6716820
## 7 0.6613311
## 4 0.6588594
Berdasarkan output, MSE data testing dari kesembilan model berkisar antara 7,1925 sampai 8,1774 dan R² berkisar antara 0,6589 sampai 0,6999. Tiga model terbaik seluruhnya menggunakan mtry = 5, yaitu dengan 1000 pohon (MSE 7,1925), 500 pohon (MSE 7,3826), dan 200 pohon (MSE 7,6596). Model dengan mtry = 3 berada di tengah dengan MSE 7,7780 sampai 7,8278, sedangkan model dengan mtry = 2 menghasilkan MSE terbesar, yaitu 7,8700 sampai 8,1774, dengan model terburuk adalah mtry = 2 dan 500 pohon. Hal ini menunjukkan bahwa mtry lebih berpengaruh terhadap kinerja model dibandingkan jumlah pohon. Nilai OOB MSE menunjukkan urutan yang serupa, yaitu terkecil pada mtry = 5 dan 1000 pohon (6,8260) dan terbesar pada mtry = 2 (8,0553 sampai 8,2222). Selisih antarmodel relatif kecil sehingga dapat dipengaruhi oleh jumlah data testing yang hanya 60 observasi.
## Model mtry num.trees OOB_MSE MSE RMSE MAE R2
## 9 mtry_5_trees_1000 5 1000 6.82596 7.192453 2.681875 2.205419 0.6999483
Pemilihan model terbaik dilakukan berdasarkan nilai MSE terkecil pada data testing. Berdasarkan output, model terbaik adalah Random Forest Regression dengan mtry = 5 dan num.trees = 1000 (mtry_5_trees_1000), dengan OOB MSE 6,8260, MSE 7,1925, RMSE 2,6819, MAE 2,2054, dan R² 0,6999. Nilai R² tersebut menunjukkan bahwa model mampu menjelaskan sekitar 70% keragaman nilai y pada data testing. OOB MSE (6,8260) yang dekat dengan MSE data testing (7,1925) menunjukkan bahwa kinerja model pada data baru konsisten dengan perkiraan dari data training, sehingga tidak ada indikasi overfitting yang berarti.
pred.terbaik <- predict(rf.terbaik, data = reg.test)$predictions
hasil.prediksi <- data.frame(
Aktual = reg.test$y,
Prediksi = pred.terbaik,
Residual = reg.test$y - pred.terbaik)
head(hasil.prediksi, 10)## Aktual Prediksi Residual
## 1 10.232309 12.54560 -2.313287
## 2 11.845301 10.28195 1.563355
## 3 10.335689 12.78220 -2.446509
## 4 16.727262 13.72361 3.003650
## 5 25.077119 20.44406 4.633058
## 6 15.446886 14.44204 1.004842
## 7 15.642915 12.79740 2.845519
## 8 7.110835 12.57824 -5.467401
## 9 13.351277 15.52667 -2.175391
## 10 12.871960 14.88958 -2.017625
Tabel ini membandingkan nilai aktual, prediksi, dan residual dari model terbaik pada 10 observasi pertama data testing. Secara umum, prediksi mengikuti pola nilai aktual, tetapi galat yang terjadi cukup bervariasi, dengan residual berkisar dari -5,47 sampai 4,63 pada 10 observasi ini. Model kurang akurat pada nilai ekstrem. Pada observasi ke-5 (aktual 25,08), prediksi hanya 20,44 sehingga nilai tinggi diprediksi terlalu rendah (residual 4,63). Sebaliknya, pada observasi ke-8 (aktual 7,11), prediksi sebesar 12,58 sehingga nilai rendah diprediksi terlalu tinggi (residual -5,47). Pola ini menunjukkan kecenderungan prediksi tertarik ke arah nilai tengah.
mtry.val <- c(2, 3, 5)
tree.val <- sort(unique(kombinasi$num.trees))
# Matriks MSE: baris = jumlah pohon, kolom = mtry
mse.mat <- sapply(mtry.val, function(m) {
evaluasi$MSE[match(paste0("mtry_", m, "_trees_", tree.val),
evaluasi$Model)]
})
matplot(
x = tree.val,
y = mse.mat,
type = "b",
pch = 1:3,
col = 1:3,
lty = 1,
xlab = "Number of Trees",
ylab = "MSE Testing",
main = "Perbandingan MSE Random Forest")
legend("topright",
legend = paste("mtry =", mtry.val),
col = 1:3, pch = 1:3, lty = 1)Grafik garis membandingkan MSE data testing dari kesembilan model, dengan sumbu-x berupa jumlah pohon dan setiap garis mewakili satu nilai mtry. Garis mtry = 5 menurun secara konsisten dari 7,6596 (200 pohon) ke 7,3826 (500 pohon) dan 7,1925 (1000 pohon), sehingga penambahan pohon pada mtry ini terus memperbaiki kinerja model. Garis mtry = 3 relatif datar di sekitar 7,78 sampai 7,83, sedangkan garis mtry = 2 naik dari 7,8700 (200 pohon) menjadi 8,1774 (500 pohon) dan 8,1181 (1000 pohon), sehingga penambahan pohon tidak memberikan perbaikan. Garis mtry = 5 berada paling bawah pada setiap jumlah pohon, sehingga mtry = 5 menghasilkan MSE terkecil secara konsisten. Kenaikan MSE pada mtry = 2 saat jumlah pohon bertambah tidak mengindikasikan bahwa lebih banyak pohon memperburuk model, karena penambahan pohon pada Random Forest secara umum hanya menstabilkan prediksi. Perbedaan tersebut lebih mungkin berasal dari variasi acak pada data testing yang kecil.
plot(hasil.prediksi$Aktual,
hasil.prediksi$Prediksi,
pch = 19,
xlab = "Nilai Aktual",
ylab = "Nilai Prediksi",
main = paste("Aktual vs Prediksi -", nama.terbaik))
abline(a = 0, b = 1, lty = 2, lwd = 2)Scatter plot membandingkan nilai aktual dengan nilai prediksi model terbaik, dengan garis putus-putus sebagai garis ideal (prediksi = aktual). Titik-titik menyebar mengikuti garis tersebut dan membentuk pola linear positif, yang menunjukkan bahwa model mampu menangkap hubungan antara prediktor dan respon. Namun, sebaran titik di sekitar garis cukup lebar sehingga sesuai dengan R² sekitar 0,70. Pada nilai aktual yang rendah (di bawah 10), hampir seluruh titik berada di atas garis sehingga prediksi terlalu tinggi (misalnya nilai aktual sekitar 4 diprediksi sekitar 7). Pada nilai aktual yang tinggi (di atas 20), titik berada di bawah garis sehingga prediksi terlalu rendah, dengan prediksi yang tidak melampaui sekitar 21 meskipun nilai aktual mencapai 25. Pola ini menunjukkan bahwa prediksi Random Forest cenderung tertarik ke arah nilai tengah karena prediksi merupakan rata-rata dari banyak pohon, sehingga nilai-nilai ekstrem kurang mampu ditangkap.
plot(
hasil.prediksi$Prediksi,
hasil.prediksi$Residual,
pch = 19,
xlab = "Nilai Prediksi",
ylab = "Residual",
main = paste("Residual Plot -", nama.terbaik))
abline(h = 0, lty = 2, lwd = 2)Residual plot menampilkan residual (aktual dikurangi prediksi) terhadap nilai prediksi, dengan garis putus-putus pada residual nol. Residual tersebar di atas dan di bawah garis nol dengan rentang sekitar -6 sampai 5, serta tidak terlihat pola melengkung atau pola corong yang jelas, sehingga tidak ada indikasi pelanggaran yang serius terhadap kelinearan maupun ragam yang konstan. Namun, terdapat kecenderungan sistematis pada ujung-ujung sebaran: pada nilai prediksi yang tinggi (di atas sekitar 18), sebagian besar residual bernilai positif sehingga nilai aktual lebih besar daripada prediksi, sedangkan pada nilai prediksi yang rendah (sekitar 10 sampai 13), terdapat cukup banyak residual negatif yang besar sehingga nilai aktual lebih kecil daripada prediksi. Hal ini sejalan dengan temuan pada scatter plot bahwa model cenderung meremehkan nilai tinggi dan melebihkan nilai rendah.
## x.4 x.1 x.2 x.3 x.5 x.6
## 12.931369548 9.387495698 3.821133252 1.825483548 0.972018449 0.099989113
## x.10 x.8 x.9 x.7
## 0.097567088 -0.009637107 -0.080222740 -0.143027440
barplot(
importance.terbaik,
las = 2,
main = paste("Variable Importance -", nama.terbaik),
ylab = "Permutation Importance")Variable importance dengan metode permutasi menunjukkan seberapa besar kenaikan error model ketika nilai suatu prediktor diacak. Berdasarkan output, variabel x.4 memiliki kepentingan terbesar (12,93), diikuti x.1 (9,39), x.2 (3,82), x.3 (1,83), dan x.5 (0,97). Variabel x.6 (0,10) dan x.10 (0,10) bernilai mendekati nol, sedangkan x.8 (-0,01), x.9 (-0,08), dan x.7 (-0,14) bernilai sedikit negatif. Nilai negatif yang kecil berarti pengacakan variabel tersebut tidak menurunkan kinerja model sehingga variabel tersebut dapat dianggap tidak berpengaruh. Hasil ini sesuai dengan struktur data Friedman, karena hanya x.1 sampai x.5 yang benar-benar membentuk variabel respon, sedangkan x.6 sampai x.10 adalah variabel noise. Model Random Forest dengan demikian berhasil membedakan variabel yang berpengaruh dari variabel noise.
importance.semua <- data.frame()
for (i in 1:length(hasil.model)) {
model <- hasil.model[[i]]
importance.semua <- rbind(
importance.semua,
data.frame(
Model = names(hasil.model)[i],
Variabel = names(model$variable.importance),
Importance = as.numeric(model$variable.importance)))}
print(importance.semua)## Model Variabel Importance
## 1 mtry_2_trees_200 x.1 7.056402842
## 2 mtry_2_trees_200 x.2 4.103479945
## 3 mtry_2_trees_200 x.3 2.630648488
## 4 mtry_2_trees_200 x.4 10.300689487
## 5 mtry_2_trees_200 x.5 1.497595283
## 6 mtry_2_trees_200 x.6 0.243901550
## 7 mtry_2_trees_200 x.7 -0.168485417
## 8 mtry_2_trees_200 x.8 0.016045797
## 9 mtry_2_trees_200 x.9 -0.226556931
## 10 mtry_2_trees_200 x.10 0.238938308
## 11 mtry_3_trees_200 x.1 7.961441583
## 12 mtry_3_trees_200 x.2 3.457770950
## 13 mtry_3_trees_200 x.3 1.799914151
## 14 mtry_3_trees_200 x.4 10.936625336
## 15 mtry_3_trees_200 x.5 0.801224075
## 16 mtry_3_trees_200 x.6 -0.142122996
## 17 mtry_3_trees_200 x.7 -0.291552239
## 18 mtry_3_trees_200 x.8 0.055217155
## 19 mtry_3_trees_200 x.9 -0.115099299
## 20 mtry_3_trees_200 x.10 0.120569021
## 21 mtry_5_trees_200 x.1 9.434048063
## 22 mtry_5_trees_200 x.2 3.255413296
## 23 mtry_5_trees_200 x.3 1.663861471
## 24 mtry_5_trees_200 x.4 12.328727376
## 25 mtry_5_trees_200 x.5 0.882374511
## 26 mtry_5_trees_200 x.6 0.223386219
## 27 mtry_5_trees_200 x.7 -0.124867790
## 28 mtry_5_trees_200 x.8 0.112827321
## 29 mtry_5_trees_200 x.9 -0.102671921
## 30 mtry_5_trees_200 x.10 -0.102819997
## 31 mtry_2_trees_500 x.1 7.281171058
## 32 mtry_2_trees_500 x.2 3.978849876
## 33 mtry_2_trees_500 x.3 2.703048247
## 34 mtry_2_trees_500 x.4 9.589757633
## 35 mtry_2_trees_500 x.5 1.315871833
## 36 mtry_2_trees_500 x.6 0.087094427
## 37 mtry_2_trees_500 x.7 -0.225811480
## 38 mtry_2_trees_500 x.8 -0.080118231
## 39 mtry_2_trees_500 x.9 0.035186132
## 40 mtry_2_trees_500 x.10 0.288219756
## 41 mtry_3_trees_500 x.1 8.171805449
## 42 mtry_3_trees_500 x.2 3.556322153
## 43 mtry_3_trees_500 x.3 2.233852516
## 44 mtry_3_trees_500 x.4 11.013712844
## 45 mtry_3_trees_500 x.5 1.012069618
## 46 mtry_3_trees_500 x.6 -0.132610434
## 47 mtry_3_trees_500 x.7 -0.166863098
## 48 mtry_3_trees_500 x.8 -0.101421845
## 49 mtry_3_trees_500 x.9 -0.036803366
## 50 mtry_3_trees_500 x.10 0.153295624
## 51 mtry_5_trees_500 x.1 9.211047217
## 52 mtry_5_trees_500 x.2 3.436769442
## 53 mtry_5_trees_500 x.3 1.740485054
## 54 mtry_5_trees_500 x.4 12.742513925
## 55 mtry_5_trees_500 x.5 0.882063578
## 56 mtry_5_trees_500 x.6 0.143975996
## 57 mtry_5_trees_500 x.7 -0.164765218
## 58 mtry_5_trees_500 x.8 -0.033853940
## 59 mtry_5_trees_500 x.9 -0.076846602
## 60 mtry_5_trees_500 x.10 0.032523216
## 61 mtry_2_trees_1000 x.1 7.327525783
## 62 mtry_2_trees_1000 x.2 3.826732204
## 63 mtry_2_trees_1000 x.3 2.576426409
## 64 mtry_2_trees_1000 x.4 9.464248061
## 65 mtry_2_trees_1000 x.5 1.228531540
## 66 mtry_2_trees_1000 x.6 -0.050256445
## 67 mtry_2_trees_1000 x.7 -0.247929894
## 68 mtry_2_trees_1000 x.8 -0.191476230
## 69 mtry_2_trees_1000 x.9 0.026979395
## 70 mtry_2_trees_1000 x.10 0.059092035
## 71 mtry_3_trees_1000 x.1 8.183378670
## 72 mtry_3_trees_1000 x.2 3.577988543
## 73 mtry_3_trees_1000 x.3 2.283376053
## 74 mtry_3_trees_1000 x.4 10.981225121
## 75 mtry_3_trees_1000 x.5 1.093136982
## 76 mtry_3_trees_1000 x.6 -0.125417507
## 77 mtry_3_trees_1000 x.7 -0.148611169
## 78 mtry_3_trees_1000 x.8 -0.109432850
## 79 mtry_3_trees_1000 x.9 -0.126854670
## 80 mtry_3_trees_1000 x.10 0.078835375
## 81 mtry_5_trees_1000 x.1 9.387495698
## 82 mtry_5_trees_1000 x.2 3.821133252
## 83 mtry_5_trees_1000 x.3 1.825483548
## 84 mtry_5_trees_1000 x.4 12.931369548
## 85 mtry_5_trees_1000 x.5 0.972018449
## 86 mtry_5_trees_1000 x.6 0.099989113
## 87 mtry_5_trees_1000 x.7 -0.143027440
## 88 mtry_5_trees_1000 x.8 -0.009637107
## 89 mtry_5_trees_1000 x.9 -0.080222740
## 90 mtry_5_trees_1000 x.10 0.097567088
Tabel ini menampilkan nilai permutation importance setiap variabel pada kesembilan model. Pada seluruh model, urutan lima variabel teratas selalu sama, yaitu x.4, x.1, x.2, x.3, dan x.5, sedangkan nilai x.6 sampai x.10 selalu berada di sekitar nol (berkisar antara -0,29 sampai 0,29). Hal ini menunjukkan bahwa kesimpulan mengenai variabel penting stabil terhadap perubahan mtry dan jumlah pohon. Perbedaan antarmodel terutama terlihat pada besarnya nilai. Nilai x.4 dan x.1 meningkat seiring bertambahnya mtry, yaitu x.4 sekitar 9,5 sampai 10,3 pada mtry = 2, sekitar 11,0 pada mtry = 3, dan sekitar 12,3 sampai 12,9 pada mtry = 5, sedangkan x.1 meningkat dari sekitar 7,1 sampai 7,3 menjadi 9,2 sampai 9,4. Sebaliknya, nilai x.3 menurun dari sekitar 2,6 pada mtry = 2 menjadi sekitar 1,7 sampai 1,8 pada mtry = 5. Hal ini terjadi karena pada mtry yang besar, variabel yang kuat lebih sering terpilih pada pemisahan simpul sehingga perannya semakin dominan, sedangkan pada mtry yang kecil, variabel yang lebih lemah mendapat kesempatan lebih besar untuk dipilih. Perubahan jumlah pohon hanya sedikit memengaruhi nilai importance.
Random forest dan double random forest merupakan metode ensemble learning berbasis decision tree yang menggabungkan beberapa pohon keputusan untuk menghasilkan prediksi yang lebih baik. Random forest membangun banyak pohon menggunakan sampel bootstrap dan pemilihan subset variabel secara acak, sedangkan double random forest mengembangkan pendekatan tersebut dengan menggabungkan dua proses random forest untuk meningkatkan kemampuan pemodelan.
Implementasi random forest untuk klasifikasi dilakukan dengan memprediksi kelas berdasarkan hasil penggabungan prediksi seluruh pohon, sedangkan regresi menggunakan rata-rata hasil prediksi pohon. Sementara itu, double random forest untuk klasifikasi dan regresi dilakukan melalui dua tahapan pemodelan sesuai mekanisme metode tersebut. Implementasi kedua metode memerlukan penentuan parameter serta pembagian data menjadi data latih dan data uji agar model dapat dibangun dan dievaluasi.
Evaluasi performa model dilakukan menggunakan confusion matrix, akurasi, presisi, recall, dan F1-score untuk klasifikasi, serta MSE, RMSE, MAE, dan R² untuk regresi. Selain itu, Out-of-Bag (OOB) error digunakan sebagai evaluasi internal model dengan memanfaatkan observasi yang tidak terpilih dalam proses bootstrap. Perbandingan random forest dan double random forest dilakukan berdasarkan hasil evaluasi tersebut untuk mengetahui metode yang memberikan performa prediksi lebih baik.
Model random forest regression dengan kombinasi \(mtry = 2;\ 3;\ 5\) dan \(num.trees = 200;\ 500;\ 1000\) menghasilkan kinerja prediksi yang cukup baik pada data testing, dengan nilai \(R^2\) berkisar antara 0,6589 sampai 0,6999. Model dengan \(mtry = 5\) dan 1000 pohon memberikan MSE terkecil sebesar 7,1925, sedangkan model dengan \(mtry = 2\) dan 500 pohon memiliki MSE terbesar sebesar 8,1774. Selisih MSE antara keduanya sekitar 13,7%, dan seluruh model dengan \(mtry = 5\) selalu lebih baik daripada model dengan \(mtry\) lainnya, sehingga \(mtry\) lebih berpengaruh terhadap kinerja model dibandingkan jumlah pohon. Selain itu, model cenderung kurang akurat pada nilai ekstrem karena prediksi ditarik ke arah nilai tengah, yaitu nilai tinggi diprediksi terlalu rendah dan nilai rendah diprediksi terlalu tinggi. Analisis variable importance menunjukkan bahwa \(x4\), \(x1\), \(x2\), \(x3\), dan \(x5\) merupakan variabel yang paling berpengaruh pada seluruh model, sedangkan variabel lainnya memiliki pengaruh mendekati nol, sesuai dengan struktur data Friedman. Dengan demikian, random forest regression dengan \(mtry = 5\) dan 1000 pohon dipilih sebagai model terbaik karena memberikan kinerja prediksi yang paling baik pada data testing.
Ketika menjalankan suatu fungsi pada program R diharapkan untuk teliti saat mengoperasikannya. Penulisan syntax sangat perlu diperhatikan karena apabila terdapat kesalahan penulisan akan membuat program error. Selain itu, perlu untuk memperhatikan tatacara penulisan yang sesuai dengan KBBI, sehingga dapat menghasilkan laporan yang baik.
Breiman, L., Friedman, J. H., Olshen, R. A., & Stone, C. J. (1984). Classification and Regression Trees. Wadsworth.
Fransiska, H. (2026). Modul Praktikum Machine Learning. Bengkulu: Laboratorium Statistika FMIPA Universitas Bengkulu.
Freund, Y., & Schapire, R. E. (1997). A decision-theoretic generalization of on-line learning and an application to boosting. Journal of Computer and System Sciences, 55(1), 119–139.
Friedman, J. H. (2001). Greedy function approximation: A gradient boosting machine. The Annals of Statistics, 29(5), 1189–1232.
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.
Ridgeway, G. (2007). Generalized Boosted Models: A Guide to the gbm Package. R package vignette.
Schapire, R. E. (1990). The strength of weak learnability. Machine Learning, 5(2), 197–227.