BAB I PENDAHULUAN

1.1 Latar Belakang

Dalam machine learning, ensemble learning merupakan pendekatan yang menggabungkan beberapa model untuk menghasilkan prediksi yang lebih baik. Salah satu metodenya adalah boosting, yaitu metode yang membangun model secara berurutan dengan memperhatikan kesalahan model sebelumnya. Firmansyah dan Abidin (2022) membahas penerapan Gradient Boosted Decision Trees pada AdaBoost untuk klasifikasi status desa. Penelitian tersebut menunjukkan penerapan metode boosting dalam permasalahan klasifikasi.

Penerapan boosting juga dilakukan oleh Novianti dkk. (2022) melalui algoritma AdaBoost untuk meningkatkan kinerja klasifikasi pada data diabetes yang tidak seimbang. Selain itu, Majid dan Miharja (2022) mengkaji kombinasi teknik discretization dan AdaBoost untuk meningkatkan akurasi klasifikasi penyakit jantung. Kedua penelitian tersebut menunjukkan bahwa metode boosting dapat diterapkan pada berbagai permasalahan klasifikasi dengan karakteristik data yang berbeda.

Salah satu metode boosting yang digunakan untuk permasalahan regresi adalah Gradient Boosting. Metode ini membangun model secara bertahap untuk memperbaiki kesalahan prediksi dari model sebelumnya. Pada praktikum ini, Gradient Boosting diterapkan pada data simulasi Friedman menggunakan fungsi gbm() pada perangkat lunak R dengan membandingkan nilai shrinkage sebesar 0,01; 0,05; dan 0,10. Jumlah iterasi optimal ditentukan menggunakan cross-validation, sedangkan performa model dibandingkan berdasarkan nilai MSE, RMSE, MAE, dan R-Square.

1.2 Rumusan Masalah

Berdasarkan latar belakang di atas, rumusan masalah yang dapat disimpulkan yaitu:

  1. Bagaimana cara memahami Boosting sebagai metode ensemble learning?
  2. Bagaimana mengimplementasikan Boosting untuk kasus klasifikasi dan regresi menggunakan R?
  3. Bagaimana mengevaluasi performa model menggunakan ukuran evaluasi yang sesuai?

1.3 Tujuan Penelitian

Berdasarkan rumusan masalah di atas, tujuan yang dapat disimpulkan yaitu:

  1. Praktikan dapat memahami Boosting sebagai metode ensemble learning.
  2. Praktikan dapat mengimplementasikan Boosting untuk kasus klasifikasi dan regresi menggunakan R.
  3. Praktikan dapat mengevaluasi performa model menggunakan ukuran evaluasi yang sesuai.

1.4 Manfaat Penelitian

Adapun manfaat dari praktikum ini yaitu:

  1. Bagi penulis, yaitu dapat memberikan informasi dan pengetahuan serta menerapkan ilmu pengetahuan mengenai metode Boosting dengan R.
  2. Bagi Pembaca, yaitu dapat menambah ilmu pengetahuan dan pemahaman mengenai metode Boosting terhadap kinerja model.

1.5 Batasan Masalah

Adapun batasan masalah dari praktikum ini, yaitu lakukan regresi menggunakan Gradient Boosting pada data Friedman. Clue : Gunakan gbm() dan bandingkan nilai learning rate (shrinkage) 𝜈 = 0.01, 0.05, dan 0.10. Gunakan cross-validation untuk menentukan jumlah iterasi optimal pada masing-masing model. Bandingkan performa berdasarkan MSE, RMSE, MAE, dan 𝑅2, kemudian interpretasikan hasilnya.

BAB II TINJAUAN PUSTAKA

2.1 Ensemble Learning dan Boosting

Ensemble learning merupakan pendekatan yang menggabungkan beberapa model dasar (base learner) untuk memperoleh model gabungan yang memiliki kemampuan prediksi lebih baik. Salah satu metode ensemble learning adalah boosting. Berbeda dengan bagging yang membentuk banyak model secara relatif independen menggunakan sampel bootstrap, boosting membentuk model secara berurutan (sequential) dengan memperhatikan kesalahan yang masih dilakukan oleh model sebelumnya (Fransiska, 2026).

Pada boosting, learner kedua dibangun berdasarkan informasi dari hasil learner pertama, kemudian learner ketiga dibangun untuk memperbaiki hasil yang masih belum baik dari tahap sebelumnya. Proses tersebut dilakukan secara berurutan hingga diperoleh model akhir. Model sederhana yang dibentuk pada setiap tahap disebut weak learner. Meskipun kemampuan prediksi weak learner terbatas apabila digunakan sendiri, penggabungan beberapa weak learner dapat menghasilkan model yang lebih kuat (strong learner) (Fransiska, 2026).

Pada boosting berbasis pohon, decision tree dapat digunakan sebagai base learner. Kedalaman pohon dapat dibatasi sehingga setiap pohon tetap sederhana dan berperan sebagai weak learner. Selanjutnya, kontribusi dari pohon-pohon tersebut digabungkan secara bertahap untuk membentuk model boosting akhir (Fransiska, 2026).

Perbedaan antara bagging dan boosting dapat dilihat pada Tabel berikut.

Tabel 2.1. Perbedaan Bagging dan Boosting

Aspek Bagging Boosting
Cara membangun model Paralel atau relatif independen Sequential
Data tiap learner Umumnya sampel bootstrap Data, bobot, atau target dapat disesuaikan berdasarkan kesalahan sebelumnya
Fokus utama Mengurangi variance melalui agregasi Memperbaiki kesalahan secara bertahap
Kontribusi learner Umumnya setara Dapat berbeda
Base learner Sering menggunakan pohon relatif besar Umumnya learner sederhana atau pohon dangkal
Komputasi Relatif mudah diparalelkan Lebih sulit diparalelkan
Parameter penting Jumlah model dan bootstrap Jumlah iterasi, learning rate, dan kompleksitas learner

Dengan demikian, bagging membangun banyak learner secara independen kemudian menggabungkan hasil prediksinya, sedangkan boosting membangun learner secara berurutan agar setiap learner baru membantu memperbaiki kesalahan yang masih tersisa. Dalam praktikum ini, konsep boosting untuk kasus klasifikasi diperkenalkan melalui Adaptive Boosting (AdaBoost), sedangkan untuk kasus regresi diperkenalkan melalui Gradient Boosting (Fransiska, 2026).

2.2 Adaptive Boosting (AdaBoost)

Adaptive Boosting atau AdaBoost merupakan salah satu algoritma boosting yang digunakan untuk kasus klasifikasi. Pada klasifikasi berbasis pohon, base learner yang digunakan biasanya berupa pohon sederhana atau decision stump. Prinsip utama AdaBoost adalah memberikan perhatian lebih besar pada observasi yang masih salah diklasifikasikan sehingga learner berikutnya dapat lebih fokus pada observasi tersebut (Fransiska, 2026).

Untuk klasifikasi biner, misalkan tersedia data latih \((x_i,y_i)\), dengan \(i=1,2,\ldots,n\). Pada awal proses, seluruh observasi diberikan bobot yang sama, yaitu:

\[ w_i^{(1)}=\frac{1}{n}, \qquad i=1,2,\ldots,n \]

dengan \(w_i^{(1)}\) merupakan bobot observasi ke-\(i\) pada iterasi pertama.

Pada setiap iterasi dibentuk weak learner \(G_m(x)\). Setelah prediksi dilakukan, dihitung kesalahan klasifikasi terbobot sebagai berikut:

\[ err_m= \frac{ \sum_{i=1}^{n} w_i^{(m)} I\{y_i\neq G_m(x_i)\} }{ \sum_{i=1}^{n}w_i^{(m)} } \]

dengan \(err_m\) merupakan kesalahan klasifikasi terbobot pada learner ke-\(m\), \(w_i^{(m)}\) merupakan bobot observasi ke-\(i\) pada iterasi ke-\(m\), \(G_m(x_i)\) merupakan kelas hasil prediksi learner ke-\(m\), dan \(I\{y_i\neq G_m(x_i)\}\) merupakan fungsi indikator yang bernilai 1 apabila observasi salah diklasifikasikan dan 0 apabila diklasifikasikan dengan benar (Fransiska, 2026).

Observasi yang salah diklasifikasikan kemudian memperoleh bobot yang lebih besar sehingga learner berikutnya memberikan perhatian lebih besar terhadap observasi tersebut. Dengan demikian, setiap learner baru berusaha memperbaiki kesalahan yang masih dilakukan oleh learner sebelumnya (Fransiska, 2026).

Setiap learner diberi bobot berdasarkan performanya. Bobot learner ke-\(m\) dapat dituliskan sebagai:

\[ \alpha_m= \log\left( \frac{1-err_m}{err_m} \right) \]

dengan \(\alpha_m\) merupakan bobot atau tingkat kontribusi learner ke-\(m\) terhadap prediksi akhir.

Prediksi akhir diperoleh melalui weighted voting:

\[ G(x)= sign\left[ \sum_{m=1}^{M} \alpha_mG_m(x) \right] \]

dengan \(M\) merupakan jumlah seluruh weak learner, sedangkan fungsi \(sign(.)\) menentukan kelas akhir berdasarkan tanda dari jumlah voting terbobot tersebut.

Dengan demikian, pada AdaBoost terdapat dua jenis bobot, yaitu bobot observasi yang mengatur perhatian terhadap data latih dan bobot learner yang mengatur kontribusi setiap learner terhadap prediksi akhir (Fransiska, 2026).

BAB III METODE PENELITIAN

3.1 Sumber Data

Data yang digunakan merupakan data sekunder berupa data simulasi Friedman yang dibangkitkan menggunakan fungsi mlbench.friedman1() dari package mlbench pada perangkat lunak R, sebanyak 200 observasi dengan set.seed(234). Karena data dibangkitkan melalui simulasi, data ini tidak berasal dari pengamatan langsung terhadap objek penelitian nyata.

3.2 Variabel Penelitian

Penelitian ini menggunakan variabel y sebagai variabel respons numerik kontinu dan sepuluh variabel numerik sebagai variabel prediktor. Berdasarkan persamaan pembangkit data, hanya lima variabel prediktor pertama yang benar-benar memengaruhi y.

3.3 Langkah-langkah Analisis

Berikut adalah langkah-langkah yang dilakukan dalam analisis:

  1. Memanggil package gbm, mlbench, dan caret.
  2. Membangkitkan data Friedman sebanyak 200 observasi, lalu memeriksa struktur dan ringkasan data.
  3. Membagi data menjadi data training (70%) dan testing (30%) menggunakan createDataPartition() dengan set.seed(234).
  4. Membentuk model Gradient Boosting dengan gbm() menggunakan distribution = "gaussian", n.trees = 1000, interaction.depth = 2, bag.fraction = 1, n.minobsinnode = 5, dan cv.folds = 10 pada tiga nilai shrinkage, yaitu 0,01; 0,05; dan 0,10.
  5. Menentukan jumlah iterasi optimal masing-masing model dengan gbm.perf(method = "cv").
  6. Melakukan prediksi pada data testing menggunakan jumlah iterasi optimal masing-masing model.
  7. Menghitung MSE, RMSE, MAE, dan \(R^2\), lalu membandingkannya dalam bentuk tabel.
  8. Membuat grafik nilai aktual vs prediksi dan grafik residual untuk memeriksa kesesuaian prediksi.
  9. Menghitung variable importance menggunakan summary().
  10. Menentukan model terbaik dan menginterpretasikan hasil.

3.4 Diagram Alir Penelitian

BAB IV HASIL DAN PEMBAHASAN

4.1 Eksplorasi Awal Data

library(gbm)
library(mlbench)
library(caret)

# B1. Membentuk dataset
set.seed(234)
reg.data <- as.data.frame(mlbench.friedman1(200))

# Melihat struktur data
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 ...
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
# Jumlah observasi dan variabel
dim(reg.data)
## [1] 200  11
# Nama variabel prediktor (dipakai pada tahap variable importance)
predictors <- setdiff(names(reg.data), "y")
predictors
##  [1] "x.1"  "x.2"  "x.3"  "x.4"  "x.5"  "x.6"  "x.7"  "x.8"  "x.9"  "x.10"

Data Friedman yang dibangkitkan terdiri dari 200 observasi dan 11 variabel, yaitu satu variabel respons y dan 10 variabel prediktor numerik. Berdasarkan ringkasan data, variabel y memiliki nilai minimum 3.08, rata-rata 14.27, dan maksimum 26.15. Struktur data menunjukkan seluruh variabel bertipe numerik sehingga dapat langsung digunakan pada model regresi.

4.2 Pembagian Data Training dan Testing

# B2. Membagi data training dan testing (70% training dan 30% 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, ]

# Melihat ukuran data
dim(reg.train)
## [1] 140  11
dim(reg.test)
## [1] 60 11

Data dibagi menjadi data training sebanyak 140 observasi (70%) dan data testing sebanyak 60 observasi (30%). Data training digunakan untuk membangun model dan menentukan iterasi optimal melalui cross-validation, sedangkan data testing hanya digunakan untuk mengevaluasi prediksi pada data yang tidak digunakan selama pelatihan.

4.3 Pembentukan Model Gradient Boosting

# B3. Membentuk Gradient Boosting untuk tiga nilai shrinkage
nu <- c(0.01, 0.05, 0.10)
nama.model <- sprintf("nu_%.2f", nu)

model.gbm <- list()
for (i in seq_along(nu)) {
  set.seed(234)
  model.gbm[[nama.model[i]]] <- gbm(
    formula = y ~ .,
    data = reg.train,
    distribution = "gaussian",
    n.trees = 1000,
    interaction.depth = 2,
    shrinkage = nu[i],
    bag.fraction = 1,
    cv.folds = 10,
    n.minobsinnode = 5,
    verbose = FALSE
  )
}

model.gbm[[1]]
## gbm(formula = y ~ ., distribution = "gaussian", data = reg.train, 
##     n.trees = 1000, interaction.depth = 2, n.minobsinnode = 5, 
##     shrinkage = nu[i], bag.fraction = 1, cv.folds = 10, verbose = FALSE)
## A gradient boosted model with gaussian loss function.
## 1000 iterations were performed.
## The best cross-validation iteration was 999.
## There were 10 predictors of which 9 had non-zero influence.
model.gbm[[2]]
## gbm(formula = y ~ ., distribution = "gaussian", data = reg.train, 
##     n.trees = 1000, interaction.depth = 2, n.minobsinnode = 5, 
##     shrinkage = nu[i], bag.fraction = 1, cv.folds = 10, verbose = FALSE)
## A gradient boosted model with gaussian loss function.
## 1000 iterations were performed.
## The best cross-validation iteration was 458.
## There were 10 predictors of which 10 had non-zero influence.
model.gbm[[3]]
## gbm(formula = y ~ ., distribution = "gaussian", data = reg.train, 
##     n.trees = 1000, interaction.depth = 2, n.minobsinnode = 5, 
##     shrinkage = nu[i], bag.fraction = 1, cv.folds = 10, verbose = FALSE)
## A gradient boosted model with gaussian loss function.
## 1000 iterations were performed.
## The best cross-validation iteration was 212.
## There were 10 predictors of which 10 had non-zero influence.

Tiga model Gradient Boosting dibentuk dengan parameter yang sama, yaitu distribution = "gaussian" (kerugian kuadrat untuk regresi), 1000 pohon, interaction.depth = 2, bag.fraction = 1 (tanpa subsampling), n.minobsinnode = 5, dan cross-validation 10 lipatan. Satu-satunya parameter yang dibedakan adalah shrinkage, yaitu 0.01; 0.05; 0.10, sehingga perbedaan hasil antarmodel dapat dikaitkan dengan perbedaan learning rate. Ringkasan setiap model di atas memuat jumlah iterasi yang dibangun serta jumlah iterasi terbaik berdasarkan cross-validation.

4.4 Penentuan Jumlah Iterasi Optimal dengan Cross-Validation

# B4. Menentukan jumlah iterasi optimal
par(mfrow = c(1, 3))
best.iter <- numeric(length(nu))
for (i in seq_along(nu)) {
  best.iter[i] <- gbm.perf(model.gbm[[i]], method = "cv", plot.it = TRUE)
  title(main = sprintf("Shrinkage = %.2f", nu[i]))
}

par(mfrow = c(1, 1))

# Ringkasan iterasi optimal dan kesalahan cross-validation
cv.min <- sapply(model.gbm, function(m) min(m$cv.error))
tabel.iter <- data.frame(
  Shrinkage = nu,
  Iterasi_Optimal = best.iter,
  CV_MSE_Minimum = round(cv.min, 4),
  row.names = NULL
)
tabel.iter
##   Shrinkage Iterasi_Optimal CV_MSE_Minimum
## 1      0.01             999         4.3015
## 2      0.05             458         4.0046
## 3      0.10             212         3.9630
# Kalimat interpretasi (dibangun dari hasil)
kal.iter <- paste(sprintf("%d iterasi pada shrinkage %.2f", best.iter, nu), collapse = ", ")

pola.iter <- if (all(diff(best.iter) < 0)) {
  "semakin besar nilai shrinkage, semakin sedikit iterasi optimal yang dibutuhkan"
} else {
  "jumlah iterasi optimal tidak menurun secara konsisten seiring bertambahnya shrinkage"
}

batas.iter <- if (any(best.iter >= 1000)) {
  paste0("Pada shrinkage ", paste(sprintf("%.2f", nu[best.iter >= 1000]), collapse = " dan "),
         ", iterasi optimal berada pada batas n.trees = 1000 sehingga model tersebut kemungkinan belum mencapai titik optimum dan membutuhkan pohon yang lebih banyak.")
} else {
  "Seluruh iterasi optimal berada di bawah batas n.trees = 1000 sehingga jumlah pohon yang disediakan sudah memadai."
}

Pada setiap grafik, kurva hitam menunjukkan kesalahan pada data training yang terus menurun, sedangkan kurva hijau menunjukkan kesalahan hasil cross-validation; garis putus-putus biru menandai iterasi dengan kesalahan cross-validation terkecil. Berdasarkan hasil di atas, jumlah iterasi optimal masing-masing model adalah 999 iterasi pada shrinkage 0.01, 458 iterasi pada shrinkage 0.05, 212 iterasi pada shrinkage 0.10. Hasil ini menunjukkan bahwa semakin besar nilai shrinkage, semakin sedikit iterasi optimal yang dibutuhkan, sesuai dengan prinsip bahwa learning rate yang kecil membuat pembelajaran lebih lambat sehingga membutuhkan lebih banyak pohon (Boehmke & Greenwell, 2020). Seluruh iterasi optimal berada di bawah batas n.trees = 1000 sehingga jumlah pohon yang disediakan sudah memadai.

4.5 Prediksi Data Testing

# B5. Prediksi data testing dengan iterasi optimal masing-masing model
actual <- reg.test$y

pred.reg <- list()
for (i in seq_along(nu)) {
  pred.reg[[nama.model[i]]] <- as.numeric(
    predict(model.gbm[[i]], newdata = reg.test,
            n.trees = best.iter[i], type = "response")
  )
}

# Menyimpan hasil (contoh: shrinkage 0.05)
hasil.reg <- data.frame(
  Aktual = actual,
  Prediksi = pred.reg[["nu_0.05"]],
  Residual = actual - pred.reg[["nu_0.05"]]
)
head(hasil.reg, 10)
##       Aktual Prediksi   Residual
## 1  10.232309 10.46850 -0.2361895
## 2  11.845301 11.01535  0.8299476
## 3  10.335689 11.91667 -1.5809826
## 4  16.727262 15.48904  1.2382190
## 5  25.077119 23.78820  1.2889164
## 6  15.446886 16.16480 -0.7179124
## 7  15.642915 14.65071  0.9922070
## 8   7.110835 11.97079 -4.8599552
## 9  13.351277 15.78174 -2.4304647
## 10 12.871960 14.64838 -1.7764246

Prediksi dilakukan pada data testing dengan menggunakan jumlah iterasi optimal masing-masing model, bukan seluruh 1000 pohon. Tabel di atas menampilkan contoh sepuluh observasi pertama untuk model dengan shrinkage 0,05, yaitu nilai aktual, nilai prediksi, dan residual (aktual dikurangi prediksi). Residual positif berarti model memprediksi lebih rendah dari nilai aktual, sedangkan residual negatif berarti model memprediksi lebih tinggi.

4.6 Evaluasi dan Perbandingan Performa Model

# B6. Evaluasi model regresi
evaluasi <- function(actual, pred) {
  MSE  <- mean((actual - pred)^2)
  RMSE <- sqrt(MSE)
  MAE  <- mean(abs(actual - pred))
  R2   <- 1 - sum((actual - pred)^2) / sum((actual - mean(actual))^2)
  c(MSE = MSE, RMSE = RMSE, MAE = MAE, R_Square = R2)
}

evaluasi.reg <- data.frame(
  Shrinkage = nu,
  Iterasi_Optimal = best.iter,
  t(sapply(pred.reg, function(p) evaluasi(actual, p))),
  row.names = NULL
)
round(evaluasi.reg, 4)
##   Shrinkage Iterasi_Optimal    MSE   RMSE    MAE R_Square
## 1      0.01             999 4.4962 2.1204 1.6464   0.8124
## 2      0.05             458 4.2639 2.0649 1.6008   0.8221
## 3      0.10             212 4.0312 2.0078 1.5579   0.8318
# Menentukan model terbaik
ib <- which.min(evaluasi.reg$MSE)
konsisten <- all(c(which.min(evaluasi.reg$RMSE),
                   which.min(evaluasi.reg$MAE),
                   which.max(evaluasi.reg$R_Square)) == ib)

iw <- which.max(evaluasi.reg$MSE)
selisih.mse <- evaluasi.reg$MSE[iw] - evaluasi.reg$MSE[ib]
persen.mse  <- 100 * selisih.mse / evaluasi.reg$MSE[iw]

kal.konsisten <- if (konsisten) {
  "Keempat metrik memberikan kesimpulan yang sama, yaitu model dengan MSE terkecil juga memiliki RMSE dan MAE terkecil serta R-Square terbesar."
} else {
  "Keempat metrik tidak sepenuhnya menunjuk model yang sama sehingga pemilihan model terbaik perlu mempertimbangkan metrik yang paling sesuai dengan tujuan analisis."
}

Berdasarkan tabel evaluasi, model dengan performa terbaik adalah model dengan shrinkage 0.10 yang menggunakan 212 iterasi, dengan MSE 4.0312, RMSE 2.0078, MAE 1.5579, dan R-Square 0.8318. Keempat metrik memberikan kesimpulan yang sama, yaitu model dengan MSE terkecil juga memiliki RMSE dan MAE terkecil serta R-Square terbesar. Model dengan shrinkage 0.01 memiliki MSE terbesar, yaitu 4.4962, sehingga MSE model terbaik lebih rendah sebesar 0.465 atau sekitar 10.3% dibandingkan model tersebut.

Nilai R-Square 0.8318 berarti model terbaik mampu menjelaskan sekitar 83.2% variasi nilai y pada data testing. Nilai RMSE 2.0078 berarti rata-rata kesalahan prediksi berada pada kisaran 2.01 satuan y, dan nilai MAE 1.5579 menunjukkan rata-rata selisih absolut antara nilai aktual dan prediksi. Sebagai pembanding, galat acak \(\varepsilon\) pada data Friedman memiliki varians 1, sehingga MSE yang mendekati 1 menunjukkan bahwa model sudah mendekati batas kesalahan yang tidak dapat dijelaskan oleh prediktor; MSE model terbaik adalah 4.03. Karena data testing hanya berisi 60 observasi, perbedaan antarmodel yang kecil perlu ditafsirkan dengan hati-hati.

4.7 Grafik Nilai Aktual dan Prediksi

# B7. Plot nilai aktual dan prediksi
par(mfrow = c(1, 3))
for (i in seq_along(nu)) {
  plot(actual, pred.reg[[i]], pch = 19,
       xlab = "Nilai Aktual", ylab = "Nilai Prediksi",
       main = sprintf("Aktual vs Prediksi\nShrinkage = %.2f", nu[i]))
  abline(a = 0, b = 1, lty = 2, lwd = 2)
}

par(mfrow = c(1, 1))

Garis putus-putus pada grafik menunjukkan kondisi prediksi sempurna (nilai prediksi sama dengan nilai aktual). Semakin dekat titik-titik ke garis tersebut, semakin akurat prediksi model. Apabila titik-titik pada suatu model mengikuti arah garis diagonal, berarti model tersebut mampu menangkap pola hubungan antara prediktor dan respons. Berdasarkan Subbab 4.6, model dengan MSE terkecil adalah model shrinkage 0.10, sehingga secara kuantitatif model ini memiliki selisih antara nilai prediksi dan aktual yang paling kecil; bandingkan dengan sebaran titik pada dua model lainnya.

4.8 Grafik Residual

# B8. Plot residual
par(mfrow = c(1, 3))
for (i in seq_along(nu)) {
  residual.reg <- actual - pred.reg[[i]]
  plot(pred.reg[[i]], residual.reg, pch = 19,
       xlab = "Nilai Prediksi", ylab = "Residual",
       main = sprintf("Residual Plot\nShrinkage = %.2f", nu[i]))
  abline(h = 0, lty = 2, lwd = 2)
}

par(mfrow = c(1, 1))

Pada grafik residual yang baik, titik tersebar acak di sekitar garis nol tanpa pola yang jelas, karena pola tertentu menandakan adanya informasi yang belum ditangkap model. Penyebaran residual pada ketiga model dapat dibandingkan secara visual: residual yang berkumpul lebih dekat ke garis nol menunjukkan kesalahan prediksi yang lebih kecil, sejalan dengan nilai RMSE dan MAE pada Subbab 4.6.

4.9 Variable Importance

# B9. Variable Importance (pada iterasi optimal masing-masing model)
imp.tab <- data.frame(Variabel = predictors)
for (i in seq_along(nu)) {
  s <- summary(model.gbm[[i]], n.trees = best.iter[i], plotit = FALSE)
  imp.tab[[nama.model[i]]] <- s$rel.inf[match(imp.tab$Variabel, s$var)]
}
imp.tab[, -1] <- round(imp.tab[, -1], 2)
imp.tab
##    Variabel nu_0.01 nu_0.05 nu_0.10
## 1       x.1   28.79   28.47   28.25
## 2       x.2   14.14   14.11   13.84
## 3       x.3   12.12   12.14   11.73
## 4       x.4   38.96   38.24   38.47
## 5       x.5    5.01    4.83    5.45
## 6       x.6    0.46    0.97    1.02
## 7       x.7    0.25    0.48    0.42
## 8       x.8    0.00    0.18    0.15
## 9       x.9    0.13    0.22    0.26
## 10     x.10    0.16    0.35    0.40
# Plot variable importance
par(mfrow = c(1, 3))
for (i in seq_along(nu)) {
  barplot(imp.tab[[nama.model[i]]], names.arg = imp.tab$Variabel,
          las = 2, ylim = c(0, max(imp.tab[, -1])),
          main = sprintf("Variable Importance\nShrinkage = %.2f", nu[i]),
          ylab = "Relative Influence")
}

par(mfrow = c(1, 1))

# Kontribusi lima prediktor pertama (variabel yang benar-benar berpengaruh)
inf5 <- sum(imp.tab[[nama.model[ib]]][1:5])
urut <- imp.tab[order(-imp.tab[[nama.model[ib]]]), ]

Pada model terbaik (shrinkage 0.10), variabel dengan relative influence terbesar adalah x.4 (38.47%), diikuti x.1 (28.25%) dan x.2 (13.84%). Menurut persamaan pembangkit data, hanya lima variabel pertama (x.1, x.2, x.3, x.4, x.5) yang memengaruhi y. Pada model terbaik, kelima variabel tersebut menyumbang 97.7% dari total pengaruh, sedangkan lima variabel noise menyumbang sisanya, yaitu 2.3%. Hal ini menunjukkan bahwa model berhasil membedakan variabel yang berpengaruh dari variabel noise.

4.10 Pembahasan Umum

Perbandingan ketiga nilai shrinkage menunjukkan bahwa jumlah iterasi optimal ditentukan oleh learning rate: 999 iterasi pada shrinkage 0.01, 458 iterasi pada shrinkage 0.05, 212 iterasi pada shrinkage 0.10. Model terbaik berdasarkan MSE, RMSE, MAE, dan R-Square adalah model dengan shrinkage 0.10. Seluruh iterasi optimal berada di bawah batas n.trees = 1000 sehingga jumlah pohon yang disediakan sudah memadai. Hasil ini sejalan dengan landasan teori bahwa shrinkage dan jumlah pohon saling berkaitan, sehingga learning rate yang kecil tidak otomatis menghasilkan model terbaik bila jumlah pohon yang tersedia terbatas (James dkk., 2021; Boehmke & Greenwell, 2020).

BAB V KESIMPULAN DAN SARAN

5.1 Kesimpulan

Gradient Boosting merupakan metode ensemble yang membangun model secara berurutan, dengan setiap pohon baru dilatih untuk memperbaiki kesalahan (pseudo-residual) model sebelumnya, dan kontribusi tiap pohon diatur oleh learning rate (shrinkage). Berbeda dengan bagging, boosting dapat mengalami overfitting sehingga jumlah iterasi perlu dipilih secara tepat.

Implementasi dilakukan dengan fungsi gbm() pada data Friedman sebanyak 200 observasi yang dibagi menjadi 140 data training dan 60 data testing. Jumlah iterasi optimal ditentukan dengan cross-validation 10 lipatan menggunakan gbm.perf(method = "cv"), dengan hasil 999 iterasi pada shrinkage 0.01, 458 iterasi pada shrinkage 0.05, 212 iterasi pada shrinkage 0.10.

Berdasarkan evaluasi pada data testing, model terbaik adalah model dengan shrinkage 0.10 dengan MSE 4.0312, RMSE 2.0078, MAE 1.5579, dan R-Square 0.8318. Keempat metrik memberikan kesimpulan yang sama, yaitu model dengan MSE terkecil juga memiliki RMSE dan MAE terkecil serta R-Square terbesar. Analisis variable importance pada model terbaik menunjukkan bahwa lima variabel pertama menyumbang 97.7% dari total pengaruh.

5.2 Saran

Praktikan dapat melakukan pembelajaran lebih lanjut mengenai Gradient Boosting dengan R, misalnya dengan menambah jumlah pohon (n.trees) pada shrinkage yang kecil, menyetel interaction.depth dan bag.fraction, serta membandingkan dengan implementasi lain seperti XGBoost atau LightGBM (Bentéjac dkk., 2021). Dalam penulisan laporan praktikan juga diharapkan untuk selalu teliti dan memperhatikan tata cara penulisan yang baik.

DAFTAR PUSTAKA

Firmansyah, H., & Abidin, Z. (2022). Penerapan algoritma Gradient Boosted Decision Trees pada Adaboost untuk klasifikasi status desa. Jurnal Ilmiah JIAII: Jurnal Informatika UPS, 1(1), 27–35.

Fransiska, H. (2026). Modul Praktikum Machine Learning dan Model Prediction. Universitas Bengkulu: Bengkulu.

Majid, A. M., & Miharja, M. N. D. (2022). Penerapan metode discretization dan Adaboost untuk meningkatkan akurasi algoritma klasifikasi dalam memprediksi penyakit jantung. Indonesian Journal of Business Intelligence, 5(2), 70.

Novianti, N., Zarlis, M., & Sihombing, P. (2022). Penerapan algoritma Adaboost untuk peningkatan kinerja klasifikasi data mining pada imbalance dataset diabetes. Jurnal Media Informatika Budidarma, 6(2), 1200–1206.