Prediksi Status Pengajuan Pinjaman

Dalam studi kasus ini, saya akan melakukan prediksi dari data pinjaman nasabah. Kemudian mencari indikator apa saja yang dapat digunakan untuk memprediksi dari pengajuan pinjaman nasabah tersebut mendapatkan persetujuan atau penolakan. Proses kelayakan pinjaman (secara real-time) berdasarkan detail nasabah yang diberikan, saat mengisi formulir aplikasi online dari jenis kelamin, status perkawinan, pendidikan, jumlah tanggungan, pendapatan dan rincian lainnya yang disertakan.
Algoritma yang akan saya gunakan yaitu menggunakan logistik regression dan k-nearest neighbor yang termasuk dalam supervised learning.

Library

library(dplyr)
library(gtools)
library(gmodels)
library(ggplot2)
library(class)
library(tidyr)

Data Preparation

Import Data

loan <- read.csv("datainput/df1_loan.csv", stringsAsFactors = T)
head(loan)
#>   X  Loan_ID Gender Married Dependents    Education Self_Employed
#> 1 0 LP001002   Male      No          0     Graduate            No
#> 2 1 LP001003   Male     Yes          1     Graduate            No
#> 3 2 LP001005   Male     Yes          0     Graduate           Yes
#> 4 3 LP001006   Male     Yes          0 Not Graduate            No
#> 5 4 LP001008   Male      No          0     Graduate            No
#> 6 5 LP001011   Male     Yes          2     Graduate           Yes
#>   ApplicantIncome CoapplicantIncome LoanAmount Loan_Amount_Term Credit_History
#> 1            5849                 0         NA              360              1
#> 2            4583              1508        128              360              1
#> 3            3000                 0         66              360              1
#> 4            2583              2358        120              360              1
#> 5            6000                 0        141              360              1
#> 6            5417              4196        267              360              1
#>   Property_Area Loan_Status Total_Income
#> 1         Urban           Y      $5849.0
#> 2         Rural           N      $6091.0
#> 3         Urban           Y      $3000.0
#> 4         Urban           Y      $4941.0
#> 5         Urban           Y      $6000.0
#> 6         Urban           Y      $9613.0

⚙️ Menghilangkan simbol $ dari kolom total pendapatan.

loan$Total_Income <-  sub("([.])|[[:punct:]]", "\\1", as.matrix(loan$Total_Income))
loan$Total_Income <- as.numeric(loan$Total_Income)
loan %>% head()
#>   X  Loan_ID Gender Married Dependents    Education Self_Employed
#> 1 0 LP001002   Male      No          0     Graduate            No
#> 2 1 LP001003   Male     Yes          1     Graduate            No
#> 3 2 LP001005   Male     Yes          0     Graduate           Yes
#> 4 3 LP001006   Male     Yes          0 Not Graduate            No
#> 5 4 LP001008   Male      No          0     Graduate            No
#> 6 5 LP001011   Male     Yes          2     Graduate           Yes
#>   ApplicantIncome CoapplicantIncome LoanAmount Loan_Amount_Term Credit_History
#> 1            5849                 0         NA              360              1
#> 2            4583              1508        128              360              1
#> 3            3000                 0         66              360              1
#> 4            2583              2358        120              360              1
#> 5            6000                 0        141              360              1
#> 6            5417              4196        267              360              1
#>   Property_Area Loan_Status Total_Income
#> 1         Urban           Y         5849
#> 2         Rural           N         6091
#> 3         Urban           Y         3000
#> 4         Urban           Y         4941
#> 5         Urban           Y         6000
#> 6         Urban           Y         9613

Data Cleansing

🧮 Mengecek tipe data

str(loan)
#> 'data.frame':    500 obs. of  15 variables:
#>  $ X                : int  0 1 2 3 4 5 6 7 8 9 ...
#>  $ Loan_ID          : Factor w/ 500 levels "LP001002","LP001003",..: 1 2 3 4 5 6 7 8 9 10 ...
#>  $ Gender           : Factor w/ 3 levels "","Female","Male": 3 3 3 3 3 3 3 3 3 3 ...
#>  $ Married          : Factor w/ 3 levels "","No","Yes": 2 3 3 3 2 3 3 3 3 3 ...
#>  $ Dependents       : Factor w/ 5 levels "","0","1","2",..: 2 3 2 2 2 4 2 5 4 3 ...
#>  $ Education        : Factor w/ 2 levels "Graduate","Not Graduate": 1 1 1 2 1 1 2 1 1 1 ...
#>  $ Self_Employed    : Factor w/ 3 levels "","No","Yes": 2 2 3 2 2 3 2 2 2 2 ...
#>  $ ApplicantIncome  : int  5849 4583 3000 2583 6000 5417 2333 3036 4006 12841 ...
#>  $ CoapplicantIncome: num  0 1508 0 2358 0 ...
#>  $ LoanAmount       : num  NA 128 66 120 141 267 95 158 168 349 ...
#>  $ Loan_Amount_Term : num  360 360 360 360 360 360 360 360 360 360 ...
#>  $ Credit_History   : num  1 1 1 1 1 1 1 0 1 1 ...
#>  $ Property_Area    : Factor w/ 3 levels "Rural","Semiurban",..: 3 1 3 3 3 3 3 2 3 2 ...
#>  $ Loan_Status      : Factor w/ 2 levels "N","Y": 2 1 2 2 2 2 2 1 2 1 ...
#>  $ Total_Income     : num  5849 6091 3000 4941 6000 ...

⚙️ Mengubah tipe data dan menghapus kolom yang tidak digunakan:

library(dplyr)
loan_clean <- loan %>% 
  select(-c(X, Loan_ID)) %>% 
  mutate(Credit_History = as.factor(Credit_History))
loan_clean %>% head()
#>   Gender Married Dependents    Education Self_Employed ApplicantIncome
#> 1   Male      No          0     Graduate            No            5849
#> 2   Male     Yes          1     Graduate            No            4583
#> 3   Male     Yes          0     Graduate           Yes            3000
#> 4   Male     Yes          0 Not Graduate            No            2583
#> 5   Male      No          0     Graduate            No            6000
#> 6   Male     Yes          2     Graduate           Yes            5417
#>   CoapplicantIncome LoanAmount Loan_Amount_Term Credit_History Property_Area
#> 1                 0         NA              360              1         Urban
#> 2              1508        128              360              1         Rural
#> 3                 0         66              360              1         Urban
#> 4              2358        120              360              1         Urban
#> 5                 0        141              360              1         Urban
#> 6              4196        267              360              1         Urban
#>   Loan_Status Total_Income
#> 1           Y         5849
#> 2           N         6091
#> 3           Y         3000
#> 4           Y         4941
#> 5           Y         6000
#> 6           Y         9613
str(loan_clean)
#> 'data.frame':    500 obs. of  13 variables:
#>  $ Gender           : Factor w/ 3 levels "","Female","Male": 3 3 3 3 3 3 3 3 3 3 ...
#>  $ Married          : Factor w/ 3 levels "","No","Yes": 2 3 3 3 2 3 3 3 3 3 ...
#>  $ Dependents       : Factor w/ 5 levels "","0","1","2",..: 2 3 2 2 2 4 2 5 4 3 ...
#>  $ Education        : Factor w/ 2 levels "Graduate","Not Graduate": 1 1 1 2 1 1 2 1 1 1 ...
#>  $ Self_Employed    : Factor w/ 3 levels "","No","Yes": 2 2 3 2 2 3 2 2 2 2 ...
#>  $ ApplicantIncome  : int  5849 4583 3000 2583 6000 5417 2333 3036 4006 12841 ...
#>  $ CoapplicantIncome: num  0 1508 0 2358 0 ...
#>  $ LoanAmount       : num  NA 128 66 120 141 267 95 158 168 349 ...
#>  $ Loan_Amount_Term : num  360 360 360 360 360 360 360 360 360 360 ...
#>  $ Credit_History   : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 1 2 2 ...
#>  $ Property_Area    : Factor w/ 3 levels "Rural","Semiurban",..: 3 1 3 3 3 3 3 2 3 2 ...
#>  $ Loan_Status      : Factor w/ 2 levels "N","Y": 2 1 2 2 2 2 2 1 2 1 ...
#>  $ Total_Income     : num  5849 6091 3000 4941 6000 ...

✏️ Pastikan data tidak ada missing value, karena dapat menyebabkan error ketika dimasukkan pada model

colSums(is.na(loan_clean))
#>            Gender           Married        Dependents         Education 
#>                 0                 0                 0                 0 
#>     Self_Employed   ApplicantIncome CoapplicantIncome        LoanAmount 
#>                 0                 0                 0                18 
#>  Loan_Amount_Term    Credit_History     Property_Area       Loan_Status 
#>                14                41                 0                 0 
#>      Total_Income 
#>                 0

⚙️ Menghapus semua baris data yang memiliki nilai hilang:

loan_clean <- loan_clean %>% 
  filter(complete.cases(.)) 
colSums(is.na(loan_clean))
#>            Gender           Married        Dependents         Education 
#>                 0                 0                 0                 0 
#>     Self_Employed   ApplicantIncome CoapplicantIncome        LoanAmount 
#>                 0                 0                 0                 0 
#>  Loan_Amount_Term    Credit_History     Property_Area       Loan_Status 
#>                 0                 0                 0                 0 
#>      Total_Income 
#>                 0

Exploratory Data Analysis

Check pattern data

summary(loan_clean)
#>     Gender    Married   Dependents        Education   Self_Employed
#>        :  8      :  2     :  9     Graduate    :342      : 21      
#>  Female: 77   No :154   0 :245     Not Graduate: 86   No :352      
#>  Male  :343   Yes:272   1 : 68                        Yes: 55      
#>                         2 : 71                                     
#>                         3+: 35                                     
#>                                                                    
#>  ApplicantIncome CoapplicantIncome   LoanAmount    Loan_Amount_Term
#>  Min.   :  150   Min.   :    0     Min.   : 17.0   Min.   : 36.0   
#>  1st Qu.: 2880   1st Qu.:    0     1st Qu.:100.0   1st Qu.:360.0   
#>  Median : 3863   Median : 1062     Median :127.5   Median :360.0   
#>  Mean   : 5627   Mean   : 1503     Mean   :144.0   Mean   :342.8   
#>  3rd Qu.: 5818   3rd Qu.: 2212     3rd Qu.:162.0   3rd Qu.:360.0   
#>  Max.   :81000   Max.   :20000     Max.   :700.0   Max.   :480.0   
#>  Credit_History   Property_Area Loan_Status  Total_Income  
#>  0: 63          Rural    :123   N:133       Min.   : 1442  
#>  1:365          Semiurban:167   Y:295       1st Qu.: 4166  
#>                 Urban    :138               Median : 5274  
#>                                             Mean   : 7131  
#>                                             3rd Qu.: 7544  
#>                                             Max.   :81000

Check class-imbalance

prop.table(table(loan_clean$Loan_Status))
#> 
#>         N         Y 
#> 0.3107477 0.6892523

📝 Jika dilihat dari proporsi kelas target 31:69, menunjukkan proporsi yang masih seimbang.

Logistic Regression

Cross Validation

Jika kita ingin melakukan sebuah prediksi, maka kita tidak disarankan melihat nilai error pada data yang digunakan untuk melatih model, karena itu hanya menunjukkan bahwa model dapat memprediksi data lama tetapi belum tentu dapat memprediksi data baru.

Data yang digunakan untuk melatih model kita sebut dengan data train, sedangkan data yang digunakan untuk menguji model disebut dengan data test.

RNGkind(sample.kind = "Rounding")
set.seed(100)
index_loan <- sample(nrow(loan_clean), nrow(loan_clean)*0.8)
loan_train <- loan_clean[index_loan,]
loan_test <- loan_clean[-index_loan,]
# re-check class imbalance
loan_train$Loan_Status %>% table() %>% prop.table()
#> .
#>         N         Y 
#> 0.3157895 0.6842105

Proporsi kelas yang balance penting untuk data train karena kita akan melatih model menggunakan data train.

Build Model

Melakukan permodelan menggunakan regresi logistik. Permodelan menggunakan fungsi glm() dalam memodelkan menggunakan regresi logistik. Variabel yang digunakan adalah beberapa variabel yang kita anggap mempengaruhi target variabel, dimana variabel target menjadi variabel responnya.

names(loan_train)
#>  [1] "Gender"            "Married"           "Dependents"       
#>  [4] "Education"         "Self_Employed"     "ApplicantIncome"  
#>  [7] "CoapplicantIncome" "LoanAmount"        "Loan_Amount_Term" 
#> [10] "Credit_History"    "Property_Area"     "Loan_Status"      
#> [13] "Total_Income"
# model seluruh prediktor
model_loan <- glm(formula = Loan_Status ~ .,
                 data = loan_train,
                 family = "binomial")
summary(model_loan)
#> 
#> Call:
#> glm(formula = Loan_Status ~ ., family = "binomial", data = loan_train)
#> 
#> Coefficients: (1 not defined because of singularities)
#>                             Estimate    Std. Error z value        Pr(>|z|)    
#> (Intercept)              14.74685166 1024.36604916   0.014        0.988514    
#> GenderFemale             -1.16122739    1.43541544  -0.809        0.418525    
#> GenderMale               -0.90330871    1.38281419  -0.653        0.513602    
#> MarriedNo               -14.55494589 1024.36475250  -0.014        0.988663    
#> MarriedYes              -14.47521371 1024.36474297  -0.014        0.988726    
#> Dependents0               0.05693535    1.22163230   0.047        0.962827    
#> Dependents1              -0.30302500    1.24789860  -0.243        0.808138    
#> Dependents2               0.70588367    1.26678117   0.557        0.577373    
#> Dependents3+              0.73200150    1.33193621   0.550        0.582610    
#> EducationNot Graduate    -0.56935683    0.38448150  -1.481        0.138648    
#> Self_EmployedNo          -0.20570568    0.72738217  -0.283        0.777328    
#> Self_EmployedYes         -0.46939149    0.82793323  -0.567        0.570752    
#> ApplicantIncome           0.00002003    0.00002918   0.687        0.492366    
#> CoapplicantIncome         0.00000401    0.00008334   0.048        0.961627    
#> LoanAmount               -0.00412445    0.00236264  -1.746        0.080864 .  
#> Loan_Amount_Term         -0.00536540    0.00294323  -1.823        0.068309 .  
#> Credit_History1           4.02497406    0.59711510   6.741 0.0000000000158 ***
#> Property_AreaSemiurban    1.24404024    0.37379485   3.328        0.000874 ***
#> Property_AreaUrban        0.22690449    0.36158906   0.628        0.530318    
#> Total_Income                      NA            NA      NA              NA    
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> (Dispersion parameter for binomial family taken to be 1)
#> 
#>     Null deviance: 426.58  on 341  degrees of freedom
#> Residual deviance: 302.09  on 323  degrees of freedom
#> AIC: 340.09
#> 
#> Number of Fisher Scoring iterations: 14
# model menggunakan stepwise
model_step <- step(object = model_loan, direction="backward")
#> Start:  AIC=340.09
#> Loan_Status ~ Gender + Married + Dependents + Education + Self_Employed + 
#>     ApplicantIncome + CoapplicantIncome + LoanAmount + Loan_Amount_Term + 
#>     Credit_History + Property_Area + Total_Income
#> 
#> 
#> Step:  AIC=340.09
#> Loan_Status ~ Gender + Married + Dependents + Education + Self_Employed + 
#>     ApplicantIncome + CoapplicantIncome + LoanAmount + Loan_Amount_Term + 
#>     Credit_History + Property_Area
#> 
#>                     Df Deviance    AIC
#> - Self_Employed      2   302.52 336.52
#> - Gender             2   302.97 336.97
#> - Married            2   303.06 337.06
#> - Dependents         4   307.16 337.16
#> - CoapplicantIncome  1   302.09 338.09
#> - ApplicantIncome    1   302.55 338.55
#> <none>                   302.09 340.09
#> - Education          1   304.23 340.23
#> - LoanAmount         1   305.17 341.17
#> - Loan_Amount_Term   1   306.01 342.01
#> - Property_Area      2   315.69 349.69
#> - Credit_History     1   391.68 427.68
#> 
#> Step:  AIC=336.52
#> Loan_Status ~ Gender + Married + Dependents + Education + ApplicantIncome + 
#>     CoapplicantIncome + LoanAmount + Loan_Amount_Term + Credit_History + 
#>     Property_Area
#> 
#>                     Df Deviance    AIC
#> - Gender             2   303.35 333.35
#> - Married            2   303.57 333.57
#> - Dependents         4   307.90 333.90
#> - CoapplicantIncome  1   302.52 334.52
#> - ApplicantIncome    1   302.96 334.96
#> <none>                   302.52 336.52
#> - Education          1   304.63 336.63
#> - LoanAmount         1   305.51 337.51
#> - Loan_Amount_Term   1   306.47 338.47
#> - Property_Area      2   316.31 346.31
#> - Credit_History     1   392.97 424.97
#> 
#> Step:  AIC=333.35
#> Loan_Status ~ Married + Dependents + Education + ApplicantIncome + 
#>     CoapplicantIncome + LoanAmount + Loan_Amount_Term + Credit_History + 
#>     Property_Area
#> 
#>                     Df Deviance    AIC
#> - Married            2   304.57 330.57
#> - Dependents         4   309.27 331.27
#> - CoapplicantIncome  1   303.36 331.36
#> - ApplicantIncome    1   303.93 331.93
#> <none>                   303.35 333.35
#> - Education          1   305.36 333.36
#> - LoanAmount         1   306.14 334.14
#> - Loan_Amount_Term   1   307.49 335.49
#> - Property_Area      2   317.03 343.03
#> - Credit_History     1   394.06 422.06
#> 
#> Step:  AIC=330.57
#> Loan_Status ~ Dependents + Education + ApplicantIncome + CoapplicantIncome + 
#>     LoanAmount + Loan_Amount_Term + Credit_History + Property_Area
#> 
#>                     Df Deviance    AIC
#> - CoapplicantIncome  1   304.58 328.58
#> - ApplicantIncome    1   305.13 329.13
#> - Dependents         4   311.19 329.19
#> <none>                   304.57 330.57
#> - Education          1   306.65 330.65
#> - LoanAmount         1   307.17 331.17
#> - Loan_Amount_Term   1   308.52 332.52
#> - Property_Area      2   318.60 340.60
#> - Credit_History     1   395.61 419.61
#> 
#> Step:  AIC=328.58
#> Loan_Status ~ Dependents + Education + ApplicantIncome + LoanAmount + 
#>     Loan_Amount_Term + Credit_History + Property_Area
#> 
#>                    Df Deviance    AIC
#> - ApplicantIncome   1   305.14 327.14
#> - Dependents        4   311.24 327.24
#> <none>                  304.58 328.58
#> - Education         1   306.70 328.70
#> - LoanAmount        1   307.39 329.39
#> - Loan_Amount_Term  1   308.55 330.55
#> - Property_Area     2   318.77 338.77
#> - Credit_History    1   395.63 417.63
#> 
#> Step:  AIC=327.14
#> Loan_Status ~ Dependents + Education + LoanAmount + Loan_Amount_Term + 
#>     Credit_History + Property_Area
#> 
#>                    Df Deviance    AIC
#> - Dependents        4   311.90 325.90
#> <none>                  305.14 327.14
#> - Education         1   307.42 327.42
#> - LoanAmount        1   307.52 327.52
#> - Loan_Amount_Term  1   309.74 329.74
#> - Property_Area     2   319.27 337.27
#> - Credit_History    1   395.71 415.71
#> 
#> Step:  AIC=325.9
#> Loan_Status ~ Education + LoanAmount + Loan_Amount_Term + Credit_History + 
#>     Property_Area
#> 
#>                    Df Deviance    AIC
#> - LoanAmount        1   313.65 325.65
#> - Education         1   313.84 325.84
#> <none>                  311.90 325.90
#> - Loan_Amount_Term  1   316.81 328.81
#> - Property_Area     2   324.90 334.90
#> - Credit_History    1   400.04 412.04
#> 
#> Step:  AIC=325.65
#> Loan_Status ~ Education + Loan_Amount_Term + Credit_History + 
#>     Property_Area
#> 
#>                    Df Deviance    AIC
#> - Education         1   314.98 324.98
#> <none>                  313.65 325.65
#> - Loan_Amount_Term  1   318.20 328.20
#> - Property_Area     2   327.16 335.16
#> - Credit_History    1   404.00 414.00
#> 
#> Step:  AIC=324.98
#> Loan_Status ~ Loan_Amount_Term + Credit_History + Property_Area
#> 
#>                    Df Deviance    AIC
#> <none>                  314.98 324.98
#> - Loan_Amount_Term  1   319.14 327.14
#> - Property_Area     2   329.45 335.45
#> - Credit_History    1   409.76 417.76
summary(model_step)
#> 
#> Call:
#> glm(formula = Loan_Status ~ Loan_Amount_Term + Credit_History + 
#>     Property_Area, family = "binomial", data = loan_train)
#> 
#> Coefficients:
#>                         Estimate Std. Error z value         Pr(>|z|)    
#> (Intercept)            -1.336430   1.042366  -1.282         0.199803    
#> Loan_Amount_Term       -0.005124   0.002707  -1.892         0.058435 .  
#> Credit_History1         3.886297   0.561857   6.917 0.00000000000462 ***
#> Property_AreaSemiurban  1.267555   0.359440   3.526         0.000421 ***
#> Property_AreaUrban      0.291414   0.333679   0.873         0.382480    
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> (Dispersion parameter for binomial family taken to be 1)
#> 
#>     Null deviance: 426.58  on 341  degrees of freedom
#> Residual deviance: 314.98  on 337  degrees of freedom
#> AIC: 324.98
#> 
#> Number of Fisher Scoring iterations: 5

💡 Step Wise (direction) - Memilih prediktor mana yang akan digunakan berdasarkan nilai AIC

model_loan$aic
#> [1] 340.091
model_step$aic
#> [1] 324.9792

📈 Dari hasil di atas, dapat dilihat bahwa model yg paling baik digunakan adalah model_step, karena memiliki nilai AIC paling kecil.

Predict

Dengan menggunakan model_step hasil dari stepwise, kita akan coba prediksi menggunakan data test yang sudah kita miliki dengan fungsi predict(object model, newdata, type)

loan_pred <- predict(object = model_step, newdata = loan_test, type = "response")
loan_pred_label <- as.factor(ifelse(loan_pred > 0.5, "Y", "N")) 
table(loan_pred_label)
#> loan_pred_label
#>  N  Y 
#> 14 72
table(predict = loan_pred_label,
              actual = loan_test$Loan_Status)
#>        actual
#> predict  N  Y
#>       N 12  2
#>       Y 13 59

Model Evaluation

Setelah dilakukan prediksi menggunakan model, masih ada saja prediksi yang salah. Pada klasifikasi, kita mengevaluasi model berdasarkan confusion matrix

# confusion matrix
library(caret)

confusionMatrix(data = loan_pred_label,
                reference = loan_test$Loan_Status, 
                positive = "Y")
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  N  Y
#>          N 12  2
#>          Y 13 59
#>                                          
#>                Accuracy : 0.8256         
#>                  95% CI : (0.7287, 0.899)
#>     No Information Rate : 0.7093         
#>     P-Value [Acc > NIR] : 0.009537       
#>                                          
#>                   Kappa : 0.5139         
#>                                          
#>  Mcnemar's Test P-Value : 0.009823       
#>                                          
#>             Sensitivity : 0.9672         
#>             Specificity : 0.4800         
#>          Pos Pred Value : 0.8194         
#>          Neg Pred Value : 0.8571         
#>              Prevalence : 0.7093         
#>          Detection Rate : 0.6860         
#>    Detection Prevalence : 0.8372         
#>       Balanced Accuracy : 0.7236         
#>                                          
#>        'Positive' Class : Y              
#> 

💡 Ada 4 metriks performa model:
1. Accuracy: Seberapa banyak yang benar diprediksi dari keseluruhan data (positif maupun negatif).
2. Sensitivity/Recall: Seberapa banyak yang benar diprediksi positif, dari yang aktualnya positif.
3. Specificity: Seberapa mampu proporsi model menebak yang benar.
4. Post Pred Value/Precision: Seberapa banyak yang benar diprediksi positif, dari yang terprediksi positif.

📝 Berdasarkan hasil Confusion Matrix, dapat disimpulkan bahwa kemampuan model dalam memprediksi target Y (status pinjaman disetujui atau tidak) adalah sebesar 82,5%. Sedangkan berdasarkan dari data aktual nasabah yang status pinjamannya tidak disetujui, model mampu menebak dengan benar sebesar 48%. Model tersebut mampu memprediksi sebesar 96,7% waktu dengan benar dari seluruh data aktual nasabah yang menerima status pinjaman disetujui. Model menebak dengan benar kelas positif sebesar 81,9% berdasarkan keseluruhan hasil prediksi.

Model K-Nearest Neighboor (K-NN)

Cross Validation

set.seed(100)
index_loan <- sample(nrow(loan_clean), nrow(loan_clean)*0.8)
loan_train <- loan_clean[index_loan,]
loan_test <- loan_clean[-index_loan,]

✏️ Model K-NN dipisahkan antara prediktor dan label (target variabelnya).

x = prediktor
y = target

library(dplyr)
# prediktor
loan_train_x <- loan_train %>% select_if(is.numeric)
loan_test_x <- loan_test %>% select_if(is.numeric)

# target
loan_train_y <- loan_train[,"Loan_Status"]
loan_test_y <- loan_test[,"Loan_Status"]

Splitting Train-Test

Langkah selanjutnya yaitu melakukkan splitting train data test. Tujuannya data test juga harus discaling menggunakan parameter dari data train (karena menganggap data test adalah unseen data).

train_x_scaled <- scale(loan_train_x)
test_x_scaled <- scale(loan_test_x,
                center = attr(train_x_scaled,"scaled:center"), 
                scale = attr(train_x_scaled, "scaled:scale")) 

Predict

sqrt(nrow(loan_train_x))
#> [1] 18.49324

K optimum = 18

💡 Parameter pada fungsi knn():
- train : data train, prediktor, yang sudah discaling, tipe numerik
- test : data test, prediktor, yang sudah discaling, tipe numerik
- cl : data train, label (target) aktual (kategorikal)
- k : nilai k yang ditentukan

library(class)
loan_pred <- knn(train = train_x_scaled,
                 test = test_x_scaled,
                 cl = loan_train_y,
                 k = 18)

loan_pred
#>  [1] Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
#> [39] Y Y Y Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y Y Y N Y N
#> [77] Y Y Y Y Y Y Y Y Y Y
#> Levels: N Y

Model Evaluation

library(caret)
confusionMatrix(data = loan_pred, reference = loan_test_y, positive = "Y")
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  N  Y
#>          N  4  0
#>          Y 21 61
#>                                          
#>                Accuracy : 0.7558         
#>                  95% CI : (0.6513, 0.842)
#>     No Information Rate : 0.7093         
#>     P-Value [Acc > NIR] : 0.2044         
#>                                          
#>                   Kappa : 0.2127         
#>                                          
#>  Mcnemar's Test P-Value : 0.00001275     
#>                                          
#>             Sensitivity : 1.0000         
#>             Specificity : 0.1600         
#>          Pos Pred Value : 0.7439         
#>          Neg Pred Value : 1.0000         
#>              Prevalence : 0.7093         
#>          Detection Rate : 0.7093         
#>    Detection Prevalence : 0.9535         
#>       Balanced Accuracy : 0.5800         
#>                                          
#>        'Positive' Class : Y              
#> 

📝 Berdasarkan hasil Confusion Matrix, dapat disimpulkan bahwa kemampuan model dalam memprediksi target Y (status pinjaman disetujui atau tidak) adalah sebesar 75,5%. Sedangkan berdasarkan data aktual dari nasabah yang status pinjamannya tidak disetujui, model mampu menebak dengan benar sebesar 16%. Model tersebut mampu memprediksi sebesar 100% waktu dengan benar dari seluruh data aktual masyarakat yang menerima status pinjaman disetujui. Model menebak dengan benar kelas positif sebesar 74,3% berdasarkan keseluruhan hasil prediksi.

Conclusion

Dalam hal ini tindakan yang akan saya berikan kepada calon nasabah untuk memprediksi apakah pinjamannya akan disetujui atau tidak? Yaitu, dengan menggunakan metric recall. Karena saya tidak ingin model memprediksi pelanggan yang kemungkinan besar tidak akan disetujui, namun memperkirakan bahwa hal tersebut akan merugikan perusahaan dan menambah resiko.

Jika dibandingkan dengan dua model yaitu model regresi logistik dan K-Nearest Neighbor, maka model yang mampu memprediksi secara tepat data aktual pelanggan yang disetujui lebih baik menggunakan model K-Nearest Neighbor, karena memiliki nilai recall sebesar 100%. Jika dibandingkan dengan model regresi logistik yang memiliki nilai sebesar 96,7%. Jadi, dengan menggunakan model ini, perusahaan dapat mengurangi resiko pemberian pinjaman kepada calon nasabah.