Beberapa package yang digunakan dalam analisis data ini adalah sebagai berikut.
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.3 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ ggplot2 3.4.3 ✔ tibble 3.2.1
## ✔ lubridate 1.9.2 ✔ tidyr 1.3.0
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## ── Attaching packages ────────────────────────────────────── tidymodels 1.1.1 ──
## ✔ broom 1.0.5 ✔ rsample 1.2.0
## ✔ dials 1.2.0 ✔ tune 1.1.2
## ✔ infer 1.0.5 ✔ workflows 1.1.3
## ✔ modeldata 1.2.0 ✔ workflowsets 1.0.1
## ✔ parsnip 1.1.1 ✔ yardstick 1.2.0
## ✔ recipes 1.0.8
## ── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
## ✖ scales::discard() masks purrr::discard()
## ✖ dplyr::filter() masks stats::filter()
## ✖ recipes::fixed() masks stringr::fixed()
## ✖ dplyr::lag() masks stats::lag()
## ✖ yardstick::spec() masks readr::spec()
## ✖ recipes::step() masks stats::step()
## • Use suppressPackageStartupMessages() to eliminate package startup messages
library(dplyr)
library(DataExplorer)
library(skimr)
library(themis)
library(tictoc)
library(xgboost)
##
## Attaching package: 'xgboost'
##
## The following object is masked from 'package:dplyr':
##
## slice
Data yang digunakan berasal dari Kaggle yaitu Loan-Approval-Prediction-Dataset. Import data dilakukan menggunakan read.csv karena data yang digunakan berada dalam format csv.
dataku <- read.csv("D:/S2 STATISTIKA/SEMESTER 2/PEMBELAJARAN MESIN STATISTIKA/loan_approval_dataset.csv")
head(dataku)
## loan_id no_of_dependents education self_employed income_annum loan_amount
## 1 1 2 Graduate No 9600000 29900000
## 2 2 0 Not Graduate Yes 4100000 12200000
## 3 3 3 Graduate No 9100000 29700000
## 4 4 3 Graduate No 8200000 30700000
## 5 5 5 Not Graduate Yes 9800000 24200000
## 6 6 0 Graduate Yes 4800000 13500000
## loan_term cibil_score residential_assets_value commercial_assets_value
## 1 12 778 2400000 17600000
## 2 8 417 2700000 2200000
## 3 20 506 7100000 4500000
## 4 8 467 18200000 3300000
## 5 20 382 12400000 8200000
## 6 10 319 6800000 8300000
## luxury_assets_value bank_asset_value loan_status
## 1 22700000 8000000 Approved
## 2 8800000 3300000 Rejected
## 3 33300000 12800000 Rejected
## 4 23300000 7900000 Rejected
## 5 29400000 5000000 Rejected
## 6 13700000 5100000 Rejected
## Rows: 4,269
## Columns: 13
## $ loan_id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14…
## $ no_of_dependents <int> 2, 0, 3, 3, 5, 0, 5, 2, 0, 5, 4, 2, 3, 2, 1, …
## $ education <chr> " Graduate", " Not Graduate", " Graduate", " …
## $ self_employed <chr> " No", " Yes", " No", " No", " Yes", " Yes", …
## $ income_annum <int> 9600000, 4100000, 9100000, 8200000, 9800000, …
## $ loan_amount <int> 29900000, 12200000, 29700000, 30700000, 24200…
## $ loan_term <int> 12, 8, 20, 8, 20, 10, 4, 20, 20, 10, 2, 18, 1…
## $ cibil_score <int> 778, 417, 506, 467, 382, 319, 678, 382, 782, …
## $ residential_assets_value <int> 2400000, 2700000, 7100000, 18200000, 12400000…
## $ commercial_assets_value <int> 17600000, 2200000, 4500000, 3300000, 8200000,…
## $ luxury_assets_value <int> 22700000, 8800000, 33300000, 23300000, 294000…
## $ bank_asset_value <int> 8000000, 3300000, 12800000, 7900000, 5000000,…
## $ loan_status <chr> " Approved", " Rejected", " Rejected", " Reje…
Setelah dilakukan import data, dilakukan langkah untuk menghilangkan kolom loan_id yang terdapat pada data.
## Rows: 4,269
## Columns: 12
## $ no_of_dependents <int> 2, 0, 3, 3, 5, 0, 5, 2, 0, 5, 4, 2, 3, 2, 1, …
## $ education <chr> " Graduate", " Not Graduate", " Graduate", " …
## $ self_employed <chr> " No", " Yes", " No", " No", " Yes", " Yes", …
## $ income_annum <int> 9600000, 4100000, 9100000, 8200000, 9800000, …
## $ loan_amount <int> 29900000, 12200000, 29700000, 30700000, 24200…
## $ loan_term <int> 12, 8, 20, 8, 20, 10, 4, 20, 20, 10, 2, 18, 1…
## $ cibil_score <int> 778, 417, 506, 467, 382, 319, 678, 382, 782, …
## $ residential_assets_value <int> 2400000, 2700000, 7100000, 18200000, 12400000…
## $ commercial_assets_value <int> 17600000, 2200000, 4500000, 3300000, 8200000,…
## $ luxury_assets_value <int> 22700000, 8800000, 33300000, 23300000, 294000…
## $ bank_asset_value <int> 8000000, 3300000, 12800000, 7900000, 5000000,…
## $ loan_status <chr> " Approved", " Rejected", " Rejected", " Reje…
## 'data.frame': 4269 obs. of 12 variables:
## $ no_of_dependents : int 2 0 3 3 5 0 5 2 0 5 ...
## $ education : chr " Graduate" " Not Graduate" " Graduate" " Graduate" ...
## $ self_employed : chr " No" " Yes" " No" " No" ...
## $ income_annum : int 9600000 4100000 9100000 8200000 9800000 4800000 8700000 5700000 800000 1100000 ...
## $ loan_amount : int 29900000 12200000 29700000 30700000 24200000 13500000 33000000 15000000 2200000 4300000 ...
## $ loan_term : int 12 8 20 8 20 10 4 20 20 10 ...
## $ cibil_score : int 778 417 506 467 382 319 678 382 782 388 ...
## $ residential_assets_value: int 2400000 2700000 7100000 18200000 12400000 6800000 22500000 13200000 1300000 3200000 ...
## $ commercial_assets_value : int 17600000 2200000 4500000 3300000 8200000 8300000 14800000 5700000 800000 1400000 ...
## $ luxury_assets_value : int 22700000 8800000 33300000 23300000 29400000 13700000 29200000 11800000 2800000 3300000 ...
## $ bank_asset_value : int 8000000 3300000 12800000 7900000 5000000 5100000 4300000 6000000 600000 1600000 ...
## $ loan_status : chr " Approved" " Rejected" " Rejected" " Rejected" ...
Berdasarkan output tersebut, terlihat bahwa peubah
education
, self_employed
dan
loan_status
bertipe karakter padahal peubah peubah tersebut
merupakan peubah kategorik yang seharusnya bertipe factor sehingga dalam
hal ini akan dilakukan penyesuaian tipe peubah.
dataku$education <- as.factor(dataku$education)
dataku$self_employed <- as.factor(dataku$self_employed)
dataku$loan_status <- as.factor(dataku$loan_status)
## 'data.frame': 4269 obs. of 12 variables:
## $ no_of_dependents : int 2 0 3 3 5 0 5 2 0 5 ...
## $ education : Factor w/ 2 levels " Graduate"," Not Graduate": 1 2 1 1 2 1 1 1 1 2 ...
## $ self_employed : Factor w/ 2 levels " No"," Yes": 1 2 1 1 2 2 1 2 2 1 ...
## $ income_annum : int 9600000 4100000 9100000 8200000 9800000 4800000 8700000 5700000 800000 1100000 ...
## $ loan_amount : int 29900000 12200000 29700000 30700000 24200000 13500000 33000000 15000000 2200000 4300000 ...
## $ loan_term : int 12 8 20 8 20 10 4 20 20 10 ...
## $ cibil_score : int 778 417 506 467 382 319 678 382 782 388 ...
## $ residential_assets_value: int 2400000 2700000 7100000 18200000 12400000 6800000 22500000 13200000 1300000 3200000 ...
## $ commercial_assets_value : int 17600000 2200000 4500000 3300000 8200000 8300000 14800000 5700000 800000 1400000 ...
## $ luxury_assets_value : int 22700000 8800000 33300000 23300000 29400000 13700000 29200000 11800000 2800000 3300000 ...
## $ bank_asset_value : int 8000000 3300000 12800000 7900000 5000000 5100000 4300000 6000000 600000 1600000 ...
## $ loan_status : Factor w/ 2 levels " Approved"," Rejected": 1 2 2 2 2 2 1 2 1 2 ...
## no_of_dependents education self_employed
## 0 0 0
## income_annum loan_amount loan_term
## 0 0 0
## cibil_score residential_assets_value commercial_assets_value
## 0 0 0
## luxury_assets_value bank_asset_value loan_status
## 0 0 0
## [1] 0
Berdasarkan output tersebut, diperoleh bahwa tidak terdapat missing value dan data duplikat pada data.
Name | dataku |
Number of rows | 4269 |
Number of columns | 12 |
_______________________ | |
Column type frequency: | |
factor | 3 |
numeric | 9 |
________________________ | |
Group variables | None |
Variable type: factor
skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
---|---|---|---|---|---|
education | 0 | 1 | FALSE | 2 | Gr: 2144, No: 2125 |
self_employed | 0 | 1 | FALSE | 2 | Ye: 2150, No: 2119 |
loan_status | 0 | 1 | FALSE | 2 | Ap: 2656, Re: 1613 |
Variable type: numeric
skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 |
---|---|---|---|---|---|---|---|---|---|
no_of_dependents | 0 | 1 | 2.50 | 1.70 | 0e+00 | 1 | 3 | 4 | 5 |
income_annum | 0 | 1 | 5059123.92 | 2806839.83 | 2e+05 | 2700000 | 5100000 | 7500000 | 9900000 |
loan_amount | 0 | 1 | 15133450.46 | 9043362.98 | 3e+05 | 7700000 | 14500000 | 21500000 | 39500000 |
loan_term | 0 | 1 | 10.90 | 5.71 | 2e+00 | 6 | 10 | 16 | 20 |
cibil_score | 0 | 1 | 599.94 | 172.43 | 3e+02 | 453 | 600 | 748 | 900 |
residential_assets_value | 0 | 1 | 7472616.54 | 6503636.59 | -1e+05 | 2200000 | 5600000 | 11300000 | 29100000 |
commercial_assets_value | 0 | 1 | 4973155.31 | 4388966.09 | 0e+00 | 1300000 | 3700000 | 7600000 | 19400000 |
luxury_assets_value | 0 | 1 | 15126305.93 | 9103753.67 | 3e+05 | 7500000 | 14600000 | 21700000 | 39200000 |
bank_asset_value | 0 | 1 | 4976692.43 | 3250185.31 | 0e+00 | 2300000 | 4600000 | 7100000 | 14700000 |
Adapun ringkasan dari data adalah sebagai berikut.
## no_of_dependents education self_employed income_annum
## Min. :0.000 Graduate :2144 No :2119 Min. : 200000
## 1st Qu.:1.000 Not Graduate:2125 Yes:2150 1st Qu.:2700000
## Median :3.000 Median :5100000
## Mean :2.499 Mean :5059124
## 3rd Qu.:4.000 3rd Qu.:7500000
## Max. :5.000 Max. :9900000
## loan_amount loan_term cibil_score residential_assets_value
## Min. : 300000 Min. : 2.0 Min. :300.0 Min. : -100000
## 1st Qu.: 7700000 1st Qu.: 6.0 1st Qu.:453.0 1st Qu.: 2200000
## Median :14500000 Median :10.0 Median :600.0 Median : 5600000
## Mean :15133450 Mean :10.9 Mean :599.9 Mean : 7472617
## 3rd Qu.:21500000 3rd Qu.:16.0 3rd Qu.:748.0 3rd Qu.:11300000
## Max. :39500000 Max. :20.0 Max. :900.0 Max. :29100000
## commercial_assets_value luxury_assets_value bank_asset_value
## Min. : 0 Min. : 300000 Min. : 0
## 1st Qu.: 1300000 1st Qu.: 7500000 1st Qu.: 2300000
## Median : 3700000 Median :14600000 Median : 4600000
## Mean : 4973155 Mean :15126306 Mean : 4976692
## 3rd Qu.: 7600000 3rd Qu.:21700000 3rd Qu.: 7100000
## Max. :19400000 Max. :39200000 Max. :14700000
## loan_status
## Approved:2656
## Rejected:1613
##
##
##
##
Melakukan visualisasi peubah Y menggunakan piechart untuk melihat banyaknya peminjam yang berpotensi menerima pinjaman dan ditolak.
dataku %>%
count(loan_status) %>%
mutate(percent=n*100/sum(n),label=str_c(round(percent,2),"%")) %>%
ggplot(aes(x="",y=n,fill=loan_status))+
geom_col()+
geom_text(aes(label = label),
position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y")+
theme_void() +
labs(title = "Proporsi Loan Status",
fill = "Loan Status")
Berdasarkan piechart tersebut terlihat bahwa banyaknya peminjam yang berpotensi menerima pinjaman jauh lebih banyak dibandingkan dengan peminjam yang berpotensi ditolak untuk menerima pinjaman. Hal ini menunjukkan adanya proporsi data yang tidak seimbang sehingga perlu dilakukan penanganan pada tahapan praproses data.
Name | dataku |
Number of rows | 4269 |
Number of columns | 12 |
_______________________ | |
Column type frequency: | |
factor | 3 |
numeric | 9 |
________________________ | |
Group variables | None |
Variable type: factor
skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
---|---|---|---|---|---|
education | 0 | 1 | FALSE | 2 | Gr: 2144, No: 2125 |
self_employed | 0 | 1 | FALSE | 2 | Ye: 2150, No: 2119 |
loan_status | 0 | 1 | FALSE | 2 | Ap: 2656, Re: 1613 |
Variable type: numeric
skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 |
---|---|---|---|---|---|---|---|---|---|
no_of_dependents | 0 | 1 | 2.50 | 1.70 | 0e+00 | 1 | 3 | 4 | 5 |
income_annum | 0 | 1 | 5059123.92 | 2806839.83 | 2e+05 | 2700000 | 5100000 | 7500000 | 9900000 |
loan_amount | 0 | 1 | 15133450.46 | 9043362.98 | 3e+05 | 7700000 | 14500000 | 21500000 | 39500000 |
loan_term | 0 | 1 | 10.90 | 5.71 | 2e+00 | 6 | 10 | 16 | 20 |
cibil_score | 0 | 1 | 599.94 | 172.43 | 3e+02 | 453 | 600 | 748 | 900 |
residential_assets_value | 0 | 1 | 7472616.54 | 6503636.59 | -1e+05 | 2200000 | 5600000 | 11300000 | 29100000 |
commercial_assets_value | 0 | 1 | 4973155.31 | 4388966.09 | 0e+00 | 1300000 | 3700000 | 7600000 | 19400000 |
luxury_assets_value | 0 | 1 | 15126305.93 | 9103753.67 | 3e+05 | 7500000 | 14600000 | 21700000 | 39200000 |
bank_asset_value | 0 | 1 | 4976692.43 | 3250185.31 | 0e+00 | 2300000 | 4600000 | 7100000 | 14700000 |
Dari peubah penjelas kategorik yang terdiri dari education dan self_employed. Pada peubah education menunjukkan bahwa proporsi status pinjaman diterima untuk graduate dan not graduate lebih besar dibanding ditolak. Sedangkan pada peubah self_employed, juga menunjukkan bahwa proporsi status pinjaman diterima untuk yes dan no lebih besar dibanding ditolak.
plot_boxplot(data = dataku,by = "loan_status",
ggtheme = theme_classic(),
geom_boxplot_args = list(fill="#03A9F4"))
Berdasarkan box-plot, terlihat bahwa beberapa peubah memiliki cukup banyak pencilan. Berdasarkan boxplot terlihat pula bahwa terdapat ketidakseragaman skala pada setiap peubah sehingga perlu dilakukan penanganan pada tahapan praproses data. Berdasarkan box-plot tersebut, terlihat secara grafis bahwa ada perbedaan secara rata-rata dan sebaran antara kelompok diterima dan ditolak untuk setiap peubah penjelas.
Sebelum dilakukan pemodelan, akan dilakukan pengecekan bagaimana korelasi antar peubah penjelas yang akan digunakan dalam model. Peubah yang digunakan sebaiknya adalah peubah yang tidak saling berkorelasi satu sama lain.
plot_correlation(data = dataku,
type = "continuous",
cor_args = list(method="spearman"),
ggtheme = theme_classic(),
theme_config = list(legend.position = "none",
axis.text.x=element_text(angle = 90)))
Berdasarkan heatmap tersebut, diketahui bahwa terdapat beberapa peubah penjelas memiliki nilai korelasi di atas 0.8. Hal ini mengindikasi bahwa terdapat multikolinieritas antar peubah penjelas. Namun korelasi yang tinggi tersebut tidak diatasi karena dengan menggunakan ensemble methods seperti Random Forest atau Gradient Boosting yang lebih tahan terhadap multicollinearity bisa membantu mengurangi dampak dari korelasi yang tinggi.
# Fungsi untuk menangani outlier
handle_outliers <- function(dataku, columns) {
for (col in columns) {
# Hitung IQR
Q1 <- quantile(dataku[[col]], 0.25)
Q3 <- quantile(dataku[[col]], 0.75)
IQR <- Q3 - Q1
# Tentukan batas untuk outlier
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
# Cap outlier
dataku[[col]] <- ifelse(dataku[[col]] < lower_bound, lower_bound, dataku[[col]])
dataku[[col]] <- ifelse(dataku[[col]] > upper_bound, upper_bound, dataku[[col]])
}
return(dataku)
}
# Kolom yang akan ditangani outliernya
columns <- c('bank_asset_value', 'cibil_score', 'commercial_assets_value', 'income_annum',
'loan_amount', 'loan_term', 'luxury_assets_value', 'no_of_dependents',
'residential_assets_value')
# Tangani outlier
data <- handle_outliers(dataku, columns)
# Cek hasilnya
print(summary(data))
## no_of_dependents education self_employed income_annum
## Min. :0.000 Graduate :2144 No :2119 Min. : 200000
## 1st Qu.:1.000 Not Graduate:2125 Yes:2150 1st Qu.:2700000
## Median :3.000 Median :5100000
## Mean :2.499 Mean :5059124
## 3rd Qu.:4.000 3rd Qu.:7500000
## Max. :5.000 Max. :9900000
## loan_amount loan_term cibil_score residential_assets_value
## Min. : 300000 Min. : 2.0 Min. :300.0 Min. : -100000
## 1st Qu.: 7700000 1st Qu.: 6.0 1st Qu.:453.0 1st Qu.: 2200000
## Median :14500000 Median :10.0 Median :600.0 Median : 5600000
## Mean :15133450 Mean :10.9 Mean :599.9 Mean : 7454861
## 3rd Qu.:21500000 3rd Qu.:16.0 3rd Qu.:748.0 3rd Qu.:11300000
## Max. :39500000 Max. :20.0 Max. :900.0 Max. :24950000
## commercial_assets_value luxury_assets_value bank_asset_value
## Min. : 0 Min. : 300000 Min. : 0
## 1st Qu.: 1300000 1st Qu.: 7500000 1st Qu.: 2300000
## Median : 3700000 Median :14600000 Median : 4600000
## Mean : 4964289 Mean :15126306 Mean : 4976341
## 3rd Qu.: 7600000 3rd Qu.:21700000 3rd Qu.: 7100000
## Max. :17050000 Max. :39200000 Max. :14300000
## loan_status
## Approved:2656
## Rejected:1613
##
##
##
##
plot_boxplot(data = data,by = "loan_status",
ggtheme = theme_classic(),
geom_boxplot_args = list(fill="#03A9F4"))
Berdasarkan box-plot, terlihat bahwa beberapa peubah yang sebelumnya memiliki banyak pencilan menunjukkan pengurangan jumlah pencilan.
Berdasarkan eksplorasi data, terlihat bahwa perlu dilakukan penanganan pada kondisi data tidak seimbang. Dalam hal ini, kondisi data tidak seimbang ditangani dengan melakukan SMOTE. Selain itu, berdasarkan eksplorasi data, perlu dilakukan penanganan pada peubah penjelas numerik yang memiliki ketidakseragaman skala, sehingga dalam hal ini ketidakseragaman skala ditangani dengan melakukan proses normalisasi. Lalu juga dilakukan One-hot Encoding untuk semua variabel penjelalas kategorik.
set.seed(2024)
no_prep <- recipe(loan_status~.,data = data) %>%
#Standardization
step_normalize(all_numeric_predictors()) %>%
#One-hot Encoding
step_dummy(all_nominal_predictors(),
one_hot = TRUE)
no_prep %>%
prep() %>%
bake(new_data = NULL) %>%
glimpse()
## Rows: 4,269
## Columns: 14
## $ no_of_dependents <dbl> -0.2940673, -1.4733750, 0.2955866, 0.2955866,…
## $ income_annum <dbl> 1.61778953, -0.34170953, 1.43965325, 1.119007…
## $ loan_amount <dbl> 1.63286043, -0.32437606, 1.61074476, 1.721323…
## $ loan_term <dbl> 0.1925940, -0.5080312, 1.5938442, -0.5080312,…
## $ cibil_score <dbl> 1.0326714, -1.0609269, -0.5447766, -0.7709548…
## $ residential_assets_value <dbl> -0.78340277, -0.73690875, -0.05499633, 1.6652…
## $ commercial_assets_value <dbl> 2.76999498, -0.63356362, -0.10641313, -0.3814…
## $ luxury_assets_value <dbl> 0.83193091, -0.69491181, 1.99628579, 0.897837…
## $ bank_asset_value <dbl> 0.930597525, -0.515930823, 2.407903073, 0.899…
## $ loan_status <fct> Approved, Rejected, Rejected, Rejected, …
## $ education_X.Graduate <dbl> 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, …
## $ education_X.Not.Graduate <dbl> 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, …
## $ self_employed_X.No <dbl> 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, …
## $ self_employed_X.Yes <dbl> 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, …
set.seed(2024)
basic_prep <- recipe(loan_status~.,data = data) %>%
#SMOTE
step_smotenc(loan_status,over_ratio = 1,neighbors = 7 ) %>%
#Standardization
step_normalize(all_numeric_predictors()) %>%
#One-hot Encoding
step_dummy(all_nominal_predictors(),
one_hot = TRUE)
basic_prep %>%
prep() %>%
bake(new_data = NULL) %>%
glimpse()
## Rows: 5,312
## Columns: 14
## $ no_of_dependents <dbl> -0.3018395, -1.4906216, 0.2925515, 0.2925515,…
## $ income_annum <dbl> 1.63165760, -0.34251525, 1.45218734, 1.129140…
## $ loan_amount <dbl> 1.66601665, -0.31918783, 1.64358496, 1.755743…
## $ loan_term <dbl> 0.1586274, -0.5558404, 1.5875632, -0.5558404,…
## $ cibil_score <dbl> 1.23390421, -0.86871933, -0.35034399, -0.5774…
## $ residential_assets_value <dbl> -0.79031522, -0.74331726, -0.05401385, 1.6849…
## $ commercial_assets_value <dbl> 2.81739980, -0.63124312, -0.09710987, -0.3757…
## $ luxury_assets_value <dbl> 0.83989599, -0.70139749, 2.01527088, 0.906426…
## $ bank_asset_value <dbl> 0.94884142, -0.51793700, 2.44682789, 0.917633…
## $ loan_status <fct> Approved, Rejected, Rejected, Rejected, …
## $ education_X.Graduate <dbl> 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, …
## $ education_X.Not.Graduate <dbl> 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, …
## $ self_employed_X.No <dbl> 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, …
## $ self_employed_X.Yes <dbl> 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, …
## # A tibble: 2 × 2
## loan_status n
## <fct> <int>
## 1 " Approved" 2656
## 2 " Rejected" 2656
# Menghitung frekuensi dan persentase masing-masing kategori 'loan_status'
loan_status_count <- basic_prep %>%
prep() %>%
bake(new_data = NULL) %>%
count(loan_status) %>%
mutate(percent = n * 100 / sum(n),
label = str_c(round(percent, 2), "%"))
# Membuat plot pie chart
ggplot(loan_status_count, aes(x = "", y = n, fill = loan_status)) +
geom_col() +
geom_text(aes(label = label),
position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y") +
theme_void() +
labs(title = "Proporsi Loan Status",
fill = "Loan Status")
Dari hasil penanganan data tidak seimbang dengan SMOTE diperoleh jumlah tiap masing-masing kategori status sebesar 2656.
Dilakukan pembagian data training dan data testing dengan pembagian 80:20
## # A tibble: 2 × 2
## Data n
## <chr> <int>
## 1 Analysis 3414
## 2 Assessment 855
## [1] 3414 12
## [1] 855 12
Dari pembagian data ini diperoleh data training sebanyak 3414 data dan data testing sebanyak 855 data.
random_forest <- rand_forest() %>%
set_mode('classification') %>%
set_engine('ranger', importance = "impurity")
rand_forest()
adalah fungsi yang digunakan untuk
membuat spesifikasi model Random Forest tanpa parameter tambahan. Ini
merupakan bagian dari framework tidymodels.
set_mode('classification')
menetapkan model ini
untuk tugas klasifikasi.
set_engine('ranger', importance = "impurity")
menetapkan ranger sebagai mesin yang digunakan untuk menjalankan
algoritma Random Forest. ranger adalah implementasi cepat dari algoritma
Random Forest, terutama untuk dataset besar.
Argumen tambahan importance = "impurity"
digunakan
untuk menghitung pentingnya fitur berdasarkan impurity (ketidakmurnian)
dalam pohon keputusan.
Model training bisa dilakukan dengan memanfaatkan fungsi workflow seperti dibawah ini:
set.seed(2045)
tic()
random_forest_trained <- workflow() %>%
add_recipe(recipe = basic_prep) %>%
add_model(spec =random_forest) %>%
fit(train_df)
toc()
## 1.95 sec elapsed
Fungsi add_recipe
digunakan untuk menambahkan tahap
praproses data menggunakan package recipe.
Fungsi add_model
digunakan untuk menambahkan model
yang akan dilakukan training.
Fungsi fit
digunakan untuk menjalankan
training.
Berikut adalah sintaks mendapatkan prediksi training data dalam bentuk kategori (factor).
set.seed(2024)
pred_rf_train <- random_forest_trained %>%
predict(new_data = train_df,type = "class")
pred_rf_train
## # A tibble: 3,414 × 1
## .pred_class
## <fct>
## 1 " Approved"
## 2 " Approved"
## 3 " Approved"
## 4 " Approved"
## 5 " Approved"
## 6 " Approved"
## 7 " Approved"
## 8 " Approved"
## 9 " Approved"
## 10 " Approved"
## # ℹ 3,404 more rows
type = "class"
argumen untuk mendapatkan prediksi dalam
bentuk kategori (factor).Berikut adalah sintaks mendapatkan prediksi training data dalam bentuk peluang.
prob_rf_train <- random_forest_trained %>%
predict(new_data = train_df, type = "prob")
prob_rf_train
## # A tibble: 3,414 × 2
## `.pred_ Approved` `.pred_ Rejected`
## <dbl> <dbl>
## 1 0.970 0.0302
## 2 0.980 0.0201
## 3 0.984 0.0162
## 4 0.999 0.00133
## 5 0.997 0.00290
## 6 0.989 0.0109
## 7 0.995 0.00478
## 8 0.986 0.0140
## 9 0.993 0.00704
## 10 0.993 0.00680
## # ℹ 3,404 more rows
Berikut adalah sintaks untuk menambahkan kolom variabel respon dari training data.
## # A tibble: 3,414 × 2
## .pred_class truth
## <fct> <fct>
## 1 " Approved" " Approved"
## 2 " Approved" " Approved"
## 3 " Approved" " Approved"
## 4 " Approved" " Approved"
## 5 " Approved" " Approved"
## 6 " Approved" " Approved"
## 7 " Approved" " Approved"
## 8 " Approved" " Approved"
## 9 " Approved" " Approved"
## 10 " Approved" " Approved"
## # ℹ 3,404 more rows
Selanjutnya, kita akan mengeluarkan confussion matriks.
Confusion matriks dapat ditampilkan dalam bentuk chart sebagai berikut:
autoplot(confussion_matrix_train, type = "heatmap") +
scale_fill_gradient(low = "#F4AFAB", high = "#EE847E")
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
Fungsi autoplot
digunakan untuk mennampilkan
confussion matrix.
Fungsi scale_fill_gradient
digunakan untuk memberi
warna pada confussion matrix.
Berdasarkan output confussion matrix, terdapat 9 kasus status
pinjaman sebenarnya rejected
tetapi model memprediksi
sebagai approved
. Selain itu terdapat 1 kasus di mana
status pinjaman sebenarnya approved
, tetapi model
memprediksi sebagai rejected
.
Pertama-tama, kita harus definsikan terlebih dahulu metrics yang kita
gunakan. Metrics-metrics ini didapatkan dengan menggunakan package
yardstick
.
Fungsi metric_set
digunakan untuk menyatukan beberapa
metrik evaluasi. F_meas
adalah metrik f1-score.
Berikut adalah hasil evaluasi prediksi pada testing data menggunakan 4 metrik yang sudah didefinisikan.
pred_rf_train %>%
#menambahkan kolom truth
mutate(truth=train_df$loan_status) %>%
# evaluasi prediksi berdasarkan metrik
multi_metric(truth = truth,estimate = .pred_class)
## # A tibble: 4 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 accuracy binary 0.997
## 2 sensitivity binary 1.00
## 3 specificity binary 0.993
## 4 f_meas binary 0.998
Accuracy (Akurasi): 0.9970709
Akurasi adalah proporsi prediksi yang benar (baik positif maupun negatif) dari keseluruhan jumlah kasus. Dalam kasus ini, model memiliki akurasi sebesar 99.7%, yang berarti model memprediksi dengan benar 99.7% dari semua kasus.
Sensitivity (Sensitivitas) atau Recall: 0.9995292
Sensitivitas adalah proporsi kasus positif yang benar-benar teridentifikasi dengan benar oleh model. Sensitivitas sebesar 99.95% menunjukkan bahwa model berhasil mengidentifikasi semua kasus positif dengan benar (tidak ada False Negatives).
Specificity (Spesifisitas): 0.9930233
Spesifisitas adalah proporsi kasus negatif yang benar-benar teridentifikasi dengan benar oleh model. Spesifisitas sebesar 0.9930233 menunjukkan bahwa model berhasil mengidentifikasi sekitar 99.3% dari semua kasus negatif dengan benar (hanya ada sedikit False Positives).
F-measure (F1-score): 0.9976504
F1-score adalah rata-rata harmonik dari presisi dan sensitivitas. Ini memberikan ukuran seimbang dari kemampuan model dalam mengenali kasus positif, dengan menggabungkan baik False Positives dan False Negatives. Nilai sebesar 99.76% menunjukkan kinerja model yang sangat baik dalam mengidentifikasi kasus positif.
Dengan metrik-metrik ini, dapat disimpulkan bahwa model yang digunakan memiliki kinerja yang sangat baik dalam mengklasifikasikan status pinjaman, dengan akurasi dan keseimbangan yang tinggi antara sensitivitas dan spesifisitas.
set.seed(2024)
pred_rf_test <- random_forest_trained %>%
predict(new_data = test_df, type = "class")
pred_rf_test
## # A tibble: 855 × 1
## .pred_class
## <fct>
## 1 " Approved"
## 2 " Rejected"
## 3 " Rejected"
## 4 " Approved"
## 5 " Rejected"
## 6 " Rejected"
## 7 " Approved"
## 8 " Approved"
## 9 " Approved"
## 10 " Rejected"
## # ℹ 845 more rows
## # A tibble: 855 × 2
## `.pred_ Approved` `.pred_ Rejected`
## <dbl> <dbl>
## 1 0.949 0.0506
## 2 0.0434 0.957
## 3 0.0297 0.970
## 4 0.520 0.480
## 5 0.0206 0.979
## 6 0.0184 0.982
## 7 0.924 0.0757
## 8 0.975 0.0247
## 9 0.967 0.0329
## 10 0.0250 0.975
## # ℹ 845 more rows
pred_rf_test <- pred_rf_test %>%
#menambahkan kolom truth
mutate(truth=test_df$loan_status)
pred_rf_test
## # A tibble: 855 × 2
## .pred_class truth
## <fct> <fct>
## 1 " Approved" " Approved"
## 2 " Rejected" " Rejected"
## 3 " Rejected" " Rejected"
## 4 " Approved" " Approved"
## 5 " Rejected" " Rejected"
## 6 " Rejected" " Rejected"
## 7 " Approved" " Approved"
## 8 " Approved" " Approved"
## 9 " Approved" " Approved"
## 10 " Rejected" " Rejected"
## # ℹ 845 more rows
autoplot(confussion_matrix_test,type = "heatmap")+
scale_fill_gradient(low = "#F4AFAB",high = "#EE847E")
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
Berdasarkan output confussion matrix, terdapat 6 kasus status
pinjaman sebenarnya rejected
tetapi model memprediksi
sebagai approved
. Selain itu terdapat 16 kasus di mana
status pinjaman sebenarnya approved
, tetapi model
memprediksi sebagai rejected
.
pred_rf_test %>%
#menambahkan kolom truth
mutate(truth=test_df$loan_status) %>%
# evaluasi prediksi berdasarkan metrik
multi_metric(truth = truth,estimate = .pred_class)
## # A tibble: 4 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 accuracy binary 0.974
## 2 sensitivity binary 0.970
## 3 specificity binary 0.981
## 4 f_meas binary 0.979
Accuracy (Akurasi): 0.9742690
Akurasi adalah proporsi prediksi yang benar (baik positif maupun negatif) dari keseluruhan jumlah kasus. Dalam kasus ini, model memiliki akurasi sebesar 97.42%, yang berarti model memprediksi dengan benar 97.42% dari semua kasus.
Sensitivity (Sensitivitas) atau Recall: 0.9699248
Sensitivitas adalah proporsi kasus positif yang benar-benar teridentifikasi dengan benar oleh model. Sensitivitas sebesar 96.99% menunjukkan bahwa model berhasil mengidentifikasi semua kasus positif dengan benar (tidak ada False Negatives).
Specificity (Spesifisitas): 0.9814241
Spesifisitas adalah proporsi kasus negatif yang benar-benar teridentifikasi dengan benar oleh model. Spesifisitas sebesar 0.9814241 menunjukkan bahwa model berhasil mengidentifikasi sekitar 98.14% dari semua kasus negatif dengan benar (hanya ada sedikit False Positives).
F-measure (F1-score): 0.9791271
F1-score adalah rata-rata harmonik dari presisi dan sensitivitas. Ini memberikan ukuran seimbang dari kemampuan model dalam mengenali kasus positif, dengan menggabungkan baik False Positives dan False Negatives. Nilai sebesar 97.91% menunjukkan kinerja model yang sangat baik dalam mengidentifikasi kasus positif.
Dengan metrik-metrik ini, dapat disimpulkan bahwa model yang digunakan memiliki kinerja yang sangat baik dalam mengklasifikasikan status pinjaman, dengan akurasi dan keseimbangan yang tinggi antara sensitivitas dan spesifisitas.
Pembagian data dilakukan dengan menggunakan metode Cross
Validation dengan fungsi vfold_cv
v = 10
untuk menentukan banyaknya fold yang
digunakan dalam Cross Validation adalah 10.
strata = "class"
metode sampling yang digunakan
adalah Stratified Random Sampling dengan stratifikasi berdasarkan kolom
class
yang berperan sebagai variabel respon.
Model Training and Evaluation akan dilakukan dengan bantuan fungsi
workflow_set
dan workflow_map
. Kedua fungsi
ini memungkinkan kita untuk melakukan pemilihan model terbaik
berdasarkan metrik-metrik tertentu.
Fungsi workflow_set
digunakan untuk menginput tahap
praproses data dan model apa yang digunakan. Sementara itu, fungsi
workflow_map
digunakan untuk menginputkan metode pembagian
data dan metrik sekaligus melakukan model training and
evaluation.
set.seed(2024)
mod_selection_trained <- workflow_set(preproc = list(no=no_prep,basic=basic_prep),
models = list(rf_mod),
cross = TRUE ) %>%
workflow_map(fn = "fit_resamples",
resamples= folds,
metrics = multi_metric,
control = control_resamples(save_workflow = TRUE),
seed = 2045)
argumen preproc
digunakan untuk menginputkan tahap
praproses data
sintaksbasic=
digunakan untuk memberi nama pada
tahap praproses data
argumen models
digunakan untuk menginputkan
model
argumen cross=TRUE
menandakan bahwa tahap praproses
data dan model dipasangkan secara kombinasi. Sebagai ilustrasi tahap
praproses data basic
akan dipasangkan dengan model decision
tree, random forest dan regresi logistik.
argumen cross=TRUE
menandakan bahwa tahap praproses
data dan model dipasangkan sesuai dengan urutanyan. Sebgai ilustrasi
tahap praproses data no
dipasangkan dengan decision. tree
dan tahap praproses data basic
akan dipasangkan dengan
random forest. Semetara model regresi logistik tidak punya tahap
praproses data sehingga akan menyebabkan error
.
argumen fn
digunakan untuk menentukan fungsi
tidymodels yang akan digunakan.
argumen resamples
digunakan untuk menginputkan
metode pembagian data
argumen metrics
digunakan untuk menginputkan
metrik-metrik.
untuk argumen control
bisa melihat help untuk lebih
jelas.
Hasil training and evaluation pada sintaks sebelumnya disimpan dalam
objek mod_selection_trained
. Selanjutnya kita akan
menampilkan hasilnya dengan menggunakan ranking.
custom_output <- function(data){
data %>%
mutate(method = map_chr(wflow_id, ~ str_split(.x, "_",simplify = TRUE)[1])) %>%
select(method,model,.metric,mean,std_err,rank)
}
mod_selection_result <- rank_results(mod_selection_trained,
rank_metric = "accuracy") %>%
custom_output()
mod_selection_result
## # A tibble: 8 × 6
## method model .metric mean std_err rank
## <chr> <chr> <chr> <dbl> <dbl> <int>
## 1 no rand_forest accuracy 0.981 0.00172 1
## 2 no rand_forest f_meas 0.985 0.00138 1
## 3 no rand_forest sensitivity 0.989 0.00253 1
## 4 no rand_forest specificity 0.968 0.00378 1
## 5 basic rand_forest accuracy 0.977 0.00174 2
## 6 basic rand_forest f_meas 0.982 0.00143 2
## 7 basic rand_forest sensitivity 0.980 0.00350 2
## 8 basic rand_forest specificity 0.972 0.00393 2
argumen rank_metric
digunakan untuk menentukan
metrik apa yang digunakan sebagai ranking.
fungsi custom_output
digunakan untuk mengkustomisasi
output yang dihasilkan. Fungsi ini bisa tidak perlu
dirubah-rubah.
mod_selection_result %>%
ggplot(aes(x = rank, y = mean, pch = method, col = model)) +
geom_point(cex = 3)+
facet_wrap(~.metric)+
theme_bw()
Setelah mendapatkan model terbaik kita bisa mengekstraknya model
tersebut kemudian melakukan training ulang dengan seluruh data yang
dimiliki menggunakan fungsi fit_best
berikut ini.
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Recipe
## Model: rand_forest()
##
## ── Preprocessor ────────────────────────────────────────────────────────────────
## 2 Recipe Steps
##
## • step_normalize()
## • step_dummy()
##
## ── Model ───────────────────────────────────────────────────────────────────────
## Ranger result
##
## Call:
## ranger::ranger(x = maybe_data_frame(x), y = y, importance = ~"impurity", num.threads = 1, verbose = FALSE, seed = sample.int(10^5, 1), probability = TRUE)
##
## Type: Probability estimation
## Number of trees: 500
## Sample size: 4269
## Number of independent variables: 13
## Mtry: 3
## Target node size: 10
## Variable importance mode: impurity
## Splitrule: gini
## OOB prediction error (Brier s.): 0.01805937
##
## ── Recipe ──────────────────────────────────────────────────────────────────────
##
## ── Inputs
## Number of variables by role
## outcome: 1
## predictor: 11
##
## ── Training information
## Training data contained 4269 data points and no incomplete rows.
##
## ── Operations
## • Centering and scaling for: no_of_dependents, income_annum, ... | Trained
## • Dummy variables from: education, self_employed | Trained
Untuk mengetahui peubah penjelas mana yang paling berkontribusi terhadap peubah respon, dilakukan perhitungan nilai feature importance dari peubah-peubah penjelas yang digunakan dalam pembentukan model.
# Retraining Random Forest dengan seluruh data
rf_mod_trained <- workflow() %>%
add_recipe(recipe = no_prep) %>%
add_model(spec = rf_mod) %>%
fit(data=data)
plot_importance<- function(rf){
rf %>%
ranger::importance() %>%
as.data.frame() %>%
rownames_to_column("Variables") %>%
rename("impurity"=".") %>%
arrange(impurity) %>%
mutate(Variables=factor(Variables,levels=Variables)) %>%
ggplot(aes(Variables,impurity))+
geom_col(fill="#03A9F4")+
coord_flip()+
theme_classic()+
theme(axis.line.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() )+
scale_y_continuous(expand = c(0,0))
}
Berdasarkan plot tersebut, terlihat bahwa peubah yang memiliki peranan paling penting untuk menentukan apakah peminjam berpotensi memperoleh pinjaman adalah peubah cibil_score, loan_term, dan loan_amount.
boost_tree()
’ adalah fungsi dari paket
parsnip
yang digunakan untuk membuat spesifikasi model
untuk model pohon yang akan ditingkatkan, seperti XGBoost.
set_engine("xgboost")
: Ini adalah fungsi dari paket
parsnip
yang digunakan untuk menentukan mesin pembelajaran
yang akan digunakan untuk menjalankan model, dalam hal ini,
xgboost
(XGBoost).
set_mode('classification')
menetapkan model ini
untuk tugas klasifikasi.
Model training bisa dilakukan dengan memanfaatkan fungsi workflow seperti dibawah ini:
set.seed(2045)
tic()
xgboost_trained <- workflow() %>%
add_recipe(recipe = basic_prep) %>%
add_model(spec =xgb_spec) %>%
fit(train_df)
toc()
## 1.06 sec elapsed
Fungsi add_recipe
digunakan untuk menambahkan tahap
praproses data menggunakan package recipe.
Fungsi add_model
digunakan untuk menambahkan model
yang akan dilakukan training.
Fungsi fit
digunakan untuk menjalankan
training.
Berikut adalah sintaks mendapatkan prediksi training data dalam bentuk kategori (factor).
set.seed(2024)
pred_xgb_train <- xgboost_trained %>%
predict(new_data = train_df, type = "class")
pred_xgb_train
## # A tibble: 3,414 × 1
## .pred_class
## <fct>
## 1 " Approved"
## 2 " Approved"
## 3 " Approved"
## 4 " Approved"
## 5 " Approved"
## 6 " Approved"
## 7 " Approved"
## 8 " Approved"
## 9 " Approved"
## 10 " Approved"
## # ℹ 3,404 more rows
type = "class"
argumen untuk mendapatkan prediksi dalam
bentuk kategori (factor).Berikut adalah sintaks mendapatkan prediksi training data dalam bentuk peluang.
## # A tibble: 3,414 × 2
## `.pred_ Approved` `.pred_ Rejected`
## <dbl> <dbl>
## 1 0.994 0.00563
## 2 0.987 0.0131
## 3 0.994 0.00563
## 4 0.994 0.00563
## 5 0.994 0.00563
## 6 0.994 0.00563
## 7 0.994 0.00563
## 8 0.994 0.00563
## 9 0.994 0.00563
## 10 0.994 0.00563
## # ℹ 3,404 more rows
Berikut adalah sintaks untuk menambahkan kolom variabel respon dari training data.
## # A tibble: 3,414 × 2
## .pred_class truth
## <fct> <fct>
## 1 " Approved" " Approved"
## 2 " Approved" " Approved"
## 3 " Approved" " Approved"
## 4 " Approved" " Approved"
## 5 " Approved" " Approved"
## 6 " Approved" " Approved"
## 7 " Approved" " Approved"
## 8 " Approved" " Approved"
## 9 " Approved" " Approved"
## 10 " Approved" " Approved"
## # ℹ 3,404 more rows
Selanjutnya, kita akan mengeluarkan confussion matriks.
Confusion matriks dapat ditampilkan dalam bentuk chart sebagai berikut:
autoplot(confussion_matrix_train, type = "heatmap") +
scale_fill_gradient(low = "#F4AFAB", high = "#EE847E")
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
Fungsi autoplot
digunakan untuk mennampilkan
confussion matrix.
Fungsi scale_fill_gradient
digunakan untuk memberi
warna pada confussion matrix.
Berdasarkan output confussion matrix, terdapat 9 kasus status
pinjaman sebenarnya rejected
tetapi model memprediksi
sebagai approved
. Selain itu terdapat 1 kasus di mana
status pinjaman sebenarnya approved
, tetapi model
memprediksi sebagai rejected
.
Pertama-tama, kita harus definsikan terlebih dahulu metrics yang kita
gunakan. Metrics-metrics ini didapatkan dengan menggunakan package
yardstick
.
Fungsi metric_set
digunakan untuk menyatukan beberapa
metrik evaluasi. F_meas
adalah metrik f1-score.
Berikut adalah hasil evaluasi prediksi pada testing data menggunakan 5 metrik yang sudah didefinisikan.
pred_xgb_train %>%
#menambahkan kolom truth
mutate(truth=train_df$loan_status) %>%
# evaluasi prediksi berdasarkan metrik
multi_metric(truth = truth,estimate = .pred_class)
## # A tibble: 4 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 accuracy binary 0.997
## 2 sensitivity binary 0.999
## 3 specificity binary 0.995
## 4 f_meas binary 0.998
Accuracy (Akurasi): 0.9973638
Akurasi adalah proporsi prediksi yang benar (baik positif maupun negatif) dari keseluruhan jumlah kasus. Dalam kasus ini, model memiliki akurasi sebesar 99.73%, yang berarti model memprediksi dengan benar 99.73% dari semua kasus.
Sensitivity (Sensitivitas) atau Recall: 0.9985876
Sensitivitas adalah proporsi kasus positif yang benar-benar teridentifikasi dengan benar oleh model. Sensitivitas sebesar 99.85% menunjukkan bahwa model berhasil mengidentifikasi semua kasus positif dengan benar (tidak ada False Negatives).
Specificity (Spesifisitas): 0.9953488
Spesifisitas adalah proporsi kasus negatif yang benar-benar teridentifikasi dengan benar oleh model. Spesifisitas sebesar 0.9953488 menunjukkan bahwa model berhasil mengidentifikasi sekitar 99.53% dari semua kasus negatif dengan benar (hanya ada sedikit False Positives).
F-measure (F1-score): 0.9978829
F1-score adalah rata-rata harmonik dari presisi dan sensitivitas. Ini memberikan ukuran seimbang dari kemampuan model dalam mengenali kasus positif, dengan menggabungkan baik False Positives dan False Negatives. Nilai sebesar 99.78% menunjukkan kinerja model yang sangat baik dalam mengidentifikasi kasus positif.
Dengan metrik-metrik ini, dapat disimpulkan bahwa model yang digunakan memiliki kinerja yang sangat baik dalam mengklasifikasikan status pinjaman, dengan akurasi dan keseimbangan yang tinggi antara sensitivitas dan spesifisitas.
set.seed(2024)
pred_xgb_test <- xgboost_trained %>%
predict(new_data = test_df, type = "class")
pred_xgb_test
## # A tibble: 855 × 1
## .pred_class
## <fct>
## 1 " Approved"
## 2 " Rejected"
## 3 " Rejected"
## 4 " Approved"
## 5 " Rejected"
## 6 " Rejected"
## 7 " Approved"
## 8 " Approved"
## 9 " Approved"
## 10 " Rejected"
## # ℹ 845 more rows
## # A tibble: 855 × 2
## `.pred_ Approved` `.pred_ Rejected`
## <dbl> <dbl>
## 1 0.994 0.00563
## 2 0.00539 0.995
## 3 0.00539 0.995
## 4 0.704 0.296
## 5 0.00539 0.995
## 6 0.00539 0.995
## 7 0.982 0.0179
## 8 0.934 0.0662
## 9 0.988 0.0117
## 10 0.00539 0.995
## # ℹ 845 more rows
## # A tibble: 855 × 2
## .pred_class truth
## <fct> <fct>
## 1 " Approved" " Approved"
## 2 " Rejected" " Rejected"
## 3 " Rejected" " Rejected"
## 4 " Approved" " Approved"
## 5 " Rejected" " Rejected"
## 6 " Rejected" " Rejected"
## 7 " Approved" " Approved"
## 8 " Approved" " Approved"
## 9 " Approved" " Approved"
## 10 " Rejected" " Rejected"
## # ℹ 845 more rows
autoplot(confussion_matrix_testxgb, type = "heatmap") +
scale_fill_gradient(low = "#F4AFAB", high = "#EE847E")
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
Berdasarkan output confussion matrix, terdapat 7 kasus status
pinjaman sebenarnya rejected
tetapi model memprediksi
sebagai approved
. Selain itu terdapat 7 kasus di mana
status pinjaman sebenarnya approved
, tetapi model
memprediksi sebagai rejected
.
pred_xgb_test %>% #menambahkan kolom truth
mutate(truth=test_df$loan_status) %>% # evaluasi prediksi berdasarkan metrik
multi_metric(truth = truth,estimate = .pred_class)
## # A tibble: 4 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 accuracy binary 0.984
## 2 sensitivity binary 0.987
## 3 specificity binary 0.978
## 4 f_meas binary 0.987
Accuracy (Akurasi): 0.9836257
Akurasi adalah proporsi prediksi yang benar (baik positif maupun negatif) dari keseluruhan jumlah kasus. Dalam kasus ini, model memiliki akurasi sebesar 98.36%, yang berarti model memprediksi dengan benar 98.36% dari semua kasus.
Sensitivity (Sensitivitas) atau Recall: 0.9868421
Sensitivitas adalah proporsi kasus positif yang benar-benar teridentifikasi dengan benar oleh model. Sensitivitas sebesar 98.68% menunjukkan bahwa model berhasil mengidentifikasi semua kasus positif dengan benar (tidak ada False Negatives).
Specificity (Spesifisitas): 0.9783282
Spesifisitas adalah proporsi kasus negatif yang benar-benar teridentifikasi dengan benar oleh model. Spesifisitas sebesar 0.9783282 menunjukkan bahwa model berhasil mengidentifikasi sekitar 97.83% dari semua kasus negatif dengan benar (hanya ada sedikit False Positives).
F-measure (F1-score): 0.986842
F1-score adalah rata-rata harmonik dari presisi dan sensitivitas. Ini memberikan ukuran seimbang dari kemampuan model dalam mengenali kasus positif, dengan menggabungkan baik False Positives dan False Negatives. Nilai sebesar 98.68% menunjukkan kinerja model yang sangat baik dalam mengidentifikasi kasus positif.
Dengan metrik-metrik ini, dapat disimpulkan bahwa model yang digunakan memiliki kinerja yang sangat baik dalam mengklasifikasikan status pinjaman, dengan akurasi dan keseimbangan yang tinggi antara sensitivitas dan spesifisitas.
Pembagian data dilakukan dengan menggunakan metode Cross
Validation dengan fungsi vfold_cv
v = 10
untuk menentukan banyaknya fold yang
digunakan dalam Cross Validation adalah 10.
strata = "class"
metode sampling yang digunakan
adalah Stratified Random Sampling dengan stratifikasi berdasarkan kolom
class
yang berperan sebagai variabel respon.
Model Training and Evaluation akan dilakukan dengan bantuan fungsi
workflow_set
dan workflow_map
. Kedua fungsi
ini memungkinkan kita untuk melakukan pemilihan model terbaik
berdasarkan metrik-metrik tertentu.
Fungsi workflow_set
digunakan untuk menginput tahap
praproses data dan model apa yang digunakan. Sementara itu, fungsi
workflow_map
digunakan untuk menginputkan metode pembagian
data dan metrik sekaligus melakukan model training and
evaluation.
set.seed(2024)
mod_selection_trained <- workflow_set(preproc = list(no=no_prep, basic=basic_prep),
models = list(rf_mod,xgb_spec),
cross = TRUE ) %>%
workflow_map(fn = "fit_resamples",
resamples= folds,
metrics = multi_metric,
control = control_resamples(save_workflow = TRUE),
seed = 2045)
argumen preproc
digunakan untuk menginputkan tahap
praproses data
sintaksbasic=
digunakan untuk memberi nama pada
tahap praproses data
argumen models
digunakan untuk menginputkan model
random forest dan xgboost
argumen cross=TRUE
menandakan bahwa tahap praproses
data dan model dipasangkan secara kombinasi. Sebagai ilustrasi tahap
praproses data basic
akan dipasangkan dengan model decision
tree, random forest dan regresi logistik.
argumen cross=TRUE
menandakan bahwa tahap praproses
data dan model dipasangkan sesuai dengan urutanyan. Sebgai ilustrasi
tahap praproses data no
dipasangkan dengan decision. tree
dan tahap praproses data basic
akan dipasangkan dengan
random forest. Semetara model regresi logistik tidak punya tahap
praproses data sehingga akan menyebabkan error
.
argumen fn
digunakan untuk menentukan fungsi
tidymodels yang akan digunakan.
argumen resamples
digunakan untuk menginputkan
metode pembagian data
argumen metrics
digunakan untuk menginputkan
metrik-metrik.
untuk argumen control
bisa melihat help untuk lebih
jelas.
Hasil training and evaluation pada sintaks sebelumnya disimpan dalam
objek mod_selection_trained
. Selanjutnya kita akan
menampilkan hasilnya dengan menggunakan ranking.
custom_output <- function(data){
data %>%
mutate(method = map_chr(wflow_id, ~ str_split(.x, "_",simplify = TRUE)[1])) %>%
select(method,model,.metric,mean,std_err,rank)
}
mod_selection_result <- rank_results(mod_selection_trained,
rank_metric = "accuracy") %>%
custom_output()
mod_selection_result
## # A tibble: 16 × 6
## method model .metric mean std_err rank
## <chr> <chr> <chr> <dbl> <dbl> <int>
## 1 basic boost_tree accuracy 0.985 0.00120 1
## 2 basic boost_tree f_meas 0.988 0.000976 1
## 3 basic boost_tree sensitivity 0.988 0.00266 1
## 4 basic boost_tree specificity 0.980 0.00377 1
## 5 no boost_tree accuracy 0.985 0.00212 2
## 6 no boost_tree f_meas 0.988 0.00167 2
## 7 no boost_tree sensitivity 0.992 0.00224 2
## 8 no boost_tree specificity 0.972 0.00659 2
## 9 no rand_forest accuracy 0.981 0.00172 3
## 10 no rand_forest f_meas 0.985 0.00138 3
## 11 no rand_forest sensitivity 0.989 0.00253 3
## 12 no rand_forest specificity 0.968 0.00378 3
## 13 basic rand_forest accuracy 0.977 0.00174 4
## 14 basic rand_forest f_meas 0.982 0.00143 4
## 15 basic rand_forest sensitivity 0.980 0.00350 4
## 16 basic rand_forest specificity 0.972 0.00393 4
argumen rank_metric
digunakan untuk menentukan
metrik apa yang digunakan sebagai ranking.
fungsi custom_output
digunakan untuk mengkustomisasi
output yang dihasilkan. Fungsi ini bisa tidak perlu
dirubah-rubah.
mod_selection_result %>%
ggplot(aes(x = rank, y = mean, pch = method, col = model)) +
geom_point(cex = 3)+
facet_wrap(~.metric)+
theme_bw()
Dari visualisasi hasil perbandingan kedua metode diperoleh secara
keseluruhan metode XGboost lebih unggul dari Random Forest baik dari
segi accuracy
, f_means
,
sensitivity
, dan specificity
.
Setelah mendapatkan model terbaik kita bisa mengekstraknya model
tersebut kemudian melakukan training ulang dengan seluruh data yang
dimiliki menggunakan fungsi fit_best
berikut ini.
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Recipe
## Model: boost_tree()
##
## ── Preprocessor ────────────────────────────────────────────────────────────────
## 3 Recipe Steps
##
## • step_smotenc()
## • step_normalize()
## • step_dummy()
##
## ── Model ───────────────────────────────────────────────────────────────────────
## ##### xgb.Booster
## raw: 33 Kb
## call:
## xgboost::xgb.train(params = list(eta = 0.3, max_depth = 6, gamma = 0,
## colsample_bytree = 1, colsample_bynode = 1, min_child_weight = 1,
## subsample = 1), data = x$data, nrounds = 15, watchlist = x$watchlist,
## verbose = 0, nthread = 1, objective = "binary:logistic")
## params (as set within xgb.train):
## eta = "0.3", max_depth = "6", gamma = "0", colsample_bytree = "1", colsample_bynode = "1", min_child_weight = "1", subsample = "1", nthread = "1", objective = "binary:logistic", validate_parameters = "TRUE"
## xgb.attributes:
## niter
## callbacks:
## cb.evaluation.log()
## # of features: 13
## niter: 15
## nfeatures : 13
## evaluation_log:
## iter training_logloss
## 1 0.45327838
## 2 0.31964884
## ---
## 14 0.02840864
## 15 0.02581924
##
## ── Recipe ──────────────────────────────────────────────────────────────────────
##
## ── Inputs
## Number of variables by role
## outcome: 1
## predictor: 11
##
## ── Training information
## Training data contained 4269 data points and no incomplete rows.
##
## ── Operations
## • SMOTENC based on: loan_status | Trained
## • Centering and scaling for: no_of_dependents, income_annum, ... | Trained
## • Dummy variables from: education, self_employed | Trained
Untuk mengetahui peubah penjelas mana yang paling berkontribusi terhadap peubah respon, dilakukan perhitungan nilai feature importance dari peubah-peubah penjelas yang digunakan dalam pembentukan model.
plot_xgb_importance<- function(model,filter=10){
xgboost::xgb.importance(model = model) %>%
arrange(Gain) %>%
mutate(Feature=factor(Feature,levels=Feature)) %>%
slice_max(order_by = Gain,n = filter) %>%
ggplot(aes(Feature,Gain))+
geom_col(fill="orange")+
coord_flip()+
theme_classic()+
theme(axis.line.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() )+
scale_y_continuous(expand = c(0,0))
}
Berdasarkan plot tersebut, terlihat bahwa peubah yang memiliki peranan paling penting untuk menentukan apakah peminjam berpotensi memperoleh pinjaman adalah peubah cibil_score, loan_term, dan loan_amount.
Berdasarkan analisis feature importance, Cibil Score, Loan Term, dan Loan Amount adalah variabel paling penting dalam menentukan kemungkinan peminjam memperoleh pinjaman. - Semakin tinggi Cibil Score, semakin besar peluang peminjam mendapatkan pinjaman karena menunjukkan riwayat kredit yang baik. - Loan Term yang lebih pendek cenderung lebih disukai karena mengurangi risiko ketidakpastian pembayaran dalam jangka panjang. - Loan Amount yang diminta juga mempengaruhi keputusan, dengan jumlah yang lebih besar meningkatkan risiko bagi pemberi pinjaman. Oleh karena itu, lembaga keuangan dapat fokus pada peminjam dengan Cibil Score tinggi, menawarkan jangka waktu pinjaman yang lebih pendek, dan menerapkan penilaian kredit yang lebih ketat untuk jumlah pinjaman yang besar guna mengurangi risiko kredit macet.
Model | Accuracy | Sensitivity | Spesificity | F1-Score |
---|---|---|---|---|
Random Forest (Tanpa Penanganan) | 0.9810 | 0.9890 | 0.9677 | 0.9848 |
Random Forest (Dengan penanganan) | 0.9772 | 0.9804 | 0.9721 | 0.9817 |
XGBoost (Tanpa penanganan) | 0.9847 | 0.9924 | 0.9721 | 0.9878 |
XGBoost (Dengan penanganan) | 0.9852 | 0.9883 | 0.9801 | 0.9881 |
Model terbaik untuk memprediksi peminjam yang berpotensi untuk menerima pinjaman adalah model XGBoost dengan perlakuan menggunakan penanganan imbalanced data ukuran kebaikan model yang lebih tinggi dibanding Random Forest dari segi accuracy, sensitivity, spesificity, f1-score.
Peubah yang berperan penting untuk memprediksi peminjam yang berpotensi untuk menerima pinjaman adalah peubah Cibil Score, Loan Term, dan Loan Amount.