
REGRESI LOGISTIK UNTUK KLASIFIKASI BINER (dengan Software R)
REGRESI LOGISTIK UNTUK KLASIFIKASI BINER
(dengan Software R)
Oleh: Fitri Ramadhini
Regresi logistik merupakan suatu algoritma dalam pengklasifikasian atau classifier yang dapat digunakan untuk memprediksi suatu kelas variabel. Dalam praktiknya, regresi logistik banyak digunakan dalam mengklasifikasikan 2 kelas dalam suatu variabel atau klasifikasi biner. Aplikasi regresi logistik menggunakan software R tidak jauh berbeda dengan regresi linear. Jika regresi linear menggunakan fungsi lm() untuk membangun model, maka regresi logistik menggunakan fungsi glm() untuk membangun modelnya.
Data
Data untuk contoh ini adalah data heart disease sebanyak 303 observasi dan 14 variabel. Dari data ini akan diprediksi apakah seseorang terkena penyakit jantung atau tidak (variabel num) berdasarkan 13 variabel penjelas. Berikut adalah deskripsi dari data heart disease:
Nama Variabel | Deskripsi | Nama Variabel | Deskripsi |
Age | Umur dari pasien | Thalach | maximum heart rate achieved |
Sex | Jenis kelamin 0: female 1: male | Exang | Exercise induced angina 0: tidak 1: ya |
Cp | Chest Pain type 1: typical angina 2: atypical angina 3: non-anginal pain 4: asymptomatic | Oldpeak | ST depression induced by exercise relative to rest |
Trestbps | Resting blood pressure (mm Hg) | Slope | Slope of peak exercise ST segment 1: upsloping 2: flat 3: downsloping |
Chol | Serum cholesterol (mg/dl) | Ca | number of major vessels (0-3) colored by flourosopy |
Fbs | Fasting blood sugar > 120 mg/dl 0: tidak 1: ya | Thal | 3 = normal 6 = fixed defect 7 = reversable defect |
restecg | resting electrocardiographic results 0: normal 1: having ST-T wave abnormality (T wave inversions and/or ST elevation or depression of > 0.05 mV) 2: showing probable or definite left ventricular hypertrophy by Estes' criteria | Num | diagnosis of heart disease (angiographic disease status) 0: < 50% diameter narrowing 1: > 50% diameter narrowing |
(Sumber: https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/heart-disease.names)
Variabel yang akan diprediksi adalah variabel num, dengan mengasumsikan bahwa nilai 0 berarti jantung baik-baik saja, dan nilai 1, 2, 3, 4 berarti jantung terkena penyakit. Data heart disease dapat langsung diimpor menggunakan fungsi read.csv() dengan memasukkan alamat https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data yang merupakan sumber data tersebut.
heart <- read.csv("https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data",header=FALSE,sep=",",na.strings = '?') names(heart) <- c( "age", "sex", "cp", "trestbps", "chol","fbs", "restecg","thalach","exang", "oldpeak","slope", "ca", "thal", "num") head(heart) age sex cp trestbps chol fbs restecg thalach exang oldpeak slope ca thal num 1 63 1 1 145 233 1 2 150 0 2.3 3 0 6 0 2 67 1 4 160 286 0 2 108 1 1.5 2 3 3 2 3 67 1 4 120 229 0 2 129 1 2.6 2 2 7 1 4 37 1 3 130 250 0 0 187 0 3.5 3 0 3 0 5 41 0 2 130 204 0 2 172 0 1.4 1 0 3 0 6 56 1 2 120 236 0 0 178 0 0.8 1 0 3 0 |
Ekplorasi Data
heart$num<-ifelse(heart$num==0,0,1) str(heart) 'data.frame': 303 obs. of 14 variables: $ age : num 63 67 67 37 41 56 62 57 63 53 ... $ sex : num 1 1 1 1 0 1 0 0 1 1 ... $ cp : num 1 4 4 3 2 2 4 4 4 4 ... $ trestbps: num 145 160 120 130 130 120 140 120 130 140 ... $ chol : num 233 286 229 250 204 236 268 354 254 203 ... $ fbs : num 1 0 0 0 0 0 0 0 0 1 ... $ restecg : num 2 2 2 0 2 0 2 0 2 2 ... $ thalach : num 150 108 129 187 172 178 160 163 147 155 ... $ exang : num 0 1 1 0 0 0 0 1 0 1 ... $ oldpeak : num 2.3 1.5 2.6 3.5 1.4 0.8 3.6 0.6 1.4 3.1 ... $ slope : num 3 2 2 3 1 1 3 1 2 3 ... $ ca : num 0 3 2 0 0 0 2 0 1 0 ... $ thal : num 6 3 7 3 3 3 3 3 7 7 ... $ num : num 0 1 1 0 0 0 1 0 1 1 ... |
Variabel-variabel di atas semuanya berupa numerik, akan tetapi jika dilihat dari deskripsi data, ada beberapa variabel yang berupa kategorik yaitu variabel sex, cp, fbs, restecg, exang, slope, ca, thal, dan num sehingga variabel-variabel ini perlu diubah menjadi variabel yang berupa kategorik.
heart$sex<-as.factor(heart$sex) heart$cp<-as.factor(heart$cp) heart$fbs<-as.factor(heart$fbs) heart$restecg<-as.factor(heart$restecg) heart$exang<-as.factor(heart$exang) heart$slope<-as.factor(heart$slope) heart$ca<-as.factor(heart$ca) heart$thal<-as.factor(heart$thal) heart$num<-as.factor(heart$num) str(heart) 'data.frame': 303 obs. of 14 variables: $ age : num 63 67 67 37 41 56 62 57 63 53 ... $ sex : Factor w/ 2 levels "0","1": 2 2 2 2 1 2 1 1 2 2 ... $ cp : Factor w/ 4 levels "1","2","3","4": 1 4 4 3 2 2 4 4 4 4 ... $ trestbps: num 145 160 120 130 130 120 140 120 130 140 ... $ chol : num 233 286 229 250 204 236 268 354 254 203 ... $ fbs : Factor w/ 2 levels "0","1": 2 1 1 1 1 1 1 1 1 2 ... $ restecg : Factor w/ 3 levels "0","1","2": 3 3 3 1 3 1 3 1 3 3 ... $ thalach : num 150 108 129 187 172 178 160 163 147 155 ... $ exang : Factor w/ 2 levels "0","1": 1 2 2 1 1 1 1 2 1 2 ... $ oldpeak : num 2.3 1.5 2.6 3.5 1.4 0.8 3.6 0.6 1.4 3.1 ... $ slope : Factor w/ 3 levels "1","2","3": 3 2 2 3 1 1 3 1 2 3 ... $ ca : Factor w/ 4 levels "0","1","2","3": 1 4 3 1 1 1 3 1 2 1 ... $ thal : Factor w/ 3 levels "3","6","7": 2 1 3 1 1 1 1 1 3 3 ... $ num : Factor w/ 2 levels "0","1": 1 2 2 1 1 1 2 1 2 2 ... |
Variabel-variabel di atas sudah memiliki jenis variabel yang sesuai dengan deskripsi data. Langkah selanjutnya adalah melihat jumlah kelas pada variabel yang akan diprediksi.
levels(heart$num) = c("No Disease","Disease") levels(heart$sex) = c("Female","Male") table(heart$num) No Disease Disease 164 139 prop.table(table(heart$num)) No Disease Disease 0.5412541 0.4587459 |
Jumlah kelas pada data menunjukkan proporsi yang cukup seimbang, sehingga dapat dikatakan tidak ada masalah imbalanced class pada data.
#Pie Chart mytable <- table(heart$num) lbls <- paste(names(mytable), "\n", mytable, sep="") pie(mytable, labels = lbls, main="Pie Chart of Disease \n (with sample sizes)", col=c("aquamarine","pink")) | #Grouped Bar Plot counts <- table(heart$num,heart$sex) barplot(counts, main="Sebaran Penyakit berdasarkan Jenis Kelamin", xlab=" ", col=c("aquamarine","pink"),legend=rownames(counts), beside=TRUE) |
![]() |
Pie chart dari variabel respon menunjukkan kelas cukup seimbang, sedangkan bar chart di atas menunjukkan sebaran penyakit berdasarkan jenis kelamin dimana pada kelompok female jumlah pasien yang terdiagnosa penyakit jantung lebih kecil dibanding yang normal, sedangkan pada kelompok male jumlah pasien yang terdiagnosa penyakit jantung lebih besar dibanding yang normal.
Stratifikasi Data
Stratifikasi data diperlukan untuk memastikan setiap kelas respon terambil dalam pengacakan. Stratifikasi data dilakukan dengan fungsi filter() dalam paket dplyr.
library(dplyr) ho <- filter(heart,num=="No Disease") hd <- filter(heart,num=="Disease") |
Data Training dan Data Testing
Data training digunakan untuk membangun model, sedangkan data testing digunakan untuk validasidengan pembagian training:testing 70%:30%. Pengambilan data secara acak menggunakan nilai seed 10. Penggunaan seed dilakukan agar hasil pengacakan tetap. Setiap nilai seed akan melakukan pengacakan yang berbeda sehingga hasil dari setiap nilai seed juga akan berbeda (misal dalam akurasi).
set.seed (10) acak.ho <- sample(1:nrow(ho), 0.7*nrow(ho)) acak.hd <- sample(1:nrow(hd), 0.7*nrow(hd)) heart.tr <- rbind(ho[acak.ho,],hd[acak.hd,]) heart.test <- rbind(ho[-acak.ho,],hd[-acak.hd,]) |
Regresi Logistik
Data training digunakan untuk membangun model regresi logistik dengan menggunakan fungsi glm() karena regresi logistik termasuk ke dalam generalized linear model dengan family = binomial.
model.logistik<-glm(num~.,data=heart.tr, family="binomial") summary(model.logistik) Call: glm(formula = num ~ ., family = "binomial", data = heart.tr) Deviance Residuals: Min 1Q Median 3Q Max -3.1937 -0.4073 -0.1068 0.2770 2.5892 Coefficients: Estimate Std. Error z value Pr(>|z|) (Intercept) -6.066907 3.714357 -1.633 0.102392 age -0.029392 0.032283 -0.910 0.362589 sexMale 1.683733 0.732862 2.297 0.021592 * cp2 1.998763 1.061595 1.883 0.059729 . cp3 0.761080 0.849789 0.896 0.370461 cp4 3.099118 0.844679 3.669 0.000244 *** trestbps 0.037416 0.013773 2.717 0.006595 ** chol 0.004578 0.005052 0.906 0.364839 fbs1 -0.613889 0.804426 -0.763 0.445380 restecg1 0.535486 3.411634 0.157 0.875277 restecg2 0.502065 0.487491 1.030 0.303059 thalach -0.029019 0.017100 -1.697 0.089689 . exang1 0.791261 0.533940 1.482 0.138359 oldpeak 0.349409 0.301611 1.158 0.246670 slope2 0.841794 0.601662 1.399 0.161779 slope3 -0.417909 1.486485 -0.281 0.778604 ca1 1.950010 0.648863 3.005 0.002653 ** ca2 3.224709 1.111950 2.900 0.003731 ** ca3 2.492708 1.231755 2.024 0.043001 * thal6 -0.064460 1.044622 -0.062 0.950796 thal7 1.659596 0.555522 2.987 0.002813 ** --- Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 (Dispersion parameter for binomial family taken to be 1) Null deviance: 285.88 on 206 degrees of freedom Residual deviance: 124.31 on 186 degrees of freedom (4 observations deleted due to missingness) AIC: 166.31 Number of Fisher Scoring iterations: 6 |
Dari output di atas, variabel sex, cp, trestbps, ca, dan thal signifikan mempengaruhi respon (num) pada taraf nyata 5%. Pemilihan variabel juga dapat dilakukan dengan hanya memasukkan variabel-variabel yang signifikan mempengaruhi respon dan kemudian membandingkan nilai akurasinya. Dalam artikel ini akan dilakukan hanya pada model penuh (memasukkan semua variabel). Interpretasi untuk pengaruh setiap variabel dapat dilihat dari nilai rasio odds. Misalnya, untuk variabel sex memiliki nilai koefisien sebesar 1.683733 dengan reference category = female, nilai rasio odds nya adalah exp(1.683733) = 5.38 yang artinya untuk pasien laki-laki, odds untuk terkena penyakit jantung adalah 5.38 kali odds perempuan atau dapat dikatakan kecenderungan laki-laki untuk terkena penyakit jantung lebih besar dibanding perempuan.
Prediksi Variabel Respon pada Data Testing
Prediksi respon pada data testing dilakukan menggunakan threshold = 0.5 dimana jika nilai probabilitas prediksi > 0.5 maka akan diprediksi di kelas event (disease) dan sebaliknya akan diprediksi masuk di kelas non event (no disease).
prob.prediksi<-predict(model.logistik, heart.test, type="response") prediksi<-ifelse(prob.prediksi>0.5,"Disease","No Disease") pred.aktual<-data.frame(“Prediksi”=prediksi,”Aktual”=heart.test$num)head(pred.aktual) Prediksi Aktual 1 No Disease No Disease 5 No Disease No Disease 6 No Disease No Disease 7 No Disease No Disease 11 No Disease No Disease 15 No Disease No Disease |
Akurasi
Hasil prediksi pada data testing selanjutnya dibandingkan dengan data sebenarnya pada respon data testing. Nilai akurasi diperoleh dari fungsi confusionMatrix() pada paket caret.
library(caret) confusionMatrix(as.factor(prediksi), heart.test$num) Confusion Matrix and Statistics
Accuracy : 0.8778 95% CI : (0.7918, 0.9374) No Information Rate : 0.5444 P-Value [Acc > NIR] : 1.202e-11 Kappa : 0.7521 Mcnemar's Test P-Value : 0.5465 Sensitivity : 0.9184 Specificity : 0.8293 Pos Pred Value : 0.8654 Neg Pred Value : 0.8947 Prevalence : 0.5444 Detection Rate : 0.5000 Detection Prevalence : 0.5778 Balanced Accuracy : 0.8738 'Positive' Class : No Disease |
Dari Output di atas, untuk hasil confusion matrix prediksi yang meleset cukup kecil yaitu 7 untuk false positivedan 4 untuk false negative.Nilai akurasi sebesar 87.78% menunjukkan bahwa hasil klasifikasi dengan regresi logistik pada data ini sudah cukup baik