R: menerapkan algoritma peningkatan gradien saya sendiri

10

Saya mencoba untuk menulis algoritma meningkatkan gradien saya sendiri. Saya mengerti ada paket-paket yang ada seperti gbmdan xgboost,tetapi saya ingin mengerti bagaimana algoritma bekerja dengan menulis sendiri.

Saya menggunakan iriskumpulan data, dan hasil saya Sepal.Length(berkelanjutan). Fungsi kerugian saya adalah mean(1/2*(y-yhat)^2)(pada dasarnya kesalahan kuadrat rata-rata dengan 1/2 di depan), jadi gradien yang sesuai saya hanya residual y - yhat. Saya menginisialisasi prediksi pada 0.

library(rpart)
data(iris)

#Define gradient
grad.fun <- function(y, yhat) {return(y - yhat)}

mod <- list()

grad_boost <- function(data, learning.rate, M, grad.fun) {
  # Initialize fit to be 0
  fit <- rep(0, nrow(data))
  grad <- grad.fun(y = data$Sepal.Length, yhat = fit)

  # Initialize model
  mod[[1]] <- fit

  # Loop over a total of M iterations
  for(i in 1:M){

    # Fit base learner (tree) to the gradient
    tmp <- data$Sepal.Length
    data$Sepal.Length <- grad
    base_learner <- rpart(Sepal.Length ~ ., data = data, control = ("maxdepth = 2"))
    data$Sepal.Length <- tmp

    # Fitted values by fitting current model
    fit <- fit + learning.rate * as.vector(predict(base_learner, newdata = data))

    # Update gradient
    grad <- grad.fun(y = data$Sepal.Length, yhat = fit)

    # Store current model (index is i + 1 because i = 1 contain the initialized estiamtes)
    mod[[i + 1]] <- base_learner

  }
  return(mod)
}

Dengan ini, saya membagi irisset data menjadi pelatihan dan menguji set data dan sesuai dengan model saya.

train.dat <- iris[1:100, ]
test.dat <- iris[101:150, ]
learning.rate <- 0.001
M = 1000
my.model <- grad_boost(data = train.dat, learning.rate = learning.rate, M = M, grad.fun = grad.fun)

Sekarang saya menghitung nilai prediksi dari my.model. Sebab my.model, nilai yang dipasang adalah 0 (vector of initial estimates) + learning.rate * predictions from tree 1 + learning rate * predictions from tree 2 + ... + learning.rate * predictions from tree M.

yhats.mymod <- apply(sapply(2:length(my.model), function(x) learning.rate * predict(my.model[[x]], newdata = test.dat)), 1, sum)

# Calculate RMSE
> sqrt(mean((test.dat$Sepal.Length - yhats.mymod)^2))
[1] 2.612972

Saya punya beberapa pertanyaan

  1. Apakah algoritma peningkatan gradien saya terlihat benar?
  2. Apakah saya menghitung nilai prediksi yhats.mymoddengan benar?
YQW
sumber

Jawaban:

0
  1. Ya ini terlihat benar. Pada setiap langkah Anda cocok dengan residu psuedo, yang dihitung sebagai turunan dari kerugian sehubungan dengan fit. Anda telah mendapatkan gradien ini dengan benar pada awal pertanyaan Anda, dan bahkan repot-repot untuk mendapatkan faktor 2 dengan benar.
  2. Ini juga terlihat benar. Anda menjumlahkan seluruh model, terbebani oleh tingkat pembelajaran, sama seperti yang Anda lakukan selama pelatihan.

Tetapi untuk mengatasi sesuatu yang tidak diminta, saya perhatikan bahwa pengaturan pelatihan Anda memiliki beberapa kebiasaan.

  • The irisdataset dibagi rata antara 3 spesies (Setosa, versicolor, virginica) dan ini adalah yang berdekatan dalam data. Data pelatihan Anda memiliki semua setosa dan versicolor, sedangkan set tes memiliki semua contoh virginica. Tidak ada tumpang tindih, yang akan menyebabkan masalah out-of-sample. Lebih baik menyeimbangkan pelatihan Anda dan set tes untuk menghindari ini.
  • Kombinasi angka belajar dan jumlah model terlihat terlalu rendah bagi saya. Cocok menyatu sebagai (1-lr)^n. Dengan lr = 1e-3dan n = 1000Anda hanya bisa memodelkan 63,2% dari besarnya data. Artinya, bahkan jika setiap model memprediksi setiap sampel dengan benar, Anda akan memperkirakan 63,2% dari nilai yang benar. Menginisialisasi kecocokan dengan rata-rata, alih-alih 0s, akan membantu sejak itu efeknya adalah regresi terhadap rata-rata, bukan hanya hambatan.
mcskinner
sumber
Terima kasih atas komentar anda Bisakah Anda memperluas mengapa "cocok konvergen sebagai (1-lr) ^ n"? Apa alasan di balik ini?
YQW
Itu karena fit <- fit + learning.rate * prediction, di mana predictionresidual target - fit. Jadi fit <- fit + lr * (target - fit), atau fit <- fit * (1 - lr) + target * lr. Ini hanya rata-rata bergerak eksponensial. Per Wikipedia , "bobot dihilangkan dengan berhenti setelah istilah k (1-α)^kkeluar dari berat total" ( αadalah tingkat belajar dan ksedang n). Anda mulai dengan perkiraan 0 bukannya rata-rata, sehingga bobot yang dihilangkan ini langsung keluar dari prediksi.
mcskinner