# ============================================================
# ANALISIS GRADIENT BOOSTING REGRESSION
# DENGAN PENENTUAN JUMLAH POHON OPTIMAL
# ============================================================
# ============================================================
# 1. MEMANGGIL PACKAGE
# ============================================================
library(gbm)
## Loaded gbm 2.3.1
## This version of gbm is no longer under development. Consider transitioning to gbm3, https://github.com/gbm-developers/gbm3
library(ggplot2)
# ============================================================
# 2. MEMBACA DATA
# ============================================================
train <- read.csv(
"D:/STATISTIKA/SEM 5/Modern Prediksi dan Machine Learning/PEkan 9-18/Studi Kasus pekan 11/train.csv",
stringsAsFactors = FALSE
)
test <- read.csv(
"D:/STATISTIKA/SEM 5/Modern Prediksi dan Machine Learning/PEkan 9-18/Studi Kasus pekan 11/test.csv",
stringsAsFactors = FALSE
)
cat("Jumlah data training:", nrow(train), "\n")
## Jumlah data training: 51879
cat("Jumlah data testing:", nrow(test), "\n")
## Jumlah data testing: 22232
# Memastikan variabel respons tersedia
if (!"price" %in% names(train)) {
stop("Variabel price tidak ditemukan pada data training.")
}
# Mengubah price menjadi numerik
train$price <- as.numeric(
gsub("[^0-9.]", "", as.character(train$price))
)
# Menghapus harga yang tidak valid
train <- train[
is.finite(train$price) & train$price >= 0,
,
drop = FALSE
]
# Menyimpan ID data testing
if ("id" %in% names(test)) {
id_test <- test$id
} else {
id_test <- seq_len(nrow(test))
}
# ============================================================
# 3. MEMILIH VARIABEL PENELITIAN
# ============================================================
# Variabel respons
variabel_Y <- "price"
# 12 variabel prediktor sesuai tabel penelitian
variabel_X <- c(
"property_type",
"room_type",
"accommodates",
"bedrooms",
"bathrooms",
"beds",
"number_of_reviews",
"review_scores_rating",
"host_response_rate",
"cancellation_policy",
"instant_bookable",
"cleaning_fee"
)
# Memeriksa variabel pada data training
variabel_tidak_ada <- setdiff(
c(variabel_Y, variabel_X),
names(train)
)
if (length(variabel_tidak_ada) > 0) {
stop(
paste(
"Variabel tidak tersedia pada training:",
paste(variabel_tidak_ada, collapse = ", ")
)
)
}
# Memeriksa variabel pada data testing
variabel_test_tidak_ada <- setdiff(
variabel_X,
names(test)
)
if (length(variabel_test_tidak_ada) > 0) {
stop(
paste(
"Variabel tidak tersedia pada testing:",
paste(variabel_test_tidak_ada, collapse = ", ")
)
)
}
# Mengambil hanya variabel penelitian
X_train_raw <- train[, variabel_X, drop = FALSE]
X_test_raw <- test[, variabel_X, drop = FALSE]
n_train <- nrow(X_train_raw)
cat("\nJUMLAH VARIABEL PREDIKTOR:", length(variabel_X), "\n")
##
## JUMLAH VARIABEL PREDIKTOR: 12
print(variabel_X)
## [1] "property_type" "room_type" "accommodates"
## [4] "bedrooms" "bathrooms" "beds"
## [7] "number_of_reviews" "review_scores_rating" "host_response_rate"
## [10] "cancellation_policy" "instant_bookable" "cleaning_fee"
# ============================================================
# 4. MENGGABUNGKAN DATA TRAINING DAN TESTING
# ============================================================
X_gabungan <- rbind(
X_train_raw,
X_test_raw
)
# ============================================================
# 5. PREPROCESSING VARIABEL
# ============================================================
# Mengubah host_response_rate menjadi numerik
X_gabungan$host_response_rate <- as.numeric(
gsub(
"%",
"",
as.character(X_gabungan$host_response_rate)
)
)
# Mengubah cleaning_fee menjadi numerik
X_gabungan$cleaning_fee <- as.numeric(
gsub(
"[$,]",
"",
as.character(X_gabungan$cleaning_fee)
)
)
## Warning: NAs introduced by coercion
# Variabel numerik
variabel_numerik <- c(
"accommodates",
"bedrooms",
"bathrooms",
"beds",
"number_of_reviews",
"review_scores_rating",
"host_response_rate",
"cleaning_fee"
)
# Variabel kategorik
variabel_kategorik <- c(
"property_type",
"room_type",
"cancellation_policy",
"instant_bookable"
)
# Memastikan tipe data numerik
for (v in variabel_numerik) {
X_gabungan[[v]] <- as.numeric(
as.character(X_gabungan[[v]])
)
}
# Memastikan tipe data kategorik
for (v in variabel_kategorik) {
X_gabungan[[v]] <- as.factor(
as.character(X_gabungan[[v]])
)
}
# ============================================================
# 6. MENGATASI MISSING VALUE
# ============================================================
for (j in seq_along(X_gabungan)) {
kolom <- X_gabungan[[j]]
if (is.numeric(kolom)) {
kolom[!is.finite(kolom)] <- NA
# Median dihitung dari data training
median_train <- median(
kolom[seq_len(n_train)],
na.rm = TRUE
)
if (!is.finite(median_train)) {
median_train <- 0
}
kolom[is.na(kolom)] <- median_train
X_gabungan[[j]] <- kolom
} else {
kolom <- as.character(kolom)
kolom[
is.na(kolom) |
trimws(kolom) == ""
] <- "Tidak diketahui"
X_gabungan[[j]] <- as.factor(kolom)
}
}
# ============================================================
# 7. MENGUBAH VARIABEL KATEGORIK MENJADI DUMMY
# ============================================================
X_all <- model.matrix(
~ . - 1,
data = X_gabungan
)
colnames(X_all) <- make.names(
colnames(X_all),
unique = TRUE
)
X_all[!is.finite(X_all)] <- 0
# Memisahkan data training dan testing
X_train_all <- X_all[
seq_len(n_train),
,
drop = FALSE
]
X_test_all <- X_all[
(n_train + 1):nrow(X_all),
,
drop = FALSE
]
cat("\nJUMLAH PREDIKTOR SETELAH DUMMY:",
ncol(X_train_all), "\n")
##
## JUMLAH PREDIKTOR SETELAH DUMMY: 50
cat("\nDAFTAR PREDIKTOR SETELAH DUMMY:\n")
##
## DAFTAR PREDIKTOR SETELAH DUMMY:
print(colnames(X_train_all))
## [1] "property_typeApartment" "property_typeBed...Breakfast"
## [3] "property_typeBoat" "property_typeBoutique.hotel"
## [5] "property_typeBungalow" "property_typeCabin"
## [7] "property_typeCamper.RV" "property_typeCasa.particular"
## [9] "property_typeCastle" "property_typeCave"
## [11] "property_typeChalet" "property_typeCondominium"
## [13] "property_typeDorm" "property_typeEarth.House"
## [15] "property_typeGuest.suite" "property_typeGuesthouse"
## [17] "property_typeHostel" "property_typeHouse"
## [19] "property_typeHut" "property_typeIn.law"
## [21] "property_typeIsland" "property_typeLighthouse"
## [23] "property_typeLoft" "property_typeOther"
## [25] "property_typeParking.Space" "property_typeServiced.apartment"
## [27] "property_typeTent" "property_typeTimeshare"
## [29] "property_typeTipi" "property_typeTownhouse"
## [31] "property_typeTrain" "property_typeTreehouse"
## [33] "property_typeVacation.home" "property_typeVilla"
## [35] "property_typeYurt" "room_typePrivate.room"
## [37] "room_typeShared.room" "accommodates"
## [39] "bedrooms" "bathrooms"
## [41] "beds" "number_of_reviews"
## [43] "review_scores_rating" "host_response_rate"
## [45] "cancellation_policymoderate" "cancellation_policystrict"
## [47] "cancellation_policysuper_strict_30" "cancellation_policysuper_strict_60"
## [49] "instant_bookablet" "cleaning_fee"
# ============================================================
# 8. TRANSFORMASI VARIABEL RESPONS
# ============================================================
# Transformasi logaritma
y_all <- log1p(train$price)
# ============================================================
# 9. MEMBAGI DATA TRAINING DAN VALIDASI
# ============================================================
set.seed(123)
n <- nrow(X_train_all)
indeks_train <- sample(
seq_len(n),
size = floor(0.8 * n)
)
indeks_valid <- setdiff(
seq_len(n),
indeks_train
)
# Data training
X_train <- X_train_all[
indeks_train,
,
drop = FALSE
]
y_train <- y_all[indeks_train]
# Data validasi
X_valid <- X_train_all[
indeks_valid,
,
drop = FALSE
]
y_valid <- y_all[indeks_valid]
# Nilai aktual skala asli
actual <- train$price[indeks_valid]
# Membentuk data frame untuk gbm
data_gb <- data.frame(
y = as.numeric(y_train),
X_train,
check.names = TRUE
)
data_valid_gb <- as.data.frame(
X_valid,
check.names = TRUE
)
cat("\nJumlah data training:", nrow(data_gb), "\n")
##
## Jumlah data training: 41503
cat("Jumlah data validasi:", nrow(data_valid_gb), "\n")
## Jumlah data validasi: 10376
# ============================================================
# 10. PEMODELAN GRADIENT BOOSTING
# DENGAN CROSS VALIDATION 5-FOLD
# ============================================================
set.seed(123)
model_gb <- gbm(
formula = y ~ .,
distribution = "gaussian",
data = data_gb,
# Batas maksimum pencarian
n.trees = 1000,
# Parameter model
interaction.depth = 3,
n.minobsinnode = 2,
shrinkage = 0.05,
bag.fraction = 0.8,
# Cross Validation
cv.folds = 5,
# Menggunakan satu core
n.cores = 1,
verbose = FALSE
)
## CV: 1
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 22: property_typeLighthouse has no variation.
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 50: cleaning_fee has no variation.
## CV: 2
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 22: property_typeLighthouse has no variation.
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 50: cleaning_fee has no variation.
## CV: 3
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 22: property_typeLighthouse has no variation.
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 50: cleaning_fee has no variation.
## CV: 4
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 22: property_typeLighthouse has no variation.
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 50: cleaning_fee has no variation.
## CV: 5
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 22: property_typeLighthouse has no variation.
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 50: cleaning_fee has no variation.
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 22: property_typeLighthouse has no variation.
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 50: cleaning_fee has no variation.
# ============================================================
# 11. MENENTUKAN JUMLAH POHON OPTIMAL
# ============================================================
jumlah_pohon_optimal <- gbm.perf(
model_gb,
method = "cv",
plot.it = TRUE
)

cat("\n====================================\n")
##
## ====================================
cat("HASIL PENCARIAN POHON OPTIMAL\n")
## HASIL PENCARIAN POHON OPTIMAL
cat("====================================\n")
## ====================================
cat(
"Jumlah pohon optimal:",
jumlah_pohon_optimal,
"\n"
)
## Jumlah pohon optimal: 992
# Memeriksa apakah pencarian mencapai batas
if (jumlah_pohon_optimal >= 1000) {
warning(
"Jumlah pohon optimal mencapai batas maksimum 1000. ",
"Pencarian perlu diperluas."
)
}
# ============================================================
# 12. PREDIKSI DATA VALIDASI
# MENGGUNAKAN POHON OPTIMAL
# ============================================================
pred_valid_log <- predict(
model_gb,
newdata = data_valid_gb,
n.trees = jumlah_pohon_optimal,
type = "response"
)
# Mengembalikan ke skala asli
pred_valid <- expm1(pred_valid_log)
# ============================================================
# 13. EVALUASI MODEL
# ============================================================
# RMSE
RMSE <- sqrt(
mean((actual - pred_valid)^2)
)
# MAE
MAE <- mean(
abs(actual - pred_valid)
)
# R-Squared
R2 <- 1 -
sum((actual - pred_valid)^2) /
sum((actual - mean(actual))^2)
# Tabel evaluasi
hasil_evaluasi <- data.frame(
Model = "Gradient Boosting",
Jumlah_Pohon_Optimal = jumlah_pohon_optimal,
RMSE = RMSE,
MAE = MAE,
R2 = R2
)
cat("\nHASIL EVALUASI MODEL\n")
##
## HASIL EVALUASI MODEL
print(hasil_evaluasi)
## Model Jumlah_Pohon_Optimal RMSE MAE R2
## 1 Gradient Boosting 992 125.6057 60.14508 0.4426829
# ============================================================
# 14. VISUALISASI AKTUAL DAN PREDIKSI
# ============================================================
data_plot <- data.frame(
Aktual = actual,
Prediksi = pred_valid
)
ggplot(
data_plot,
aes(x = Aktual, y = Prediksi)
) +
geom_point(alpha = 0.4) +
geom_abline(
intercept = 0,
slope = 1,
linetype = "dashed"
) +
labs(
title = "Aktual vs Prediksi Gradient Boosting",
x = "Harga Aktual",
y = "Harga Prediksi"
) +
theme_minimal()

# ============================================================
# 15. VARIABLE RELATIVE INFLUENCE
# ============================================================
importance_gb <- summary(
model_gb,
n.trees = jumlah_pohon_optimal,
plotit = TRUE
)

cat("\nRELATIVE INFLUENCE\n")
##
## RELATIVE INFLUENCE
print(importance_gb)
## var
## room_typePrivate.room room_typePrivate.room
## bedrooms bedrooms
## accommodates accommodates
## room_typeShared.room room_typeShared.room
## bathrooms bathrooms
## number_of_reviews number_of_reviews
## review_scores_rating review_scores_rating
## beds beds
## property_typeCondominium property_typeCondominium
## host_response_rate host_response_rate
## cancellation_policystrict cancellation_policystrict
## property_typeHouse property_typeHouse
## instant_bookablet instant_bookablet
## property_typeLoft property_typeLoft
## property_typeTimeshare property_typeTimeshare
## property_typeOther property_typeOther
## property_typeApartment property_typeApartment
## cancellation_policymoderate cancellation_policymoderate
## property_typeBed...Breakfast property_typeBed...Breakfast
## cancellation_policysuper_strict_30 cancellation_policysuper_strict_30
## property_typeDorm property_typeDorm
## property_typeGuesthouse property_typeGuesthouse
## property_typeBoutique.hotel property_typeBoutique.hotel
## property_typeHostel property_typeHostel
## property_typeTownhouse property_typeTownhouse
## property_typeVilla property_typeVilla
## cancellation_policysuper_strict_60 cancellation_policysuper_strict_60
## property_typeBungalow property_typeBungalow
## property_typeCamper.RV property_typeCamper.RV
## property_typeHut property_typeHut
## property_typeCastle property_typeCastle
## property_typeBoat property_typeBoat
## property_typeTent property_typeTent
## property_typeServiced.apartment property_typeServiced.apartment
## property_typeYurt property_typeYurt
## property_typeCabin property_typeCabin
## property_typeGuest.suite property_typeGuest.suite
## property_typeTipi property_typeTipi
## property_typeIn.law property_typeIn.law
## property_typeCasa.particular property_typeCasa.particular
## property_typeCave property_typeCave
## property_typeChalet property_typeChalet
## property_typeEarth.House property_typeEarth.House
## property_typeIsland property_typeIsland
## property_typeLighthouse property_typeLighthouse
## property_typeParking.Space property_typeParking.Space
## property_typeTrain property_typeTrain
## property_typeTreehouse property_typeTreehouse
## property_typeVacation.home property_typeVacation.home
## cleaning_fee cleaning_fee
## rel.inf
## room_typePrivate.room 33.063046394
## bedrooms 21.045450690
## accommodates 19.404653453
## room_typeShared.room 11.198534580
## bathrooms 7.109951471
## number_of_reviews 2.862817091
## review_scores_rating 1.581605498
## beds 0.680402790
## property_typeCondominium 0.381969550
## host_response_rate 0.354379034
## cancellation_policystrict 0.348865589
## property_typeHouse 0.312614097
## instant_bookablet 0.220099325
## property_typeLoft 0.203114477
## property_typeTimeshare 0.136472979
## property_typeOther 0.123037649
## property_typeApartment 0.103003123
## cancellation_policymoderate 0.095300930
## property_typeBed...Breakfast 0.087415124
## cancellation_policysuper_strict_30 0.087295517
## property_typeDorm 0.078439072
## property_typeGuesthouse 0.077642440
## property_typeBoutique.hotel 0.063887191
## property_typeHostel 0.054648187
## property_typeTownhouse 0.048018245
## property_typeVilla 0.041238350
## cancellation_policysuper_strict_60 0.036130248
## property_typeBungalow 0.035684433
## property_typeCamper.RV 0.029410654
## property_typeHut 0.028215341
## property_typeCastle 0.026969677
## property_typeBoat 0.020613185
## property_typeTent 0.014325391
## property_typeServiced.apartment 0.013687123
## property_typeYurt 0.010572050
## property_typeCabin 0.008448837
## property_typeGuest.suite 0.006181979
## property_typeTipi 0.003720010
## property_typeIn.law 0.002138227
## property_typeCasa.particular 0.000000000
## property_typeCave 0.000000000
## property_typeChalet 0.000000000
## property_typeEarth.House 0.000000000
## property_typeIsland 0.000000000
## property_typeLighthouse 0.000000000
## property_typeParking.Space 0.000000000
## property_typeTrain 0.000000000
## property_typeTreehouse 0.000000000
## property_typeVacation.home 0.000000000
## cleaning_fee 0.000000000
# ============================================================
# 16. STRUKTUR POHON REGRESI
# ============================================================
# Mengambil struktur pohon pertama
pohon_pertama <- pretty.gbm.tree(
model_gb,
i.tree = 1
)
cat("\nSTRUKTUR POHON ITERASI PERTAMA\n")
##
## STRUKTUR POHON ITERASI PERTAMA
print(pohon_pertama)
## SplitVar SplitCodePred LeftNode RightNode MissingNode ErrorReduction Weight
## 0 35 5.000000e-01 1 8 9 4716.211 33202
## 1 38 1.500000e+00 2 6 7 1910.328 19481
## 2 36 5.000000e-01 3 4 5 1011.151 12100
## 3 -1 7.823734e-03 -1 -1 -1 0.000 11153
## 4 -1 -4.599083e-02 -1 -1 -1 0.000 947
## 5 -1 3.611966e-03 -1 -1 -1 0.000 12100
## 6 -1 3.588794e-02 -1 -1 -1 0.000 7381
## 7 -1 1.584075e-02 -1 -1 -1 0.000 19481
## 8 -1 -2.242852e-02 -1 -1 -1 0.000 13721
## 9 -1 2.565708e-05 -1 -1 -1 0.000 33202
## Prediction
## 0 2.565708e-05
## 1 1.584075e-02
## 2 3.611966e-03
## 3 7.823734e-03
## 4 -4.599083e-02
## 5 3.611966e-03
## 6 3.588794e-02
## 7 1.584075e-02
## 8 -2.242852e-02
## 9 2.565708e-05
# ============================================================
# 17. MEMBENTUK MODEL FINAL
# MENGGUNAKAN SELURUH DATA TRAINING
# ============================================================
# Model final menggunakan jumlah pohon
# yang telah ditemukan melalui Cross Validation.
data_gb_full <- data.frame(
y = as.numeric(y_all),
X_train_all,
check.names = TRUE
)
set.seed(123)
model_gb_final <- gbm(
formula = y ~ .,
distribution = "gaussian",
data = data_gb_full,
n.trees = jumlah_pohon_optimal,
interaction.depth = 3,
n.minobsinnode = 2,
shrinkage = 0.05,
bag.fraction = 0.8,
cv.folds = 0,
n.cores = 1,
verbose = FALSE
)
## Warning in gbm.fit(x = x, y = y, offset = offset, distribution = distribution,
## : variable 50: cleaning_fee has no variation.
# ============================================================
# 18. PREDIKSI AKHIR DATA TESTING
# ============================================================
data_test_gb <- as.data.frame(
X_test_all,
check.names = TRUE
)
pred_test_log <- predict(
model_gb_final,
newdata = data_test_gb,
n.trees = jumlah_pohon_optimal,
type = "response"
)
# Mengembalikan ke skala asli
pred_test_final <- expm1(pred_test_log)
# Hasil prediksi akhir
hasil_prediksi_final <- data.frame(
id = id_test,
Prediksi_Price = pred_test_final
)
cat("\nHASIL PREDIKSI AKHIR\n")
##
## HASIL PREDIKSI AKHIR
print(head(hasil_prediksi_final))
## id Prediksi_Price
## 1 17423675 209.51931
## 2 6226658 87.28115
## 3 3563677 144.70815
## 4 17615783 72.61099
## 5 2479317 183.60472
## 6 14122244 241.11865
# ============================================================
# 19. MENYIMPAN HASIL
# ============================================================
# Evaluasi model
write.csv(
hasil_evaluasi,
"Evaluasi_Gradient_Boosting.csv",
row.names = FALSE
)
# Prediksi validasi
hasil_validasi <- data.frame(
Aktual = actual,
Prediksi = pred_valid
)
write.csv(
hasil_validasi,
"Prediksi_Validasi_Gradient_Boosting.csv",
row.names = FALSE
)
# Prediksi data testing
write.csv(
hasil_prediksi_final,
"Prediksi_Final_Gradient_Boosting.csv",
row.names = FALSE
)
# Struktur pohon pertama
write.csv(
pohon_pertama,
"Struktur_Pohon_Gradient_Boosting.csv",
row.names = FALSE
)
# Relative influence
write.csv(
importance_gb,
"Relative_Influence_Gradient_Boosting.csv",
row.names = FALSE
)
# ============================================================
# 20. RINGKASAN AKHIR
# ============================================================
cat("\n============================================\n")
##
## ============================================
cat("ANALISIS GRADIENT BOOSTING SELESAI\n")
## ANALISIS GRADIENT BOOSTING SELESAI
cat("============================================\n")
## ============================================
cat(
"Jumlah pohon optimal:",
jumlah_pohon_optimal,
"\n"
)
## Jumlah pohon optimal: 992
cat("RMSE:", RMSE, "\n")
## RMSE: 125.6057
cat("MAE:", MAE, "\n")
## MAE: 60.14508
cat("R-Squared:", R2, "\n")
## R-Squared: 0.4426829
cat("\nFile hasil berhasil disimpan.\n")
##
## File hasil berhasil disimpan.
cat("============================================\n")
## ============================================