BAB I PENDAHULUAN

1.1 Latar Belakang Masalah

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.

1.2 Rumusan Masalah

Berdasarkan latar belakang, rumusan masalah yang dapat disimpulkan adalah sebagai berikut:

  1. Bagaimana memahami Random Forest dan Double Random Forest sebagai metode ensemble berbasis decision tree?
  2. Bagaimana cara mengimplementasikan Random Forest untuk klasifikasi dan regresi, serta Double Random Forest untuk klasifikasi dan regresi?
  3. Bagaimana mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan Random Forest dengan Double Random Forest?

1.3 Tujuan Penelitian

Berdasarkan rumusan masalah tersebut, tujuan yang dapat disimpulkan adalah sebagai berikut:

  1. Memahami Random Forest dan Double Random Forest sebagai metode ensemble berbasis decision tree.
  2. Mengimplementasikan Random Forest untuk klasifikasi dan regresi, serta Double Random Forest untuk klasifikasi dan regresi.
  3. Mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan Random Forest dengan Double Random Forest.

BAB II TINJAUAN PUSTAKA

2.1 Dari Bagging ke Random Forest

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):

  1. Bootstrap sampling. Setiap pohon dibangun dari sampel acak dengan pengembalian dari data latih.
  2. Pembangunan banyak pohon. Setiap pohon tumbuh sangat dalam (fully grown) sehingga memiliki variance tinggi namun bias rendah.
  3. Random feature selection. Pada setiap node, hanya mtry prediktor yang dipilih secara acak sebagai kandidat pemisah.
  4. Agregasi prediksi. Pada klasifikasi digunakan majority vote, sedangkan pada regresi digunakan rata-rata prediksi seluruh pohon.

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).

2.2 Proses Random Forest Regression

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):

  1. Mengambil sampel bootstrap dari data latih untuk membentuk data bagi pohon ke-\(b\).
  2. Pada setiap node, memilih mtry prediktor secara acak dari seluruh \(p\) prediktor.
  3. Menentukan pemisah terbaik hanya dari mtry prediktor yang terpilih.
  4. Menumbuhkan pohon hingga memenuhi aturan penghentian, misalnya ukuran node minimum.
  5. Mengulangi proses sampai diperoleh \(B\) pohon, kemudian menggabungkan prediksi seluruh pohon.

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).

2.3 Out-of-Bag (OOB) Error

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).

2.4 Double Random Forest (DRF)

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).

2.5 Parameter Penting Random Forest

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.

2.6 Evaluasi 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).

2.7 Data Friedman

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.

BAB III METODE PENELITIAN

3.1 Sumber Data

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.

3.2 Variabel Penelitian

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

3.3 Langkah-langkah Analisis

Langkah-langkah yang digunakan pada penelitian ini adalah sebagai berikut:

  1. Mulai.
  2. Memanggil package yang diperlukan (ranger, mlbench, caret, ggplot2, dan knitr).
  3. Membangkitkan data Friedman #1 sebanyak 200 observasi menggunakan fungsi mlbench.friedman1() dengan set.seed(234), lalu memeriksa struktur, ringkasan, dan missing value.
  4. Membagi data menjadi data training (70%) dan data testing (30%) menggunakan createDataPartition().
  5. Membangun model Random Forest Regression menggunakan fungsi ranger() dengan importance = “permutation” untuk seluruh kombinasi mtry = 2, 3, 5 dan num.trees = 200, 500, 1000 (9 model).
  6. Melihat hasil model dan evaluasi internal berupa OOB MSE dan OOB R-squared.
  7. Memprediksi data testing dengan masing-masing model, lalu membandingkan nilai aktual dan prediksi.
  8. Menghitung metrik evaluasi (MSE, RMSE, MAE, dan R-squared) pada data testing.
  9. Membuat residual plot dan menghitung variable importance pada masing-masing model.
  10. Membandingkan seluruh model berdasarkan metrik evaluasi, residual plot, dan variable importance, lalu menentukan model terbaik.
  11. Menarik kesimpulan.
  12. Selesai.

3.4 Diagram Alir Penelitian

BAB IV HASIL DAN PEMBAHASAN

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!

4.1 Library

library(ranger)
library(mlbench)
library(caret)
library(ggplot2)
library(knitr)

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.

4.2 Membangkitkan dan Eksplorasi Data

set.seed(234)
reg.data <- as.data.frame(mlbench.friedman1(200))

head(reg.data)
##          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
str(reg.data)
## '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 ...
dim(reg.data)
## [1] 200  11
summary(reg.data)
##       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.

colSums(is.na(reg.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.

4.3 Membagi Data Training dan Testing

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
dim(reg.test)
## [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.

4.4 Random Forest Regression dengan mtry = 3 dan num.trees = 500

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.

rf.ref$prediction.error   # OOB MSE
## [1] 7.442423
rf.ref$r.squared          # OOB R-square
## [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
m.ref <- hitung_metrik(reg.test$y, pred.ref)
round(m.ref, 4)
##    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")

par(mfrow = c(1, 1))

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.

4.5 Random Forest Regression untuk Seluruh Kombinasi mtry dan num.trees

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) <- NULL

Kesembilan 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.

4.5.1 Evaluasi Internal: OOB MSE dan OOB R-squared

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)")
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.

4.5.2 Kinerja 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")
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.

4.5.3 Pengaruh mtry dan num.trees

kable(agg_mtry, digits = 4, align = "c",
      caption = "Rata-rata metrik menurut nilai mtry (rata-rata atas tiga num.trees)")
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)")
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.

4.5.4 Visualisasi Perbandingan Model

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.

4.6 Nilai Aktual vs Prediksi dan Residual Plot Seluruh Model

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")
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.

4.7 Variable Importance

# 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)
)
importance.ref <- sort(rf.ref$variable.importance, decreasing = TRUE)
round(importance.ref, 4)
##     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.

4.8 Pemilihan Model Terbaik

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")
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")

par(mfrow = c(1, 1))

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.

BAB V KESIMPULAN

5.1 Kesimpulan

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.

5.2 Saran

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.

DAFTAR PUSTAKA

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.