Pohon keputusan (decision tree) merupakan metode prediksi yang membagi data secara bertahap berdasarkan variabel prediktor sehingga mudah diinterpretasikan. Namun, satu pohon yang tumbuh penuh memiliki variance tinggi, artinya hasilnya mudah berubah apabila data latih berubah sedikit saja sehingga rentan mengalami overfitting (Fransiska, 2026). Untuk mengatasi hal tersebut dikembangkan metode ensambel, yaitu menggabungkan prediksi banyak pohon agar hasil akhir lebih stabil dan akurat.
Random Forest (RF) adalah algoritma ensemble
learning berbasis pohon yang membangun banyak pohon keputusan dan
menggabungkan prediksinya untuk meningkatkan akurasi serta mengurangi
overfitting. RF merupakan pengembangan dari Bagging
(Bootstrap Aggregating). Seperti Bagging, setiap pohon dibangun
dari sampel bootstrap, tetapi RF menambahkan pengacakan pada
pemilihan prediktor di setiap node, yaitu hanya sejumlah
mtry prediktor yang dipertimbangkan sebagai kandidat
pemisah. Pengacakan ini menurunkan korelasi antar-pohon sehingga manfaat
agregasi menjadi lebih besar (Fransiska, 2026). Pada kasus regresi,
prediksi akhir diperoleh dengan merata-ratakan prediksi seluruh pohon.
Pengembangan lanjutan dari RF adalah Double Random Forest (DRF)
yang membangun setiap pohon dari seluruh data latih, sedangkan
bootstrap hanya digunakan sementara pada setiap node
untuk mencari aturan pemisah, sehingga pohon yang dihasilkan cenderung
lebih besar (Fransiska, 2026).
Penerapan Random Forest Regression telah banyak dilakukan di Indonesia. Da Costa dan Rozi (2025) menerapkannya untuk memprediksi efisiensi tidur dan melaporkan bahwa model RF dengan 100 pohon memberikan kinerja lebih baik pada data uji dibandingkan Linear Regression dan Support Vector Regression berdasarkan MAE, MSE, RMSE, dan R². Fadillah dan Fauzan (2024) membandingkan Linear Regression dan Random Forest Regression untuk prediksi batas kredit dengan pendekatan optimasi hyperparameter dan melaporkan RF menghasilkan RMSE dan MAE terendah. Khamidah dkk. (2024) memodelkan Indeks Pembangunan Manusia pada data yang mengandung multikolinearitas dan melaporkan bahwa model Random Forest dan XGBoost lebih baik dibandingkan model lain pada data empiris, sedangkan model Regression Tree tunggal tidak direkomendasikan. Keunggulan penggabungan banyak pohon juga ditunjukkan oleh Masita dkk. (2025) yang melaporkan bahwa Random Forest Regression menghasilkan RMSE yang lebih kecil dibandingkan Decision Tree Regression pada prediksi kepesertaan Jaminan Kesehatan Nasional.
Kinerja RF dipengaruhi oleh parameter-parameter yang ditetapkan,
terutama jumlah prediktor kandidat pada setiap node
(mtry) dan jumlah pohon (num.trees). Oleh
karena itu, pada praktikum ini dilakukan Random Forest
Regression pada data Friedman menggunakan package
ranger dengan membandingkan mtry sebesar 2, 3,
dan 5 serta num.trees sebesar 200, 500, dan 1000. Kinerja
setiap kombinasi dievaluasi pada data testing menggunakan MSE, RMSE,
MAE, dan R², dilengkapi dengan residual plot, variable
importance, serta OOB MSE sebagai evaluasi internal model.
Pembahasan Double Random Forest pada laporan ini dibatasi pada
tinjauan teori dan perbandingannya dengan RF.
Berdasarkan latar belakang, rumusan masalah yang dapat disimpulkan adalah sebagai berikut:
Berdasarkan rumusan masalah tersebut, tujuan yang dapat disimpulkan adalah sebagai berikut:
Random Forest adalah algoritma ensemble learning berbasis pohon yang membangun banyak pohon keputusan dan menggabungkan prediksinya untuk meningkatkan akurasi serta mengurangi overfitting. RF merupakan pengembangan dari Bagging yang menggunakan kumpulan pohon keputusan sebagai model dasar dan dirancang untuk mengurangi variance serta meningkatkan kemampuan generalisasi (Fransiska, 2026).
Seperti Bagging, RF membentuk banyak pohon dari proses resampling dan menggabungkan hasil prediksinya. Perbedaannya, RF menambahkan pengacakan pada pemilihan prediktor di setiap node, sehingga pohon-pohon dalam forest tidak hanya dibangun dari sampel yang berbeda, tetapi juga tidak selalu mempertimbangkan prediktor yang sama ketika mencari pemisah terbaik. Tujuan pengacakan prediktor adalah mengurangi korelasi antar-pohon. Apabila semua pohon terlalu mirip, manfaat agregasi menjadi terbatas (Fransiska, 2026).
Konsep dasar RF adalah sebagai berikut (Fransiska, 2026):
mtry prediktor yang dipilih secara
acak sebagai kandidat pemisah.Tabel 1. Perbedaan Bagging dan Random Forest
| Aspek | Bagging | Random Forest |
|---|---|---|
| Data tiap tree | Umumnya sampel bootstrap | Umumnya sampel bootstrap |
| Prediktor pada pemisahan | Semua prediktor dapat dipertimbangkan | Hanya mtry prediktor yang dipilih secara
acak |
| Korelasi antar-tree | 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 tree |
Sumber: Fransiska (2026).
Misalkan tersedia data latih \(D = \{(x_i, y_i)\}, i = 1, 2, \dots, n\) dan akan dibentuk \(B\) pohon. Proses RF dilakukan sebagai berikut (Fransiska, 2026):
mtry prediktor
secara acak dari seluruh \(p\)
prediktor.mtry prediktor
yang terpilih.Untuk regresi, prediksi akhir diperoleh dengan merata-ratakan prediksi semua pohon:
\[\hat{f}_{RF}(x) = \frac{1}{B}\sum_{b=1}^{B} T_b(x)\]
dengan \(T_b(x)\) adalah prediksi pohon ke-\(b\). RF tetap merupakan metode parallel ensemble karena setiap pohon dapat dibentuk secara relatif independen, berbeda dari Boosting yang bersifat sekuensial (Fransiska, 2026).
Pada bootstrap berukuran \(n\) yang diambil dengan pengembalian dari \(n\) observasi, sebagian observasi terambil lebih dari sekali dan sebagian lainnya tidak terambil. Secara rata-rata, proporsi observasi unik pada satu sampel bootstrap mendekati \(1 - e^{-1} \approx 0{,}632\), sehingga sekitar 36,8% observasi tidak digunakan untuk membentuk pohon tertentu dan disebut observasi Out-of-Bag (OOB) (Fransiska, 2026).
Prediksi OOB untuk observasi ke-\(i\) diperoleh hanya dari pohon-pohon yang tidak menggunakan observasi tersebut ketika dibentuk. Dengan demikian, OOB MSE dapat dihitung sebagai ukuran evaluasi internal tanpa data uji terpisah:
\[\hat{y}_i^{OOB} = \frac{1}{|B_i|}\sum_{b \in B_i} T_b(x_i), \qquad MSE_{OOB} = \frac{1}{n}\sum_{i=1}^{n}\left(y_i - \hat{y}_i^{OOB}\right)^2\]
dengan \(B_i\) adalah himpunan pohon
yang tidak memuat observasi ke-\(i\).
Pada ranger, OOB error dihitung secara otomatis;
untuk regresi, prediction.error menyatakan OOB MSE dan
r.squared menyatakan R² berdasarkan prediksi OOB
(Fransiska, 2026).
Double Random Forest diperkenalkan oleh Han, Kim, dan Lee pada tahun 2020 untuk situasi ketika RF masih mengalami underfitting karena pohon yang dihasilkan belum cukup besar. Pada RF standar, satu sampel bootstrap hanya mengandung sekitar 63,2% observasi unik. Pada DRF, setiap pohon dibangun menggunakan seluruh data latih, sedangkan bootstrap dilakukan sementara pada setiap node untuk mencari aturan pemisah. Setelah pemisah terbaik ditemukan, aturan tersebut diterapkan kembali pada data asli yang mencapai node tersebut, lalu observasi asli dikirim ke child nodes (Fransiska, 2026).
Karena setiap pohon tumbuh dari seluruh data latih, DRF cenderung menghasilkan pohon yang lebih besar, sementara bootstrap pada setiap node dan random feature subset tetap menjaga keragaman aturan pemisah. Konsekuensinya, DRF umumnya membutuhkan waktu komputasi lebih besar dibandingkan RF (Fransiska, 2026).
Tabel 2. Perbedaan Random Forest dan Double Random Forest
| Aspek | Random Forest | Double Random Forest |
|---|---|---|
| Penggunaan data | Setiap pohon dibentuk dari hasil bootstrap data latih | Setiap pohon dibentuk dari seluruh data latih |
| Observasi unik | Sekitar 0,632 kali data latih | Bootstrap hanya sementara pada setiap node untuk mencari pemisah |
| Proses pemisahan | Random feature subset | Bootstrap pada setiap node dan random feature subset |
| Ukuran pohon | Lebih kecil dibandingkan DRF | Cenderung lebih besar dan beragam |
| Waktu komputasi | Lebih cepat | Lebih lama |
| Hasil prediksi akhir | Majority voting (klasifikasi) atau rata-rata (regresi) | Majority voting (klasifikasi) atau rata-rata (regresi) |
Sumber: Fransiska (2026).
Tabel 3. Parameter penting Random Forest pada
ranger
| Parameter | Peran |
|---|---|
num.trees |
Menentukan jumlah pohon yang dibentuk dalam ensambel |
mtry |
Menentukan banyak prediktor kandidat yang dipilih secara acak pada setiap node |
min.node.size |
Mengatur ukuran minimum node dan secara tidak langsung kompleksitas pohon |
replace dan
sample.fraction |
Mengatur mekanisme dan proporsi sampling |
splitrule |
Menentukan aturan pemisah (untuk regresi pada
ranger digunakan variance) |
importance |
Menentukan apakah dan bagaimana variable importance dihitung |
Sumber: Fransiska (2026).
Pada permutation importance, kepentingan suatu variabel diukur dari kenaikan galat prediksi (pada regresi berupa MSE) ketika nilai variabel tersebut diacak. Semakin besar kenaikan galat, semakin penting variabel tersebut bagi model.
Pada Random Forest Regression, evaluasi dilakukan dengan membandingkan nilai aktual dan nilai prediksi pada data testing menggunakan MSE, RMSE, MAE, dan koefisien determinasi (R²) (Fransiska, 2026):
\[MSE = \frac{1}{n}\sum_{i=1}^{n}\left(y_i - \hat{y}_i\right)^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}\left(y_i - \hat{y}_i\right)^2}{\sum_{i=1}^{n}\left(y_i - \bar{y}\right)^2}\]
Semakin kecil nilai MSE, RMSE, dan MAE, serta semakin besar nilai R², maka model semakin baik dalam memprediksi (Da Costa & Rozi, 2025; Fransiska, 2026). RMSE dan MAE memiliki satuan yang sama dengan variabel respon sehingga lebih mudah diinterpretasikan (Masita dkk., 2025).
Data Friedman #1 adalah data simulasi yang disediakan oleh
package mlbench melalui fungsi
mlbench.friedman1(). Data ini terdiri atas 10 variabel
prediktor \(x_1, x_2, \dots, x_{10}\)
yang masing-masing berdistribusi uniform pada selang \([0,1]\). Variabel respon dibangkitkan
dengan persamaan berikut:
\[y = 10\sin(\pi x_1 x_2) + 20(x_3 - 0.5)^2 + 10x_4 + 5x_5 + \varepsilon, \quad \varepsilon \sim N(0,1)\]
Persamaan di atas menunjukkan bahwa hanya lima variabel pertama (\(x_1\) sampai \(x_5\)) yang memengaruhi \(y\), sedangkan \(x_6\) sampai \(x_{10}\) merupakan variabel noise. Hubungan antara prediktor dan respon bersifat non-linear dan memuat interaksi (\(x_1\) dan \(x_2\)). Karakteristik ini menjadikan data Friedman cocok untuk menguji kemampuan model berbasis pohon, termasuk kemampuan variable importance dalam membedakan prediktor yang benar-benar berpengaruh dari variabel noise.
Jenis data yang digunakan dalam penelitian ini adalah data
kuantitatif. Data yang digunakan merupakan data simulasi Friedman #1
yang dibangkitkan dengan fungsi mlbench.friedman1() pada
package mlbench dalam perangkat lunak R, sebanyak
200 observasi dengan set.seed(234). Data dibagi menjadi
data training (70%) dan data testing (30%). Variabel
y digunakan sebagai variabel respons untuk membangun model
prediksi menggunakan Random Forest Regression.
| No | Variabel | Keterangan | Tipe Data | Peran |
|---|---|---|---|---|
| 1 | y | Variabel respon hasil persamaan Friedman #1 | Numerik | Respons |
| 2 | x.1 | Prediktor 1, berdistribusi uniform (0,1) | Numerik | Prediktor |
| 3 | x.2 | Prediktor 2, berdistribusi uniform (0,1) | Numerik | Prediktor |
| 4 | x.3 | Prediktor 3, berdistribusi uniform (0,1) | Numerik | Prediktor |
| 5 | x.4 | Prediktor 4, berdistribusi uniform (0,1) | Numerik | Prediktor |
| 6 | x.5 | Prediktor 5, berdistribusi uniform (0,1) | Numerik | Prediktor |
| 7 | x.6 | Prediktor 6, berdistribusi uniform (0,1),
tidak memengaruhi y (noise) |
Numerik | Prediktor |
| 8 | x.7 | Prediktor 7, berdistribusi uniform (0,1),
tidak memengaruhi y (noise) |
Numerik | Prediktor |
| 9 | x.8 | Prediktor 8, berdistribusi uniform (0,1),
tidak memengaruhi y (noise) |
Numerik | Prediktor |
| 10 | x.9 | Prediktor 9, berdistribusi uniform (0,1),
tidak memengaruhi y (noise) |
Numerik | Prediktor |
| 11 | x.10 | Prediktor 10, berdistribusi uniform (0,1),
tidak memengaruhi y (noise) |
Numerik | Prediktor |
Langkah-langkah yang digunakan pada penelitian ini adalah sebagai berikut:
Pada batasan masalah diminta melakukan analisis Random
Forest secara lengkap mulai dari persiapan data, pembentukan model,
prediksi, evaluasi, visualisasi, dan interpretasi menggunakan
set.seed(234). Analisis yang dilakukan adalah Random
Forest Regression pada data Friedman dengan membandingkan
mtry = c(2, 3, 5) dan
num.trees = c(200, 500, 1000). Performa pada data testing
dibandingkan berdasarkan MSE, RMSE, MAE, R², residual plot, dan
variable importance, serta ditampilkan pula OOB MSE sebagai
evaluasi internal model. Tampilkan dan interpretasikan setiap
output!
Berikut adalah package yang digunakan pada pertemuan 5.
Package ranger menyediakan fungsi ranger()
untuk membentuk model Random Forest secara cepat dan menghitung
OOB error secara otomatis, mlbench untuk
membangkitkan data Friedman, caret untuk membagi data
training dan testing melalui
createDataPartition(), ggplot2 untuk
visualisasi hasil, serta knitr untuk menyajikan tabel.
## x.1 x.2 x.3 x.4 x.5 x.6 x.7
## 1 0.74562000 0.5754994 0.02885590 0.7201653 0.8748022 0.2761835 0.93319087
## 2 0.78171242 0.3157821 0.93745388 0.1849746 0.7039934 0.6426889 0.40177800
## 3 0.02003711 0.7646459 0.79777294 0.5338609 0.9515834 0.9873938 0.08742998
## 4 0.77608539 0.2289793 0.66797951 0.5534984 0.4780999 0.8425175 0.89302195
## 5 0.06691009 0.1715219 0.59740948 0.7547957 0.5332404 0.7327976 0.10244557
## 6 0.64479512 0.6473963 0.01351334 0.7894812 0.2376348 0.4302338 0.88236742
## x.8 x.9 x.10 y
## 1 0.607462891 0.7560942 0.7179672 24.349507
## 2 0.003687496 0.4046106 0.5338439 18.046792
## 3 0.010598118 0.2473974 0.6669937 12.018651
## 4 0.446393069 0.1443539 0.6802987 12.101870
## 5 0.834936006 0.1874371 0.5950115 9.911772
## 6 0.843509237 0.6166422 0.1081932 21.874286
## '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 ...
## [1] 200 11
## 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
Data Friedman yang dibangkitkan terdiri atas 200 observasi dan 11
variabel, yaitu 1 variabel respons (y) dan 10 variabel
prediktor (x.1 sampai x.10), seluruhnya
bertipe numerik. Berdasarkan ringkasan y, nilai minimum
sebesar 3,08, median sebesar 13,81, rata-rata sebesar 14,27, dan
maksimum sebesar 26,15. Seluruh variabel prediktor berada pada rentang 0
sampai 1 sesuai distribusi uniform yang digunakan untuk
membangkitkan data.
## x.1 x.2 x.3 x.4 x.5 x.6 x.7 x.8 x.9 x.10 y
## 0 0 0 0 0 0 0 0 0 0 0
Tidak terdapat missing value pada data (total 0), sehingga data dapat langsung digunakan untuk pemodelan tanpa penanganan data hilang.
ggplot(reg.data, aes(x = y)) +
geom_histogram(bins = 20, fill = "steelblue", color = "white") +
theme_minimal() +
labs(title = "Distribusi Variabel Respons (y) Data Friedman",
x = "Nilai y", y = "Frekuensi")Histogram memperlihatkan sebaran variabel respons y.
Pola sebaran ini menjadi gambaran awal rentang nilai yang harus
diprediksi oleh model.
set.seed(234)
idx.reg <- createDataPartition(reg.data$y, p = 0.70, list = FALSE)
reg.train <- reg.data[idx.reg, ]
reg.test <- reg.data[-idx.reg, ]
dim(reg.train)## [1] 140 11
## [1] 60 11
Data dibagi menjadi data training sebanyak 140 observasi (70,0%) dan data testing sebanyak 60 observasi (30,0%). Data training digunakan untuk membangun model, sedangkan data testing digunakan untuk menguji kemampuan model pada data baru. Pembagian yang sama digunakan untuk seluruh kombinasi parameter agar perbandingan antar-model adil.
# Fungsi untuk menghitung metrik evaluasi regresi
hitung_metrik <- function(aktual, prediksi) {
mse <- mean((aktual - prediksi)^2)
c(
MSE = mse,
RMSE = sqrt(mse),
MAE = mean(abs(aktual - prediksi)),
R2 = 1 - sum((aktual - prediksi)^2) / sum((aktual - mean(aktual))^2)
)
}Fungsi hitung_metrik() dibuat agar perhitungan MSE,
RMSE, MAE, dan R² pada seluruh model menggunakan rumus yang sama, sesuai
rumus pada subbab 2.6.
Model ini mengikuti contoh sintaks pada modul dan digunakan untuk menjelaskan setiap output secara rinci sebelum seluruh kombinasi parameter dibandingkan.
set.seed(234)
rf.ref <- ranger(
y ~ ., data = reg.train,
num.trees = 500,
mtry = 3,
min.node.size = 5,
replace = TRUE,
sample.fraction = 1,
importance = "permutation",
seed = 234
)
rf.ref## Ranger result
##
## Call:
## ranger(y ~ ., data = reg.train, num.trees = 500, mtry = 3, min.node.size = 5, replace = TRUE, sample.fraction = 1, importance = "permutation", seed = 234)
##
## Type: Regression
## Number of trees: 500
## Sample size: 140
## Number of independent variables: 10
## Mtry: 3
## Target node size: 5
## Variable importance mode: permutation
## Splitrule: variance
## OOB prediction error (MSE): 7.442423
## R squared (OOB): 0.7198089
Model dibentuk dari 500 pohon dengan 3 prediktor kandidat pada setiap
node dari total 10 prediktor, ukuran node minimum
sebesar 5, dan sampling dengan pengembalian
(replace = TRUE, sample.fraction = 1). Nilai
min.node.size = 5 merupakan nilai bawaan
ranger untuk regresi.
## [1] 7.442423
## [1] 0.7198089
Evaluasi internal menghasilkan OOB MSE sebesar 7,4424 dan OOB R²
sebesar 0,7198. Nilai ini dihitung hanya dari pohon-pohon yang tidak
memuat observasi terkait sehingga dapat dipandang sebagai estimasi galat
pada data baru tanpa menggunakan data testing. OOB R² sebesar
0,7198 berarti model menjelaskan sekitar 71,98% keragaman y
berdasarkan prediksi OOB.
pred.ref <- predict(rf.ref, data = reg.test)$predictions
hasil.ref <- data.frame(
Aktual = reg.test$y,
Prediksi = pred.ref,
Residual = reg.test$y - pred.ref
)
head(hasil.ref, 10)## Aktual Prediksi Residual
## 1 10.232309 12.45530 -2.222993
## 2 11.845301 10.61769 1.227616
## 3 10.335689 13.22948 -2.893786
## 4 16.727262 13.36756 3.359704
## 5 25.077119 19.52815 5.548972
## 6 15.446886 14.25467 1.192216
## 7 15.642915 12.62468 3.018240
## 8 7.110835 12.82445 -5.713616
## 9 13.351277 15.38944 -2.038159
## 10 12.871960 14.62054 -1.748578
## MSE RMSE MAE R2
## 7.8278 2.7978 2.3058 0.6734
Pada data testing, model mtry = 3 dan
num.trees = 500 menghasilkan MSE sebesar 7,8278, RMSE
sebesar 2,7978, dan MAE sebesar 2,3058. Nilai R² sebesar 0,6734
menunjukkan bahwa model mampu menjelaskan sekitar 67,34% keragaman
y pada data testing. Kolom Residual
pada tabel menunjukkan selisih nilai aktual dan prediksi; residual
positif berarti model memprediksi lebih rendah dari nilai aktual,
sedangkan residual negatif berarti model memprediksi lebih tinggi.
par(mfrow = c(1, 2))
plot(reg.test$y, pred.ref, pch = 19, col = "steelblue",
xlab = "Nilai Aktual", ylab = "Nilai Prediksi",
main = "Aktual vs Prediksi (mtry = 3, ntree = 500)")
abline(a = 0, b = 1, lty = 2, lwd = 2, col = "red")
plot(pred.ref, hasil.ref$Residual, pch = 19, col = "steelblue",
xlab = "Nilai Prediksi", ylab = "Residual",
main = "Residual Plot (mtry = 3, ntree = 500)")
abline(h = 0, lty = 2, lwd = 2, col = "red")Pada grafik kiri, garis putus-putus merah merupakan garis identitas, yaitu kondisi ketika nilai prediksi sama dengan nilai aktual. Semakin dekat titik ke garis ini, semakin akurat prediksinya. Pada grafik kanan, residual yang tersebar acak di sekitar garis nol tanpa pola tertentu menunjukkan bahwa model tidak memiliki bias sistematis; sebaliknya, pola melengkung atau melebar menandakan ada struktur data yang belum ditangkap model.
Selanjutnya dibangun sembilan model, yaitu kombinasi
mtry (2, 3, 5) dan num.trees (200, 500, 1000).
Seluruh parameter lain dibuat sama, dan set.seed(234) serta
seed = 234 digunakan sebelum setiap model dibentuk agar
hasil dapat direproduksi.
grid <- expand.grid(mtry = c(2L, 3L, 5L), num.trees = c(200L, 500L, 1000L))
grid <- grid[order(grid$mtry, grid$num.trees), ]
rownames(grid) <- NULL
grid$id <- paste0("mtry=", grid$mtry, ", ntree=", grid$num.trees)
model_list <- vector("list", nrow(grid)); names(model_list) <- grid$id
pred_list <- vector("list", nrow(grid)); names(pred_list) <- grid$id
hasil_rows <- vector("list", nrow(grid))
for (i in seq_len(nrow(grid))) {
set.seed(234)
mod <- ranger(
y ~ ., data = reg.train,
num.trees = grid$num.trees[i],
mtry = grid$mtry[i],
min.node.size = 5,
replace = TRUE,
sample.fraction = 1,
importance = "permutation",
seed = 234
)
prd <- predict(mod, data = reg.test)$predictions
mt <- hitung_metrik(reg.test$y, prd)
res <- reg.test$y - prd
model_list[[i]] <- mod
pred_list[[i]] <- prd
hasil_rows[[i]] <- data.frame(
mtry = grid$mtry[i],
num.trees = grid$num.trees[i],
OOB_MSE = mod$prediction.error,
OOB_R2 = mod$r.squared,
MSE = unname(mt["MSE"]),
RMSE = unname(mt["RMSE"]),
MAE = unname(mt["MAE"]),
R2 = unname(mt["R2"]),
Mean_Resid = mean(res),
SD_Resid = sd(res),
MaxAbs_Resid = max(abs(res))
)
}
hasil <- do.call(rbind, hasil_rows)
rownames(hasil) <- NULLKesembilan model berhasil dibentuk dan disimpan dalam
model_list, sedangkan prediksi data testing
masing-masing model disimpan dalam pred_list. Seluruh model
dilatih pada data training yang sama dan diuji pada data
testing yang sama.
tab_oob <- hasil[, c("mtry", "num.trees", "OOB_MSE", "OOB_R2")]
kable(tab_oob, digits = 4, align = "c",
caption = "OOB MSE dan OOB R-squared seluruh kombinasi mtry dan num.trees (data training)")| mtry | num.trees | OOB_MSE | OOB_R2 |
|---|---|---|---|
| 2 | 200 | 8.2222 | 0.6905 |
| 2 | 500 | 8.1267 | 0.6940 |
| 2 | 1000 | 8.0553 | 0.6967 |
| 3 | 200 | 7.7097 | 0.7097 |
| 3 | 500 | 7.4424 | 0.7198 |
| 3 | 1000 | 7.3547 | 0.7231 |
| 5 | 200 | 7.0632 | 0.7341 |
| 5 | 500 | 6.8750 | 0.7412 |
| 5 | 1000 | 6.8260 | 0.7430 |
Berdasarkan evaluasi internal, OOB MSE terkecil diperoleh pada model
dengan mtry = 5 dan num.trees = 1000, yaitu
sebesar 6,8260 dengan OOB R² sebesar 0,7430. Jika dirata-ratakan, nilai
mtry yang menghasilkan OOB MSE terkecil adalah 5 dan nilai
num.trees yang menghasilkan OOB MSE terkecil adalah 1000.
OOB MSE dihitung tanpa data testing sehingga menjadi pembanding
internal bagi hasil pada data testing.
tab_test <- hasil[, c("mtry", "num.trees", "MSE", "RMSE", "MAE", "R2")]
kable(tab_test, digits = 4, align = "c",
caption = "Metrik evaluasi data testing seluruh kombinasi mtry dan num.trees")| mtry | num.trees | MSE | RMSE | MAE | R2 |
|---|---|---|---|---|---|
| 2 | 200 | 7.8700 | 2.8054 | 2.3414 | 0.6717 |
| 2 | 500 | 8.1774 | 2.8596 | 2.3832 | 0.6589 |
| 2 | 1000 | 8.1181 | 2.8492 | 2.3794 | 0.6613 |
| 3 | 200 | 7.8139 | 2.7953 | 2.2981 | 0.6740 |
| 3 | 500 | 7.8278 | 2.7978 | 2.3058 | 0.6734 |
| 3 | 1000 | 7.7780 | 2.7889 | 2.2996 | 0.6755 |
| 5 | 200 | 7.6596 | 2.7676 | 2.2726 | 0.6805 |
| 5 | 500 | 7.3826 | 2.7171 | 2.2312 | 0.6920 |
| 5 | 1000 | 7.1925 | 2.6819 | 2.2054 | 0.6999 |
Berdasarkan data testing, model dengan mtry = 5
dan num.trees = 1000 memiliki MSE terkecil (7,1925) dan
RMSE terkecil (2,6819). Model dengan mtry = 5 dan
num.trees = 1000 memiliki MAE terkecil (2,2054), sedangkan
R² terbesar (0,6999) dimiliki model dengan mtry = 5 dan
num.trees = 1000. Kriteria RMSE dan MAE menunjuk model yang
sama sehingga pemilihan model terbaik konsisten. Karena data
testing yang sama digunakan, urutan MSE, RMSE, dan R² selalu
sejalan.
kable(agg_mtry, digits = 4, align = "c",
caption = "Rata-rata metrik menurut nilai mtry (rata-rata atas tiga num.trees)")| mtry | OOB_MSE | MSE | RMSE | MAE | R2 |
|---|---|---|---|---|---|
| 2 | 8.1348 | 8.0552 | 2.8381 | 2.3680 | 0.6640 |
| 3 | 7.5023 | 7.8066 | 2.7940 | 2.3012 | 0.6743 |
| 5 | 6.9214 | 7.4115 | 2.7222 | 2.2364 | 0.6908 |
kable(agg_tree, digits = 4, align = "c",
caption = "Rata-rata metrik menurut nilai num.trees (rata-rata atas tiga mtry)")| num.trees | OOB_MSE | MSE | RMSE | MAE | R2 |
|---|---|---|---|---|---|
| 200 | 7.6650 | 7.7812 | 2.7894 | 2.3040 | 0.6754 |
| 500 | 7.4814 | 7.7959 | 2.7915 | 2.3067 | 0.6748 |
| 1000 | 7.4120 | 7.6962 | 2.7733 | 2.2948 | 0.6789 |
Dari rata-rata atas ketiga num.trees, nilai
mtry dengan RMSE data testing terkecil adalah 5,
yaitu 2,7222. Dari rata-rata atas ketiga mtry, nilai
num.trees dengan RMSE data testing terkecil adalah
1000, yaitu 2,7733.
Untuk membandingkan besar pengaruh kedua parameter, dihitung rentang
RMSE akibat perubahan num.trees pada mtry yang
sama (maksimum 0,0857) dan rentang RMSE akibat perubahan
mtry pada num.trees yang sama (maksimum
0,1674). Dengan demikian, variasi RMSE pada penelitian ini lebih
dipengaruhi oleh perubahan mtry dibandingkan perubahan num.trees. Secara
teori, mtry yang kecil membuat pohon lebih beragam dan
lebih tidak berkorelasi, tetapi dapat memaksa pohon memakai prediktor
yang kurang informatif, sedangkan mtry yang besar membuat
pohon lebih kuat tetapi lebih mirip satu sama lain (mendekati Bagging).
Penambahan num.trees menurunkan variance agregasi,
tetapi penurunannya semakin kecil dan akhirnya cenderung stabil. Hal ini
sejalan dengan temuan Fadillah dan Fauzan (2024) yang menunjukkan
pentingnya pengaturan hyperparameter pada Random Forest
Regression.
metrik_long <- rbind(
data.frame(mtry = factor(hasil$mtry), num.trees = hasil$num.trees,
Metrik = "OOB MSE (data training)", Nilai = hasil$OOB_MSE),
data.frame(mtry = factor(hasil$mtry), num.trees = hasil$num.trees,
Metrik = "MSE (data testing)", Nilai = hasil$MSE)
)
ggplot(metrik_long, aes(x = num.trees, y = Nilai, color = mtry, group = mtry)) +
geom_line(linewidth = 1) +
geom_point(size = 2.5) +
facet_wrap(~ Metrik, scales = "free_y") +
scale_x_continuous(breaks = c(200, 500, 1000)) +
theme_minimal() +
labs(title = "OOB MSE dan MSE Data Testing menurut num.trees dan mtry",
x = "Jumlah pohon (num.trees)", y = "Nilai MSE", color = "mtry")Grafik garis memperlihatkan perubahan OOB MSE (kiri) dan MSE data
testing (kanan) ketika num.trees bertambah, untuk
setiap nilai mtry. Garis yang mendatar menandakan bahwa
penambahan pohon tidak lagi menurunkan galat secara berarti, sedangkan
jarak antar-garis menunjukkan pengaruh mtry.
metrik_long2 <- rbind(
data.frame(mtry = factor(hasil$mtry), num.trees = hasil$num.trees, Metrik = "RMSE", Nilai = hasil$RMSE),
data.frame(mtry = factor(hasil$mtry), num.trees = hasil$num.trees, Metrik = "MAE", Nilai = hasil$MAE),
data.frame(mtry = factor(hasil$mtry), num.trees = hasil$num.trees, Metrik = "R-squared", Nilai = hasil$R2)
)
metrik_long2$Metrik <- factor(metrik_long2$Metrik, levels = c("RMSE", "MAE", "R-squared"))
ggplot(metrik_long2, aes(x = factor(num.trees), y = Nilai, fill = mtry)) +
geom_col(position = "dodge") +
geom_text(aes(label = round(Nilai, 3)),
position = position_dodge(width = 0.9), vjust = -0.3, size = 3) +
facet_wrap(~ Metrik, scales = "free_y") +
theme_minimal() +
labs(title = "RMSE, MAE, dan R-squared Data Testing",
x = "Jumlah pohon (num.trees)", y = "Nilai", fill = "mtry")Grafik batang membandingkan RMSE, MAE, dan R² pada data testing untuk seluruh kombinasi. Batang RMSE dan MAE yang lebih rendah serta batang R² yang lebih tinggi menunjukkan model yang lebih baik.
nama_mtry <- paste0("mtry = ", c(2, 3, 5))
nama_tree <- paste0("ntree = ", c(200, 500, 1000))
plot_df <- do.call(rbind, lapply(seq_len(nrow(grid)), function(i) {
data.frame(
Aktual = reg.test$y,
Prediksi = pred_list[[i]],
Residual = reg.test$y - pred_list[[i]],
mtry = factor(paste0("mtry = ", grid$mtry[i]), levels = nama_mtry),
ntree = factor(paste0("ntree = ", grid$num.trees[i]), levels = nama_tree)
)
}))ggplot(plot_df, aes(x = Aktual, y = Prediksi)) +
geom_point(alpha = 0.7, color = "steelblue") +
geom_abline(slope = 1, intercept = 0, color = "red", linetype = "dashed") +
facet_grid(mtry ~ ntree) +
theme_minimal() +
labs(title = "Nilai Aktual vs Prediksi (Data Testing)",
x = "Nilai Aktual", y = "Nilai Prediksi")Pada diagram pencar, garis putus-putus merah adalah garis identitas.
Titik-titik yang rapat di sekitar garis menunjukkan prediksi yang
akurat. Kesembilan panel memperlihatkan pola yang serupa, yang
menunjukkan bahwa seluruh kombinasi parameter mampu mengikuti pola data
dengan tingkat ketelitian yang tidak berbeda jauh; perbedaan antar-model
terutama terlihat pada sebaran titik di nilai y yang
ekstrem (rendah atau tinggi), tempat prediksi cenderung tertarik ke arah
rata-rata akibat sifat agregasi rata-rata pada RF.
ggplot(plot_df, aes(x = Prediksi, y = Residual)) +
geom_point(alpha = 0.7, color = "steelblue") +
geom_hline(yintercept = 0, color = "red", linetype = "dashed") +
facet_grid(mtry ~ ntree) +
theme_minimal() +
labs(title = "Residual Plot (Data Testing)",
x = "Nilai Prediksi", y = "Residual (Aktual - Prediksi)")tab_res <- hasil[, c("mtry", "num.trees", "Mean_Resid", "SD_Resid", "MaxAbs_Resid")]
kable(tab_res, digits = 4, align = "c",
caption = "Ringkasan residual data testing seluruh model")| mtry | num.trees | Mean_Resid | SD_Resid | MaxAbs_Resid |
|---|---|---|---|---|
| 2 | 200 | -0.1293 | 2.8260 | 5.8805 |
| 2 | 500 | -0.1670 | 2.8788 | 6.2353 |
| 2 | 1000 | -0.1443 | 2.8696 | 6.1865 |
| 3 | 200 | -0.1555 | 2.8146 | 5.9181 |
| 3 | 500 | -0.2099 | 2.8135 | 5.7136 |
| 3 | 1000 | -0.2247 | 2.8033 | 5.7419 |
| 5 | 200 | -0.3270 | 2.7714 | 5.9668 |
| 5 | 500 | -0.2830 | 2.7251 | 5.7442 |
| 5 | 1000 | -0.2726 | 2.6905 | 5.7607 |
Residual plot digunakan untuk memeriksa apakah galat
tersebar acak di sekitar nol. Rata-rata residual pada seluruh model
berkisar antara -0,3270 dan -0,1293, relatif kecil dibandingkan
simpangan baku residual sehingga tidak tampak bias sistematis yang
besar. Simpangan baku residual terkecil dimiliki model dengan
mtry = 5 dan num.trees = 1000 (2,6905),
sedangkan residual absolut terbesar pada seluruh model adalah 6,24. Jika
pada panel tampak residual positif besar pada prediksi rendah dan
residual negatif pada prediksi tinggi, hal itu mencerminkan
kecenderungan RF menarik prediksi ke arah rata-rata
(shrinkage), yang wajar pada model berbasis rata-rata
pohon.
# Matriks permutation importance: baris = variabel, kolom = model
imp_mat <- sapply(model_list, function(m) m$variable.importance)
imp_long <- data.frame(
Variabel = factor(rep(rownames(imp_mat), times = ncol(imp_mat)),
levels = paste0("x.", 1:10)),
Model = factor(rep(colnames(imp_mat), each = nrow(imp_mat)), levels = grid$id),
Importance = as.vector(imp_mat)
)## x.4 x.1 x.2 x.3 x.5 x.10 x.9 x.8 x.6 x.7
## 11.0137 8.1718 3.5563 2.2339 1.0121 0.1533 -0.0368 -0.1014 -0.1326 -0.1669
Pada model acuan (mtry = 3,
num.trees = 500), variabel dengan permutation
importance terbesar adalah x.4 (11,0137), diikuti x.1 (8,1718) dan
x.2 (3,5563).
ggplot(imp_long, aes(x = Model, y = Variabel, fill = Importance)) +
geom_tile(color = "white") +
geom_text(aes(label = round(Importance, 2)), size = 3) +
scale_fill_gradient(low = "white", high = "steelblue") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(title = "Permutation Importance pada Seluruh Model",
x = "Model", y = "Variabel")top5_semua <- apply(imp_mat, 2, function(v) {
setequal(names(sort(v, decreasing = TRUE))[1:5], paste0("x.", 1:5))
})Heatmap memperlihatkan permutation importance
seluruh variabel pada kesembilan model. Pada 9 dari 9 model, lima
variabel dengan importance tertinggi tepat berupa
x.1 sampai x.5, yaitu prediktor yang memang
membentuk y pada persamaan Friedman. Hasil ini menunjukkan
bahwa seluruh model konsisten dalam membedakan prediktor yang
berpengaruh dari variabel noise, apa pun nilai mtry dan num.trees yang
digunakan.
nama_best <- grid$id[i_rmse]
rf.best <- model_list[[nama_best]]
pred.best <- pred_list[[nama_best]]
imp_best <- sort(rf.best$variable.importance, decreasing = TRUE)
round(imp_best, 4)## x.4 x.1 x.2 x.3 x.5 x.6 x.10 x.8 x.9 x.7
## 12.9314 9.3875 3.8211 1.8255 0.9720 0.1000 0.0976 -0.0096 -0.0802 -0.1430
kable(hasil[i_rmse, c("mtry", "num.trees", "OOB_MSE", "OOB_R2", "MSE", "RMSE", "MAE", "R2")],
digits = 4, align = "c", row.names = FALSE,
caption = "Model terbaik berdasarkan RMSE data testing")| mtry | num.trees | OOB_MSE | OOB_R2 | MSE | RMSE | MAE | R2 |
|---|---|---|---|---|---|---|---|
| 5 | 1000 | 6.826 | 0.743 | 7.1925 | 2.6819 | 2.2054 | 0.6999 |
imp_df <- data.frame(
Variabel = factor(names(imp_best), levels = rev(names(imp_best))),
Importance = as.numeric(imp_best),
Jenis = ifelse(names(imp_best) %in% paste0("x.", 1:5),
"Prediktor sebenarnya (x.1 - x.5)", "Noise (x.6 - x.10)")
)
ggplot(imp_df, aes(x = Variabel, y = Importance, fill = Jenis)) +
geom_col() +
coord_flip() +
theme_minimal() +
labs(title = paste0("Variable Importance - Model Terbaik (", nama_best, ")"),
x = "Variabel", y = "Permutation Importance", fill = "")Berdasarkan RMSE data testing, model terbaik adalah model
dengan mtry = 5 dan num.trees = 1000 dengan
RMSE 2,6819, MAE 2,2054, dan R² 0,6999. Evaluasi internal model ini
memberikan OOB MSE sebesar 6,8260, sedangkan MSE pada data
testing sebesar 7,1925, atau 1,05 kali OOB MSE. Galat pada data
testing berada pada kisaran yang sama dengan estimasi OOB, yang
menunjukkan bahwa evaluasi internal dan evaluasi pada data baru
memberikan gambaran kinerja yang selaras. Model terbaik berdasarkan data
testing sama dengan model terbaik berdasarkan OOB MSE, sehingga kedua
kriteria saling menguatkan.
Pada model terbaik, variabel terpenting adalah x.4 dengan permutation importance sebesar 12,9314. Lima variabel teratas tepat berupa x.1 sampai x.5. Importance terendah di antara kelima prediktor sebenarnya sebesar 0,9720, sedangkan importance tertinggi di antara variabel noise (x.6 sampai x.10) hanya sebesar 0,1000. Hal ini sesuai dengan persamaan Friedman, yaitu hanya x.1 sampai x.5 yang membentuk y. Temuan ini menunjukkan bahwa RF tidak hanya memberikan prediksi yang akurat, tetapi juga dapat dimanfaatkan untuk mengidentifikasi variabel yang berpengaruh pada respons, termasuk hubungan non-linear dan interaksi yang sulit ditangkap model linier (Da Costa & Rozi, 2025; Khamidah dkk., 2024).
par(mfrow = c(1, 2))
plot(reg.test$y, pred.best, pch = 19, col = "steelblue",
xlab = "Nilai Aktual", ylab = "Nilai Prediksi",
main = paste0("Aktual vs Prediksi\n", nama_best))
abline(a = 0, b = 1, lty = 2, lwd = 2, col = "red")
res.best <- reg.test$y - pred.best
plot(pred.best, res.best, pch = 19, col = "steelblue",
xlab = "Nilai Prediksi", ylab = "Residual",
main = paste0("Residual Plot\n", nama_best))
abline(h = 0, lty = 2, lwd = 2, col = "red")Grafik di atas merangkum kualitas prediksi model terbaik: titik yang
rapat di sekitar garis identitas pada grafik kiri dan residual yang
tersebar acak di sekitar nol pada grafik kanan menunjukkan bahwa model
mampu memprediksi y dengan baik pada data
testing.
Random Forest adalah metode ensambel yang membangun banyak
pohon dari sampel bootstrap dengan pemilihan mtry
prediktor secara acak pada setiap node, sehingga korelasi
antar-pohon menurun dan variance prediksi berkurang. Pada kasus
regresi, prediksi akhir diperoleh dengan merata-ratakan prediksi seluruh
pohon. Double Random Forest merupakan pengembangan yang
membangun setiap pohon dari seluruh data latih dan menggunakan
bootstrap pada setiap node, sehingga cenderung
menghasilkan pohon yang lebih besar dengan waktu komputasi yang lebih
lama. Model Random Forest Regression pada data Friedman
berhasil dibangun menggunakan fungsi ranger() dengan
importance = "permutation" dan dievaluasi menggunakan OOB
MSE, MSE, RMSE, MAE, R², residual plot, dan variable
importance.
Berdasarkan perbandingan sembilan kombinasi mtry (2, 3,
5) dan num.trees (200, 500, 1000), model terbaik pada data
testing adalah model dengan mtry = 5 dan
num.trees = 1000 dengan MSE 7,1925, RMSE 2,6819, MAE
2,2054, dan R² 0,6999. Evaluasi internal menunjukkan OOB MSE terkecil
pada model dengan mtry = 5 dan num.trees =
1000 sebesar 6,8260. Variasi kinerja lebih dipengaruhi oleh mtry
dibandingkan num.trees. Dari sisi variable importance, pada 9
dari 9 model lima variabel teratas adalah x.1 sampai
x.5, yaitu prediktor yang sebenarnya membentuk
y. Dengan mempertimbangkan data testing dan OOB
MSE, model dengan mtry = 5 dan num.trees =
1000 dipilih sebagai model terbaik pada praktikum ini.
Praktikan disarankan untuk mempelajari lebih lanjut mengenai program
RStudio melalui berbagai sumber pembelajaran, seperti buku, jurnal,
modul praktikum, maupun sumber belajar lainnya agar semakin memahami
penerapan metode ensambel. Pada penelitian selanjutnya, disarankan
menggunakan validasi silang (cross-validation) atau pengulangan
pembagian data agar perbandingan model lebih andal, mencoba parameter
lain seperti min.node.size dan mtry yang lebih
beragam, serta mengimplementasikan Double Random Forest dan
membandingkannya dengan RF dari sisi akurasi dan waktu komputasi.
Praktikan juga diharapkan lebih teliti dalam melakukan pengolahan data
dan penulisan kode program agar dapat meminimalkan kesalahan selama
praktikum.
Fransiska, H. (2026). Modul Praktikum Machine Learning dan Model Prediction. Universitas Bengkulu: Bengkulu.
Da Costa, N. M. A., & Rozi, A. F. (2025). Analisis efisiensi tidur berdasarkan faktor demografi dan kebiasaan harian dengan metode random forest regression. Jurnal Pendidikan Informatika dan Sains, 14(1), 160–174. https://doi.org/10.31571/saintek.v14i1.9291
Fadillah, A. R., & Fauzan, M. N. (2024). Analisis perbandingan Linear Regression dan Random Forest Regression untuk prediksi batas kredit: Pendekatan optimasi hyperparameter. Jurnal Informatika Polinema, 10(4), 543–550. https://doi.org/10.33795/jip.v10i4.5700
Khamidah, N., Sadik, K., Soleh, A. M., & Dito, G. A. (2024). Regularisasi model pembelajaran mesin dengan regresi terpenalti pada data yang mengandung multikolinearitas (Studi kasus prediksi Indeks Pembangunan Manusia di 34 provinsi di Indonesia). Majalah Ilmiah Matematika dan Statistika, 24(1), 12–26.
Masita, A. R. P., Saputri, P. D., & Atok, R. M. (2025). Analisis perbandingan metode decision tree regression dan random forest regression pada prediksi kepesertaan Jaminan Kesehatan Nasional. MATHunesa: Jurnal Ilmiah Matematika, 13(2), 291–302.