Mempelajari dan mengembangkan algoritma klasifikasi dari awal, dan menyelidiki dasar matematika yang mendukung logistic regression dan algoritma nearest neighbors, dua algoritma paling serbaguna yang banyak digunakan saat ini.
glm
Dalam Machine Learning dan statistik, Classification / klasifikasi adalah bentuk pendekatan Supervised Learning untuk memprediksi label dari suatu data dengan tipe kategorikal.
Ide dari logistic regression mulanya berangkat dari model linear regression. Bedanya:
-Inf to Inf
0 to 1
Pada dasarnya, ketika kita melakukan klasifikasi, kita menghitung probabilitas.
\[P(yes) = \frac{n(yes)}{n(yes) + n(no)}\]
Dimana:
P
= Probabilitasn
= Jumlah kejadianKindly Reminder: Range dari Probability: 0 - 1
Case study:
Saat H-2 Lebaran, terdapat 100 penerbangan di Soekarno-Hatta airport, dari 100 penerbangan tersebut, terdapat 20 penerbangan delay.
Diketahui:
Penerbangan delay: 20 penerbangan
Penerbangan tidak delay: 80 penerbangan
Berapakah probability suatu penerbangan delay di Soekarno-Hatta?
# Please type your answer
<- 20 / 100
p_delay p_delay
## [1] 0.2
# Please type your answer
<- 80 / 100
p_no_delay p_no_delay
## [1] 0.8
Odds merupakan bentuk lain dari probabilitas, yaitu perbandingan antara probabilitas kejadian terjadi/probabilitas kejadian tidak terjadi.
\[Odds(yes) = \frac{P(yes)}{1-P(yes)}\]
Dimana:
P
= ProbabilitasCase study:
Saat H-2 Lebaran, terdapat 100 penerbangan di Soekarno-Hatta airport, dari 100 penerbangan tersebut, terdapat 20 penerbangan delay.
# Odds tepat waktu dibandingkan dengan peluang delay
/(1 - p_no_delay) p_no_delay
## [1] 4
0.8 / (1 - 0.8)
## [1] 4
Interpretasi: Odds penerbangan tepat waktu itu 4 KALI lebih mungkin dibandingkan penerbangan tidak tepat waktu (delay).
Range dari Odds: 0 - Inf
Log of odds adalah nilai odds yang dilogaritmikan
\[LogOfOdds = log(\frac{P}{1-P})\]
Case Study
Disini kita sudah mengetahu bahwa Odds dari penerbangan tepat waktu adalah 4 kali lebih mungkin dari penerbangan tidak tepat waktu.
# Please type your answer
log(4)
## [1] 1.386294
Additional Notes:
Follow up question dari additional notes: > Lalu bagaimana ketika kita ingin mengubah nilai dari Log of Odds menjadi nilai odds agar bisa di-interpretasikan?
Untuk mengubah Log of Odds ->
Odds, kita dapat menfaatkan exponential. Di R, sudah
tersedia sebuah fungsi bernama exp()
. Mari kita coba untuk
menggubank fungsi tersebut untuk mengembalikan nilai Oddsnya.
# Please type your answer
exp(1.386294)
## [1] 3.999999
Additional:
\[P = \frac{Odds}{1+Odds}\]
# Please type your answer
4 / (1+4)
## [1] 0.8
Sebelumnya kita sudah belajar, bagaimana mengtransformasi nilai
Odds menjadi Log of Odds. Sekarang
kita akan mencoba mempelajari, bagaimana mengtransformasi nilai
Probability menjadi Log of Odds. Untuk
melakukan transformasi tersebut, kita dapat memanfaatkan fungsi
logit()
dari library(gtools)
.
#install.packages("gtools")
library(gtools)
Case Study
p_no_delay
, mari kita coba ubah nilai
probabilitynya dari object tersebut.# Please type your answer
p_no_delay
## [1] 0.8
logit(p_no_delay)
## [1] 1.386294
Follow up question: > Lalu bagaimana ketika kita ingin mengubah nilai dari Log of Odds menjadi nilai probability agar bisa di-interpretasikan?
Untuk mengubah Log of Odds ke peluang dengan fungsi
inv.logit()
.
# Please type your answer
inv.logit(1.386294)
## [1] 0.7999999
Fun Fact :D Fungsi inv.logit()
sering juga
disebut sigmoidal logistic function.
# sigmoid function
curve(inv.logit(x), from = -10, to=10,
xlab = "Log of Odds",
ylab = "Probabolity")
Anda adalah seorang Data Scientist di Universitas Algoritma. Anda ditugaskan untuk memprediksi status kelulusan siswa dengan honors (cumlaude).
# Please run the code down below
library(dplyr)
<- read.csv("data_input/sample.csv") %>%
honors select(-femalexmath) %>%
mutate(female = as.factor(female),
hon = as.factor(hon))
head(honors)
Deskripsi variabel:
female
: gender of student (1 for female, 0 for
male)read
: score in reading testwrite
: score in writing testmath
: score in math testhon
: status of graduating in honors (1 for honors, 0
for not honors)Untuk membuat model logistic regression bisa menggunakan fungsi
glm()
, terdapat 3 paramater yang kita gunakan yaitu
formula
: tempat mendefinisikan target dan predictor
(y/target ~ x/predictor)data
: data yang digunakan untuk membuat modelfamily
: gunakan binomial bila ingin
menggunakan logistic regression pada pemodelan iniSyntax:
glm(formula = target ~ predictor, data = , family = binomial)
Pertama kita akan mencoba untuk membuat sebuah model tanpa prediktor,
lalu simpan ke sebuah objet bernama model_wo_predictor
.
Diketahui:
hon
<- glm(formula = hon ~ 1, data = honors, family = binomial) model_wo_predictor
Untuk melihat hasil dari model yang telah kita buat, kita dapat
memanfaatkan fungsi summary()
.
summary(model_wo_predictor)
##
## Call:
## glm(formula = hon ~ 1, family = binomial, data = honors)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.7497 -0.7497 -0.7497 -0.7497 1.6772
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.1255 0.1644 -6.845 0.00000000000762 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 222.71 on 199 degrees of freedom
## Residual deviance: 222.71 on 199 degrees of freedom
## AIC: 224.71
##
## Number of Fisher Scoring iterations: 4
Jika kita lihat dari hasil model yang telah dibuat, kita mengetahui bahwa model tanpa prediktor memiliki intercept sebesar -1.1255
Follow up question: > Dari mana nilai intercept/koefisien tersebut?
# proportion
table(honors$hon)
##
## 0 1
## 151 49
# peluang tidak mendapatkan honors
<- 151/(151+49)
p_0 p_0
## [1] 0.755
# log of odds
logit(p_0)
## [1] 1.12546
# peluang mendapatkan honors
<- 49/(49 +151)
p_1 p_1
## [1] 0.245
# log of odds
logit(p_1)
## [1] -1.12546
Y = B0 + B1.X1 Y = -1.125
Dari pembuktian di atas, kita mengetahui bahwa nilai koefisien merupakan nilai log of odds.
Pada tahapan berikutnya kita akan mencoba untuk membuat model dengan keseluruhan prediktor.
# Please type your answer
<- glm(formula = hon ~ ., data = honors, family = binomial) model_all_predictor
summary(model_all_predictor)
##
## Call:
## glm(formula = hon ~ ., family = binomial, data = honors)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.000245237 -0.000000021 -0.000000021 -0.000000021 0.000176979
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2176.87191 282900.61006 -0.008 0.994
## female1 -4.44248 18078.08748 0.000 1.000
## read 0.07478 489.40463 0.000 1.000
## write 36.30917 4837.98255 0.008 0.994
## math -0.36898 1362.81267 0.000 1.000
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 222.71004668627 on 199 degrees of freedom
## Residual deviance: 0.00000013527 on 195 degrees of freedom
## AIC: 10
##
## Number of Fisher Scoring iterations: 25
Seperti pada materi RM minggu lalu, kita menginginkan model kita terdiri dari beberapa variable yang memiliki nilai AIC serendah mungkin.
AIC = Information Loss
$aic model_all_predictor
## [1] 10
p-values: merupakan nilai p-values untuk melihat apakah variabel prediktor berpengaruh cukup signifikan terhadap variabel target. Variabel prediktor(x) dapat dikatakan signifikan jika \(p-values < 0.05\).
Hipotesis: - \(H_0\) : Prediktor tidak memengaruhi Target - \(H_1\) : Prediktor memengaruhi Target
Kita bisa melihat nilai signifikasi berdasarkan jumlah bintang - Jika 3 bintang *** -> prediktor tersebut secara signifikan mempengaruhi target - Jika 2 bintang ** -> prediktor tersebut mempengaruhi target - Jika 1 bintang * -> prediktor tersebut mempengaruhi target tp tidak terlalu kuat
Untuk dapat melakukan interpretasi, kita harus melakukan transformasi
nilai log of odds -> odds, dengan menggunakan
fungsi exp()
.
Contoh 1: Interpretasi nilai read
# Interpretasi nilai read
exp(0.07478)
## [1] 1.077647
Kesimpulan: Setiap kenaikan 1 nilai pada math, maka odds seseorang mendapatkan honor naik sebesar 1.07 KALI.
Contoh 2: Interpretasi gender
Sama seperti model RM, model Logistic juga akan membuat dummy variable
# Interpretasi gender
exp(4.44248)
## [1] 84.98544
Kesimpulan: Kejadian student female mendapatkan honors 84.98 KALI lebih tidak mungkin dibandingkan male mendapatkan honors, dengan catatan prediktor yang lain memiliki nilai yg sama.
Kesimpulan 2: > Bila student merupakan female maka akan menurunkan peluang untuk lulus sebagai honors.
Contoh 3: Interpretasi Formula
Ketika membuat formula, tidak usah mengubah ke bentuk odds (masih dlm bentuk log of odds):
Honor Formula =
-2176.87191 + female1 * -4.44248 + read * 0.07478 + write * 36.30917 + math * -0.36898
# Student Male, Read 70, Write 75, Math 60
-2176.87191 + 0 * -4.44248 + 70 * 0.07478 + 75 * 36.30917 + 60 * -0.36898
## [1] 529.4116
Additional Notes: Hasil dari formula tersebut dapat kita interepteasikan dengan mengubahnya menjadi bentuk probabilitas, untuk mengetahui apakah student tersebut memiliki kemungkinan mendapatkan honors atau tidak.
Untuk membahas Perfect Separation, mari kita coba lihat lagi hasil summary dari model Logistic Regression yang menggunakan keseluruhan predictor.
# Please type your answer
summary(model_all_predictor)
##
## Call:
## glm(formula = hon ~ ., family = binomial, data = honors)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.000245237 -0.000000021 -0.000000021 -0.000000021 0.000176979
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2176.87191 282900.61006 -0.008 0.994
## female1 -4.44248 18078.08748 0.000 1.000
## read 0.07478 489.40463 0.000 1.000
## write 36.30917 4837.98255 0.008 0.994
## math -0.36898 1362.81267 0.000 1.000
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 222.71004668627 on 199 degrees of freedom
## Residual deviance: 0.00000013527 on 195 degrees of freedom
## AIC: 10
##
## Number of Fisher Scoring iterations: 25
Perfect Separation adalah sebuah kondisi dimana ada 1 variabel yang dapat memisahkan kelas target secara sempurna. Cara mendeteksi:
Mari kita coba analisis secara spesifik prediktor tersebut, debgan melihat proporsi antara kolom predictor yang disangka ada hal yang janggal dengan target variable.
# Please type your answer
table(honors$hon, honors$write)
##
## 31 33 35 36 37 38 39 40 41 42 43 44 45 46 47 49 50 52 53 54 55 57 59 60 61
## 0 4 4 2 2 3 1 5 3 10 2 1 12 1 9 2 11 2 15 1 17 3 12 25 4 0
## 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4
##
## 62 63 65 67
## 0 0 0 0 0
## 1 18 4 16 7
table(honors$hon, honors$math)
##
## 33 35 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
## 0 1 1 1 2 6 10 6 7 7 4 7 8 3 3 9 7 6 6 6 9 4 4 10 3 2
## 1 0 0 0 0 0 0 1 0 0 0 1 0 0 2 1 0 2 0 1 1 1 3 3 3 0
##
## 60 61 62 63 64 65 66 67 68 69 70 71 72 73 75
## 0 2 4 2 2 3 1 1 0 0 0 1 2 0 0 1
## 1 3 3 2 3 2 2 3 2 1 2 0 2 3 1 1
table(honors$hon, honors$read)
##
## 28 31 34 35 36 37 39 41 42 43 44 45 46 47 48 50 52 53 54 55 57 60 61 63 65
## 0 1 1 6 1 3 2 8 2 13 2 13 2 1 22 1 15 11 0 0 9 9 6 1 10 3
## 1 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 3 3 1 1 4 5 3 0 6 6
##
## 66 68 71 73 76
## 0 0 7 0 1 1
## 1 1 4 2 4 1
Action plan ketika bertemu kondisi perfect separation:
Logistic Regression menganut 3 asumsi:
Handoyo adalah seorang murid laki-laki yang memperoleh nilai math sebesar 70, berapa probability Handoyo mendapatkan honors?
Diketahui Nilai Slope:
Intercept: -10.80595 Gender: 0.965311 Nilai Math: 0.16422
Rumus: Y = B0 + B1.X1 + B2.X2
# log of odds
-10.80595 + (0.965311 * 0) + (0.16422 * 70)
## [1] 0.68945
inv.logit(0.68945)
## [1] 0.6658446
vif()
library(car)
vif(model_all_predictor)
## female read write math
## 6.999657 3.938737 1.070529 11.508350
Ketika ada 2 nilai/predicot yang nilai vif > 10. Maka kita hanya boleh memilih salah satunya saja.
Contoh Untuk observasi saling independen: -> kita harus ambil data secara random sampling
Target: Mencari apakah seseorang akan beli atau tidak? - Mas Hadnoyo; Beli, beliau tidak puas - Mba Diva: Tidak beli, karena ada pengaruh dari Mas Handoyo
Contoh tidak bersal dari pengukuran berulang: -> Kita coba hilangkan data yang sebelumnya
Mengukur tinggi badan sebuah buah: Hari 1 : 10 cm . . Hari 10 : 14 cm
Asumsi logistic regression menuntut kita untuk memahami data secara mendalam dan memastikan data sudah siap dipakai untuk membuat model.
Buat model untuk memprediksi peluang customer akan gagal bayar pinjaman (loan default), untuk mengindikasikan apakah customer tersebut baik atau tidak untuk diberikan pinjaman.
Workflow Case Study 2:
<- read.csv("data_input/loan2017Q4.csv")
loans head(loans)
Descriptions:
initial_list_status
: Either w
(whole) or
f
(fractional). This variable indicates if the loan was a
whole loan or fractional loan. For background: Some institutional
investors have a preference to purchase loans in their entirety to
obtain legal and accounting treatment specific to their situation - with
the added benefit of “instant funding” to borrowerspurpose
: Simplified from the original data; One of:
credit_card
, debt_consolidation
,
home_improvement
, major_purchase
and
small_business
int_rate
: Interest rate in percentagesinstallment
: Monthly payment owed by the borrowerannual_inc
: Self-reported annual income provided by the
borrower / co-borrowers during applicationdti
: A ratio of the borrower’s total monthly debt
payments on his/her total obligations to the self-reported monthly
incomeverification_status
: is the reported income verified,
not verified, or if the income source was verifiedgrade
: software-assigned loan graderevol_bal
: total credit revolving balance (in the case
of credit card, it refers to the portion of credit card spending that
goes unpaid at the end of a billing cycle)inq_last_12m
: number of credit inquiries in the last 12
monthsdelinq_2yrs
: number of 30+ days past-due incidences of
delinquency in the borrower’s credit file for the past 2 yearshome_ownership
: one of MORTGAGE
,
OWN
and RENT
not_paid
: 0 for fully-paid loans, 1 for charged-off,
past-due / grace period or defaultedlog_inc
: log of annual_inc
verified
: 0 for “Not verified” under
verification_status
, 1 otherwisegrdCtoA
: 1 for a grade
of A, B or C, 0
otherwisenot_paid
-> factorverified
-> factor
grade
-> factor
home_ownership
-> factor
purpose
-> factor
initial_list_status
-> factor
Adakah variabel di bawah ini ada yang dapat dibuang?
grade
->
log_inc
->
verified_status
->
<- loans %>%
loans_clean mutate(not_paid = as.factor(not_paid),
verified = as.factor(verified),
grade = as.factor(grade),
home_ownership= as.factor(home_ownership),
purpose=as.factor(purpose),
initial_list_status=as.factor(initial_list_status))%>%
select(-c(verification_status,grdCtoA,log_inc))
glimpse(loans_clean)
## Rows: 1,556
## Columns: 13
## $ initial_list_status <fct> w, f, w, w, w, w, w, w, w, w, w, w, w, f, w, w, w,…
## $ purpose <fct> debt_consolidation, debt_consolidation, debt_conso…
## $ int_rate <dbl> 14.08, 9.44, 28.72, 13.59, 15.05, 10.91, 15.05, 10…
## $ installment <dbl> 675.99, 480.08, 1010.30, 484.19, 476.33, 130.79, 3…
## $ annual_inc <dbl> 156700, 50000, 25000, 175000, 109992, 49000, 65000…
## $ dti <dbl> 19.11, 19.35, 65.58, 12.60, 10.00, 5.12, 22.38, 33…
## $ grade <fct> C, B, F, C, C, B, C, B, D, D, F, C, C, E, B, C, C,…
## $ revol_bal <int> 21936, 5457, 23453, 31740, 2284, 2016, 14330, 2758…
## $ inq_last_12m <int> 3, 1, 0, 0, 3, 5, 0, 1, 8, 1, 0, 12, 4, 8, 1, 3, 0…
## $ delinq_2yrs <int> 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,…
## $ home_ownership <fct> MORTGAGE, RENT, OWN, MORTGAGE, MORTGAGE, MORTGAGE,…
## $ not_paid <fct> 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1,…
## $ verified <fct> 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
# Please type your answer
anyNA(loans_clean)
## [1] FALSE
# Please type your answer
prop.table(table(loans_clean$not_paid))
##
## 0 1
## 0.5 0.5
Apakah proporsi antara target variable seimbang? Seimbang
Follow up question: > Kenapa kita harus mencari tahu apakah proporsi taretnya seimbang?
Proporsi yang seimbang penting agar model dapat mempelajari karakteristik kelas positif maupun negatif secara seimbang, tidak belajar dari satu kelas saja. Hal ini mencegah model dari hanya baik memprediksi 1 kelas saja. Note: Proporsi yang imbalance sebenarnya cukup subjektif dan tidak ada aturan bakunya. Akan tetapi ketika proporsinya targetnya 90%:10% atau 95%:5%, target variable tersebut akan dianggap tidak seimbang.
Target Variable:
Kalau datanya imbalance:
Tambah data real -> memerlukan waktu
Metode downSampling -> Membuang observasi dari kelas mayoritas, sehingga seimbang. Contoh: Paid: 800 observasi -> akan dicut/dihilangkan secara random -> 200 observasi Not Paid: 200 Observasi
Metode upSampling -> Duplikasi observasi dari kelas minoritas, sehingga seimbang. Contoh: Paid: 800 Observasi Not Paid: 200 Observasi -> akan diduplicate secara random -> 800 observasi
Materi tersebut akan dipelajari di C2
Kenapa kita harus tau kelas dari target variable kita balance atau tidak? Memastikan bahwa nanti data yang dimasukan ke model kita, itu datanya memiliki proporsi target yang seimbang. Jadinya model Machine Learning kita tidak hanya belajar untuk salah satu target kelasnya saja.
Contoh Proporsi Target Variable: Paid: 57% Not Paid: 43% Proporsi Balanced
Contoh dari Instructor: Paid: 65% Not Paid: 35% Proporsi Balanced
Cross Validation merupakan sebuah tahapan dimana kita akan membagi data menjadi 2 bagian yaitu data train dan data test.
Tujuan dari cross validation adalah untuk mengetahui seberapa baik model untuk memprediksi unseen data.
Contoh:
Contoh Lainnya:
10 Soal Latihan Matetmatika 5+3 1-1 7+8 9+9 6+4 8-2 7+4 1+4 5-1 7+10
Ulangan 5 soal -> untuk melihat pemahaman ataupun untuk nilai apakah murid bisa atau tidak 5-3 1+1 7-6 9+19 6-8
Untuk memilih secara random data yang akan dimasukan kedalam Data
Train, kita akan memanfaatkan bantuan fungsi
set.seed()
dan RNGkind()
.
Intuisi:
# Agar hasil yang dikeluarkan pada R versi 3.x sama dengan R versi 4.x
RNGkind(sample.kind = "Rounding")
# set.seed digunakan untuk mengunci sifat random dari fungsi sample()
set.seed(123)
sample(x = c("Victor", "Handoyo", "Diva"), size = 2)
## [1] "Victor" "Handoyo"
Follow up question: > Kenapa kita harus mengunci sifat random yang ada?
# Agar hasil yang dikeluarkan pada R versi 3.x sama dengan R versi 4.x
RNGkind(sample.kind = "Rounding")
# set.seed digunakan untuk mengunci sifat random dari fungsi sample()
set.seed(123)
# index sampling
<- sample(x = nrow(loans_clean), # untuk menghitung jumlah dari observasi data kita
index size = nrow(loans_clean)*0.8) # Untuk mengambil seberapa banyak proporsi data yang ingin kita ambil
# splitting
<- loans_clean[index, ]
loans_train <- loans_clean[-index, ] loans_test
nrow(loans_train)
## [1] 1244
1556 *0.8
## [1] 1244.8
NOTE: Pembagian proporsi antara Data Train & Data Test tidak ada aturan bakunya, akan tetapi kebanyakan orang akan memberikan proporsi yang lebih banyak pada Data Train.
Buatlah model logistic regression untuk memprediksi status loan (not_paid). Silahkan menggunakan keseluruhan predictor yang ada pada data kita.
# Please type your answer
<- glm(formula = not_paid ~ ., data = loans_train, family = binomial) model_credit_risk
# summary model
summary(model_credit_risk)
##
## Call:
## glm(formula = not_paid ~ ., family = binomial, data = loans_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.919 -1.100 0.554 1.107 1.677
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.895253816 0.467909249 -1.913 0.0557 .
## initial_list_statusw -0.048747890 0.148032695 -0.329 0.7419
## purposedebt_consolidation 0.115336589 0.155024560 0.744 0.4569
## purposehome_improvement 0.204093183 0.230295537 0.886 0.3755
## purposemajor_purchase 0.737075738 0.355047479 2.076 0.0379 *
## purposesmall_business 0.938694313 0.526603436 1.783 0.0747 .
## int_rate -0.018378629 0.051945000 -0.354 0.7235
## installment 0.001110541 0.000228727 4.855 0.0000012 ***
## annual_inc -0.000003243 0.000001321 -2.456 0.0141 *
## dti 0.000021291 0.004807931 0.004 0.9965
## gradeB 0.182773836 0.269467189 0.678 0.4976
## gradeC 0.605594745 0.422222941 1.434 0.1515
## gradeD 0.993606286 0.657471666 1.511 0.1307
## gradeE 1.034959679 0.951289595 1.088 0.2766
## gradeF 1.080915152 1.240401733 0.871 0.3835
## gradeG 0.150604983 1.381648411 0.109 0.9132
## revol_bal 0.000001796 0.000003377 0.532 0.5948
## inq_last_12m -0.031628334 0.024697577 -1.281 0.2003
## delinq_2yrs 0.166826833 0.083625900 1.995 0.0461 *
## home_ownershipOWN 0.439661888 0.185875847 2.365 0.0180 *
## home_ownershipRENT 0.237032187 0.137641085 1.722 0.0851 .
## verified1 0.227585954 0.125577982 1.812 0.0699 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1724.5 on 1243 degrees of freedom
## Residual deviance: 1630.4 on 1222 degrees of freedom
## AIC: 1674.4
##
## Number of Fisher Scoring iterations: 4
Additional Info:
Dalam membuat sebuah model, kita dapat memilih predictor apa saja
yang kiranya memiliki pengaruh yang tinggi terhadap target varialbe,
kita bisa melakukan Feature Selection dengan
menggunakan fungsi step()
.
<- step(object = model_credit_risk,
model_step direction = "both",
trace = F)
summary(model_step)
##
## Call:
## glm(formula = not_paid ~ installment + annual_inc + grade + delinq_2yrs +
## home_ownership + verified, family = binomial, data = loans_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.9162 -1.1142 0.6502 1.1104 1.6614
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.016867074 0.211758025 -4.802 0.000001571 ***
## installment 0.001129976 0.000225011 5.022 0.000000512 ***
## annual_inc -0.000003002 0.000001133 -2.651 0.008029 **
## gradeB 0.120955536 0.203135292 0.595 0.551547
## gradeC 0.449697161 0.199287045 2.257 0.024037 *
## gradeD 0.757091610 0.213986088 3.538 0.000403 ***
## gradeE 0.698809943 0.275943528 2.532 0.011327 *
## gradeF 0.650505301 0.424713120 1.532 0.125613
## gradeG -0.280828387 0.635944022 -0.442 0.658784
## delinq_2yrs 0.162157394 0.082759891 1.959 0.050069 .
## home_ownershipOWN 0.472482689 0.183936211 2.569 0.010207 *
## home_ownershipRENT 0.278843394 0.130350327 2.139 0.032421 *
## verified1 0.235884735 0.124633872 1.893 0.058408 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1724.5 on 1243 degrees of freedom
## Residual deviance: 1639.3 on 1231 degrees of freedom
## AIC: 1665.3
##
## Number of Fisher Scoring iterations: 4
Interpretasi Model:
Ketika kita sudah berhasil membuat model, kita akan mencoba melakukan prediksi terhadapat data test yang sudah kita persiapkan pada tahapan cross validation.
Syntax: predict(object model, newdata, type)
Terdapat parameter tambahan yang akan kita gunakan pada fungsi
predict()
, yaitu parameter type
. Parameter
type
dapat kita isi dengan:
link
: menghasilkan log of oddsresponse
: menghasilkan probabilityContoh prediksi dengan menggunakan type = link
, untuk 5
data teratas
# Please type your answer
predict(object = model_step,
newdata = loans_test[1:5,],
type = "link")
## 8 13 16 24 44
## 0.13220652 -0.05171338 0.24003330 0.45283669 0.97379450
Contoh prediksi dengan menggunakan type = response
,
untuk 5 data teratas
# Please type your answer
predict(object = model_step,
newdata = loans_test[1:5,],
type = "response")
## 8 13 16 24 44
## 0.5330036 0.4870745 0.5597219 0.6113135 0.7258752
Mari kita lakukan prediksi probability not_paid
pada
data loan_test
, lalu disimpan pada kolom baru bernama
prediction
di object loan_test
.
# Please type your answer
$prediction <- predict(object = model_step, # nama/object model yang ingin kita gunakan
loans_testnewdata = loans_test, # data test
type = "response") # memilih hasil prediksinya
Setelah mendapatkan hasil prediksi yang masih bernilai probability, kita harus mengubah niali tersebut menjadi sebuah label yang sesuai dengan label pada target variable. Dalam kasus ini kita akan menggubah nilai probability menjadi 1 atau 0.
Untuk melakukan transformasi kita akan memanfaatkan fungsi
ifelse()
, fungsi tersebut dapat membantu kita untuk membuat
fungsi logic if-else sederhana.
Syntax: ifelse(test = , yes = , no =)
test
: kondisi yang ditentukanyes
: hasil yang di-inginkan jika kondisinya
terpenuhino
:hasil yang di-inginkan jika kondisinya tidak
terpenuhiKondisi penentu ketika kita ingin mentranformasikan hasil prediksi kita ke sebuah kelas, kondisi itu sering disebuh dengan Threshold.
Ketika hasil prediksi probability > 0.5 -> 1/gagal bayar
# Please type your answer
$pred_label <- ifelse(test = loans_test$prediction > 0.3,
loans_testyes = "1",
no = "0")
loans_test
Setelah dilakukan prediksi menggunakan model, masih ada saja prediksi yang salah. Pada klasifikasi, kita mengevaluasi model berdasarkan confusion matrix:
Penentuan kelas:
Contoh kasus:
Isi dari Confusion Matrix:
Untuk melakukan perhitungan confusion matrix kita akan menggunakan
fungsi confusionMatrix()
dari library(caret)
.
Pada fungsi tersebut terdapat 3 parameter yang dapat kita manfaatkan,
yaitu:
data
= Data atau kolom hasil prediksi yang sudah
ditransformasi menjadi label.reference
= Data atau kolom yang berisikan data
realpositive
= target apa yang ingin dijadikan positif
value atau target apa yang kita petingkan.$pred_label <- as.factor(loans_test$pred_label) loans_test
str(loans_test$pred_label)
## Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
# confusion matrix
library(caret)
confusionMatrix(data = loans_test$pred_label,
reference = loans_test$not_paid,
positive = "1")
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 19 1
## 1 140 152
##
## Accuracy : 0.5481
## 95% CI : (0.491, 0.6042)
## No Information Rate : 0.5096
## P-Value [Acc > NIR] : 0.09631
##
## Kappa : 0.1111
##
## Mcnemar's Test P-Value : < 0.0000000000000002
##
## Sensitivity : 0.9935
## Specificity : 0.1195
## Pos Pred Value : 0.5205
## Neg Pred Value : 0.9500
## Prevalence : 0.4904
## Detection Rate : 0.4872
## Detection Prevalence : 0.9359
## Balanced Accuracy : 0.5565
##
## 'Positive' Class : 1
##
TP: 96 TN: 90 FP: 69 FN: 57
4 metrics performa model: Accuracy, Sensitivity/Recall, Precision, Specificity
Seberapa banyak yang benar diprediksi dari keseluruhan data (positif maupun negatif).
TP+TN/TOTAL
# total data: nrow(loans.test)
96 + 90) / nrow(loans_test) (
## [1] 0.5961538
Note: tidak ada batasan mutlak berapa akurasi yang dianggap akurat (sudah baik), dikembalikan ke kebutuhan bisnis masing-masing.
Digunakan ketika:
prob.table(table())
Ada kondisi ketika accuracy bukanlah metrics terpenting. Umumnya ketika:
Saat kita mementingkan kelas tertentu, maka kita dapat memilih antara menggunakan metrics Recall / Precision:
Seberapa banyak yang benar diprediksi positif, dari yang reality-nya (aktualnya) positif.
TP/(TP+FN)
96 / (96 + 57)
## [1] 0.627451
Seberapa banyak yang benar diprediksi positif, dari yang diprediksi positif.
TP/(TP+FP)
96 / (96 + 69)
## [1] 0.5818182
Seberapa banyak yang tepat diprediksi negatif, dari yang reality-nya negatif. Jarang dipakai karena kita tidak sering fokus pada kelas negatif.
TN/(TN+FP)
90 / (90 + 69)
## [1] 0.5660377
k-NN adalah K-nearest neighboor. Metode ini akan mengkasifikasi data baru dengan membandingkan karakteristik data baru (data test) dengan data yang ada (data train). Kedekatan karakteristik tersebut diukur dengan Euclidean Distance hingga didapatkan jarak. Kemudian akan dipilih k tetangga terdekat dari data baru tersebut, kemudian ditentukan kelasnya menggunakan majority voting.
sqrt(nrow(data))
Contoh kasus: (honors not-honors) -> kelas target = 2 (low medium high) -> kelas target = 3
Melanjutkan dari studi kasus sebelumnya, kita akan coba bila klasifikasi peluang customer akan gagal bayar pinjaman dengan menggunakan k-NN. Apakah k-NN akan lebih baik dari logistic regression? Bagaimana performanya?
Dikarenakan karakterisik dari K-NN hanya baik untuk prediktor yang bertipe numerik, maka dari itu kita akan mencoba membuang prediktor kategorik yang sudah kita buat pada model logistic regression.
model_step
##
## Call: glm(formula = not_paid ~ installment + annual_inc + grade + delinq_2yrs +
## home_ownership + verified, family = binomial, data = loans_train)
##
## Coefficients:
## (Intercept) installment annual_inc gradeB
## -1.016867074 0.001129976 -0.000003002 0.120955536
## gradeC gradeD gradeE gradeF
## 0.449697161 0.757091610 0.698809943 0.650505301
## gradeG delinq_2yrs home_ownershipOWN home_ownershipRENT
## -0.280828387 0.162157394 0.472482689 0.278843394
## verified1
## 0.235884735
##
## Degrees of Freedom: 1243 Total (i.e. Null); 1231 Residual
## Null Deviance: 1725
## Residual Deviance: 1639 AIC: 1665
# Data Train
<- loans_train %>%
loans_train_knn select(not_paid, installment, annual_inc, delinq_2yrs)
# Data Test
<- loans_test %>%
loans_test_knn select(not_paid, installment, annual_inc, delinq_2yrs)
Scaling: menyamaratakan range variable prediktor
Scaling bisa menggunakan min-max normalization atau z-score standarization.
Rumus = x-min(x) / max(x)-min(x)
<- function(x){
normalize return (
- min(x))/(max(x) - min(x))
(x
) }
# contoh:
normalize(c(1,2,3,4,5)) # memampatkan range nilai menjadi 0-1
## [1] 0.00 0.25 0.50 0.75 1.00
Contoh:
Untuk kasus nilai ulangan -> range 0 - 100
Nilai Mat: 20 - 40 -> nilai min:0 & nilai max:100
Nilai Read: 70 - 100 -> nilai min:0 & nilai max:100
2. Z-score Standarization: dapat menggunakan function
scale()
Rumus = x-mean(x) / sd(x)
# contoh:
scale(c(1,2,3,4,5)) # data kita seberapa menyimpang (sd) dari pusatnya (mean)
## [,1]
## [1,] -1.2649111
## [2,] -0.6324555
## [3,] 0.0000000
## [4,] 0.6324555
## [5,] 1.2649111
## attr(,"scaled:center")
## [1] 3
## attr(,"scaled:scale")
## [1] 1.581139
Note: untuk 1 data harus menggunakan 1 tipe scaling yang sama
Untuk k-NN, dipisahkan antara prediktor dan label (target variabelnya).
library(dplyr)
# prediktor train
<- loans_train_knn %>%
loans_train_predictor select(-not_paid)
# target train
<- loans_train_knn %>%
loans_train_target pull(not_paid) # untuk menarik vector/value yang tedapat pada kolom di data frame kita
# prediktor test
<- loans_test_knn %>%
loans_test_predictor select(-not_paid)
# taget test
<- loans_test_knn %>%
loans_test_target pull(not_paid)
Data prediktor akan discaling menggunakan z-score standarization. Data test juga harus discaling menggunakan parameter dari data train (karena menganggap data test adalah unseen data).
scale()
terdiri dari beberapa parameter
# scaling data prediktor
<- scale(x = loans_train_predictor)
loans_train_scale
<- scale(x = loans_test_predictor,
loans_test_scale center = attr(loans_train_scale, "scaled:center"),
scale = attr(loans_train_scale, "scaled:scale"))
Step 1: Kita akan melakukan kalkuasi berapakah nilai k paling
optimum, dengan menggunakan fungsi sqrt()
dari jumlah data
kita.
# find optimum k
sqrt(nrow(loans_train_predictor))
## [1] 35.27038
Step 2: Kita akan langsung memprediksi dengan menggunakan fungsi
knn()
dari library(class)
.
Pada fungsi knn()
terdapat 4 parameter yang akan kita
isi, yaitu:
train
= data train - prediktor, yang sudah discaling,
tipe numeriktest
= data test - prediktor, yang sudah discaling,
tipe numerikcl
= data train - label (target) aktual
(kategorikal)k
= jumlah k yang ditentukan dari nilailibrary(class) # package untuk fungsi `knn()`
<- knn(train = loans_train_scale,
loans_pred_knn test = loans_test_scale,
cl = loans_train_target,
k = 35,
prob = T)
# cek hasil prediksi
loans_pred_knn
## [1] 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 0 0
## [38] 1 1 1 1 1 1 1 0 0 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 0 1 0 0 0 0 0 1 0 0 1 0
## [75] 0 0 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 0 1 1 1 1 0 0 0 1 0 1 0 0
## [112] 1 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1
## [149] 0 0 0 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 0 1 1 1 0 1 1 1 0 0 1 0 1 0 1 0 1 1 1
## [186] 1 0 1 1 1 1 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 1 1 1 1 0 1 0 0 1
## [223] 0 1 1 1 0 1 0 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 1 1 0 0 1 0 0 1 0 0 1
## [260] 1 1 1 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 0 1 0 1 0 1 1
## [297] 1 0 1 1 0 0 0 1 1 1 0 1 0 0 0 0
## attr(,"prob")
## [1] 0.5142857 0.5428571 0.6285714 0.6285714 0.5142857 0.6571429 0.5142857
## [8] 0.6857143 0.6285714 0.6857143 0.6571429 0.5142857 0.5142857 0.6000000
## [15] 0.5714286 0.6571429 0.6000000 0.5142857 0.6857143 0.5714286 0.5714286
## [22] 0.5142857 0.5142857 0.5714286 0.5714286 0.5142857 0.5142857 0.6571429
## [29] 0.5428571 0.5428571 0.5714286 0.5142857 0.5142857 0.6571429 0.5714286
## [36] 0.5428571 0.6000000 0.6000000 0.7714286 0.5428571 0.5142857 0.5142857
## [43] 0.6000000 0.6285714 0.7428571 0.5142857 0.6285714 0.5428571 0.6000000
## [50] 0.6000000 0.5428571 0.6000000 0.6000000 0.6000000 0.5428571 0.5142857
## [57] 0.5142857 0.5142857 0.5142857 0.7142857 0.5428571 0.5142857 0.5142857
## [64] 0.7142857 0.5142857 0.5714286 0.6571429 0.7142857 0.5142857 0.6285714
## [71] 0.6285714 0.6285714 0.6000000 0.6000000 0.6000000 0.5142857 0.6000000
## [78] 0.6285714 0.6857143 0.5714286 0.6571429 0.5714286 0.6285714 0.6285714
## [85] 0.5428571 0.5428571 0.6571429 0.5428571 0.6000000 0.6571429 0.5714286
## [92] 0.5714286 0.5714286 0.7142857 0.6571429 0.5142857 0.5428571 0.5714286
## [99] 0.7142857 0.5714286 0.5142857 0.5142857 0.5142857 0.6000000 0.6000000
## [106] 0.5142857 0.5714286 0.5142857 0.5428571 0.6857143 0.7428571 0.6857143
## [113] 0.7714286 0.6857143 0.5428571 0.5142857 0.6000000 0.5428571 0.6571429
## [120] 0.5142857 0.5714286 0.5428571 0.6571429 0.6000000 0.5142857 0.5714286
## [127] 0.6571429 0.6857143 0.5714286 0.5428571 0.6571429 0.5714286 0.6000000
## [134] 0.5714286 0.7142857 0.7142857 0.5428571 0.6285714 0.5714286 0.5714286
## [141] 0.7142857 0.5142857 0.7428571 0.5428571 0.6571429 0.5428571 0.5428571
## [148] 0.6000000 0.5428571 0.5428571 0.5142857 0.5714286 0.6285714 0.5714286
## [155] 0.6285714 0.5714286 0.5428571 0.5142857 0.6000000 0.6571429 0.5142857
## [162] 0.6857143 0.6285714 0.6000000 0.5428571 0.5142857 0.6000000 0.6857143
## [169] 0.5428571 0.5428571 0.5714286 0.5714286 0.6571429 0.6000000 0.5142857
## [176] 0.6571429 0.5142857 0.5000000 0.6571429 0.5142857 0.5428571 0.5714286
## [183] 0.5142857 0.5142857 0.5428571 0.6857143 0.6000000 0.6571429 0.6571429
## [190] 0.6571429 0.5428571 0.5142857 0.7428571 0.6285714 0.5142857 0.7142857
## [197] 0.5714286 0.5142857 0.6285714 0.6000000 0.5714286 0.6000000 0.5714286
## [204] 0.7142857 0.5714286 0.6857143 0.5428571 0.7142857 0.6571429 0.5142857
## [211] 0.5714286 0.6000000 0.5142857 0.6571429 0.5428571 0.5714286 0.5714286
## [218] 0.6285714 0.5142857 0.5142857 0.6285714 0.6000000 0.7142857 0.5714286
## [225] 0.5142857 0.5714286 0.5142857 0.5428571 0.7142857 0.7142857 0.5714286
## [232] 0.5428571 0.7428571 0.5428571 0.5142857 0.5142857 0.6000000 0.5428571
## [239] 0.5714286 0.5142857 0.5142857 0.5428571 0.5142857 0.5428571 0.5714286
## [246] 0.5428571 0.6571429 0.6571429 0.5428571 0.5142857 0.7142857 0.6571429
## [253] 0.5714286 0.5428571 0.5555556 0.5142857 0.5428571 0.6571429 0.6571429
## [260] 0.6000000 0.6285714 0.5714286 0.6388889 0.7714286 0.6000000 0.5714286
## [267] 0.6000000 0.5277778 0.5714286 0.6285714 0.6000000 0.5142857 0.5142857
## [274] 0.5714286 0.5142857 0.5833333 0.5142857 0.5714286 0.6000000 0.5428571
## [281] 0.6857143 0.6571429 0.6285714 0.5428571 0.7428571 0.5142857 0.7428571
## [288] 0.5714286 0.7142857 0.5428571 0.5428571 0.5945946 0.6000000 0.7142857
## [295] 0.6000000 0.5142857 0.6000000 0.6857143 0.5714286 0.6285714 0.6000000
## [302] 0.7142857 0.6285714 0.5714286 0.6000000 0.5714286 0.5714286 0.5428571
## [309] 0.5714286 0.5142857 0.6000000 0.5142857
## Levels: 0 1
# confusion matrix
library(caret)
confusionMatrix(data = loans_pred_knn,
reference = loans_test_target,
positive = "1")
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 80 51
## 1 79 102
##
## Accuracy : 0.5833
## 95% CI : (0.5265, 0.6386)
## No Information Rate : 0.5096
## P-Value [Acc > NIR] : 0.005326
##
## Kappa : 0.1692
##
## Mcnemar's Test P-Value : 0.017882
##
## Sensitivity : 0.6667
## Specificity : 0.5031
## Pos Pred Value : 0.5635
## Neg Pred Value : 0.6107
## Prevalence : 0.4904
## Detection Rate : 0.3269
## Detection Prevalence : 0.5801
## Balanced Accuracy : 0.5849
##
## 'Positive' Class : 1
##
attributes(loans_pred_knn)$prob %>%
head()
## [1] 0.5142857 0.5428571 0.6285714 0.6285714 0.5142857 0.6571429
confmat_plot(prob = attributes(loans_pred_knn)$prob, # hasil prediksi probability
ref = loans_test_target, # kolom label aktual
postarget = "1", # label untuk nilai mendekati 1
negtarget = "0") # label untuk nilai mendekati 0
<- ifelse(test = attributes(loans_pred_knn)$prob > 0.45,
loans_pred_knn_2 yes = "1",
no = "0")
confusionMatrix(data = as.factor(loans_pred_knn_2),
reference = loans_test_target,
positive = "1")
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 0 0
## 1 159 153
##
## Accuracy : 0.4904
## 95% CI : (0.4336, 0.5473)
## No Information Rate : 0.5096
## P-Value [Acc > NIR] : 0.7692
##
## Kappa : 0
##
## Mcnemar's Test P-Value : <0.0000000000000002
##
## Sensitivity : 1.0000
## Specificity : 0.0000
## Pos Pred Value : 0.4904
## Neg Pred Value : NaN
## Prevalence : 0.4904
## Detection Rate : 0.4904
## Detection Prevalence : 1.0000
## Balanced Accuracy : 0.5000
##
## 'Positive' Class : 1
##