Lojistik regresyon ile UCI Kardioloji Veriseti Analizi

tarihinde yayınlandıMachine Learning, R yazılımı, Veri Analizi içinde yayınlandı
Facebooktwittergoogle_plusredditpinterestlinkedinmail

Doç. Dr. Kutlu MERİH

DATALAB

Giriş

Bütün istatistik analizler ve datamining algoritmaları kullanılan verisetinin yapısına özel bir koşullar kümesine bağımlıdır.  Analiz ve algoritmalar bu durumu dikkate alırsa sonuçlar daha başarılı olur. Her algoritma her veriseti için uygun olmayabilir. Bir kategorik değişkene lineer regresyon uygulayabilirsiniz ama performans istatistikleri şaşılacak kadar düşük çıkar. Bu tür durumlarda  veriseti ile uyumlu Logistic Regression, Decision Trees, SVM, Random Forest gibi teknikler daha başarılı sonuçlar üretebiliyor. Bu teknikler için dilimizdeki en iyi kaynak BALABAN/KARTAL. Burada sedece kategorik bağımlı değişken halinde olumlu sonuçlar veren Lojistik regresyonu  ve bunun R uygulamalarını inceleyeceğiz.

Logistic Regression Nedir?

Bu esas olarak bir sınıflandırma algoritmasıdır. İkili olarak bilinen (1/0, Evet/Hayır, Doğru/Yanlış, Hasta/Sağlam, Kullanıyor/Kullanmıyor, … ) durumları verilmiş bir bağımsız etki takımına karşı reaksiyonunu tahmin eder. Bağımlı değişken 0/1 olarak verildiğinde konu bir olayın etki seti verildiğinde gerçekleşme olasılığını tahmine dönüşür. Göreceğimiz gibi bunun da çok elegant bir matematik alt yapısı vardır. 

Logistic Regression Denklemini Oluşturmak

Logistic Regression aslında Generalized Linear Model (glm) olarak bilinen daha geniş bir tekniğin bir alt uygulamasıdır. 1972 yılında Nelder and Wedderburn lineer regression ile çözümlenmesi uygun olmayan problemlerin çözümü için bazı teknikler önerdiler ve logistics regression bunların bir özel hali idi.

Genelleştirilmiş modelin temel denklemi:

g(y) = b0 + b1.x1 + b2.x2 + … = u(x)

şeklindedir. Burada g(y) bir bağlantı fonksiyonu olarak bir lineer tahmin modelidir. Buna karşılık burada konvansiyonel regresyon tekniklerini uygulamak istediğimiz sonuçları vermez. 0-1 aralığında kalması gereken değişkenler bunun dışına taşacaklardır. Sonuçları 0-1 aralığında tutacak bir teknik geliştirmeliyiz.   

Modelin Önemli Özellikleri

GLM  bağımlı ve serbest değişkenler arasında bir lineer ilişki olmasını gerektirmez. Bunun yanında bağımsız değişken ile bağlantı fonksiyonu arasında bir lineer ilişkini varlığını varsayar. Bağımlı değişkenin normal dağılması gerekmez. En önemlisi parametrelerin tahmini için OLS (Ordinary Least Square) kullanmaz fakat maximum likelihood estimation (MLE) tekniğini kullanır. Belki de modelin en elgant kısmı burasıdır. Tahmin hataları bağımsızdır fakat normal dağılmaları gerekmez.

Başlamak için önce basit y değişkeni bağlantı fonksiyonu içinde olan bir linear regression denklemi yazacağız.

        g(y) = u(x)   —(a)

Logistic regression durumunda sadece bağımlı değişkenin karakterize ettiği olayın olması veya olmaması ile ilgileniriz (yani 1 ve 0 durumu) . Bunu gösterecek olan g() bağlantı fonksiyonu da aşağıdaki koşulları sağlamalıdır
Bağımlı değişken y Başarı Olasılığı (p) ve Başarısızlık olasılığı (1-p) olduğu için;
  • g() daima pozitif ( p >= 0)
  • g() daima küçük veya eşit 1 ( p <= 1)
olmalıdır. Şimdi bu iki özelliği sağlayan bir fonksiyon belirleyebilirsek tekniğe bir başlangıç sağlayabileceğiz.
Olasılık daima pozitif olacağından model olarak bir üstel fonksiyon kullanabiliriz. Bu fonksiyon ßo ve diğer bağımsız değişkenler için hiç bir zaman negatif olmayacaktır.

g = e^u   —(b)

Şimdi bunun herzaman 1 den küçük olması için bunu  g  den daha büyük bir sayıya bölmeliyiz

p  =  e^u / e^u + 1   —(c)

Şimdi  (a), (b) ve  (c) bağıntılarını kullanırsak p olasılığını kısaca :

              p = e^y/ 1 + e^y           — (d)

verebiliriz. Burada p olasılık ve (d)  Logit Fonksiyonudur.
Şimdi p başarının olasılığı ise, 1-p başarısılık olasılığı olacak ve:

q = 1 – p = 1 – (e^y/ 1 + e^y)    — (e)

olarak verilecektir. Bölme ile, (d) / (e),

(1)        p/(1-p) = e^y

ve her iki tarafın logaritmasını alarak

(2)        log (p/1-p) = y      veya   y = log(p/1-p)

şimdi y nin yerine lineer modelini koyarsak

(3)     log (p/1-p) = u(x)

Olur.
Buna göre log(p/1-p) aradığımız bağlantı fonksiyonudur. Bunun serbest değişkenlere göre en minimal durum olduğu açık.

Üstünlük Oranı (Odd Ratio)

p/1-p) üstünlük oranı (odd ratio) olarak bilinmektedir. Yukarda p lerin serbest değişkenlerin bir lineer fonksiyonu olduğunu söylemiştik. Böylece lineer olmayan bir yapıyı lineer bir şekilde gösterebilmiş olduk. Doğal olarak buradaki  b  parametreleri bildiğimiz lineer regression teknikleri ile elde edilemez.
Buraya kadar kolay geldik de bundan sonrası pek kolay değil. Eğer M gözlem ve N değişkenden oluşan bir verisetiniz varsa logit modelinde N+1 ß parametresini belirlemek durumundasınız. Bunun için de seçtiğiniz olasılık dağılımının (genelde binom dur) Likelihood fonksiyonunun maksimize eden bir teknoloji kullanmalısınız. Bu da Newton tipi optimizasyon algoritmalarını devreye sokmayı gerektiriyor. bunun el ile veya rutin programlama ile yapılamıyacağı açık. En iyisi burada R platformunun güçlü paketlerini devreye sokmak. 

R ile Lojistik Regresyon

Lojistic regression R ile birlikte default olarak yüklenen stats paketinde var. Yani R ile hiç bir paket yüklemeden doğrudan logistic regression yapılabiliyor. Bunun için glm() fonksiyonunu kullanmak yeterli. Genel glm komutu: 
Bütün x değişkenleri için:

glm(formula = target ~ . , family = “binomial”, data = runset)

 Seçilmiş x değişkenleri için:

glm(formula = target ~ x1 + x2 + x3,…, family = “binomial”, data = runset)

Burada runset elden geçirilmiş algoritmaya hazırlanmış veriseti anlamına geliyor. Bazı değişkenlerin ayıklanması veya scale edilmesi gerekebilir.

 

UCI Kardioloji verisetine Logistics Regression

Şimdi bundan sonrasınma bir örnekle devam edelim ve örnek olarak UCI Kardioloji verisetinin uyralanmış versiyonunu kullanalım. Şimdi kadın-Erkek bir kişinin kardiolojik verilere gore kalp hastası olma olasılığını araştıracağız.
Algoritmayı uygulamak isteyenler R ile bu verisetini datalabtr.com portalinden kolayca indirebilirler. Bu set kolay anlaşılması için orijinalinden biraz farklıdır.
path<- “http://datalabtr.com/wp-content/uploads/2017/03/KARDIO.csv
 kardio<-as.data.frame(read.table(path, sep=”;”, dec=”,”, header=TRUE))
str(kardio)
‘data.frame’:   270 obs. of  15 variables:
 $ id       : int  1 2 3 4 5 6 7 8 9 10 …
 $ diagnosis: int  1 0 1 0 0 0 1 1 1 1 …
 $ cins     : int  0 1 0 0 1 0 0 0 0 1 …
 $ yas      : int  70 67 57 64 74 65 56 59 60 63 …
 $ agri     : int  4 3 2 4 2 4 3 4 4 4 …
 $ kanbas   : int  130 115 124 128 120 120 130 110 140 150 …
 $ serkol   : int  322 564 261 263 269 177 256 239 293 407 …
 $ kansek   : int  0 0 0 0 0 0 1 0 0 0 …
 $ elkardio : int  2 2 0 0 2 0 2 2 2 2 …
 $ kalphizi : int  109 160 141 105 121 140 142 142 170 154 …
 $ egzagri  : int  0 0 0 1 1 0 1 1 0 0 …
 $ stdep    : num  2.4 1.6 0.3 0.2 0.2 0.4 0.6 1.2 1.2 4 …
 $ stegim   : int  2 2 1 2 1 1 2 2 2 2 …
 $ anadamar : int  3 0 0 1 1 0 1 1 2 3 …
 $ talyum   : int  3 7 7 7 3 7 6 7 7 7 …
runset <- kardio[-1] # id faktörü ayıklanmalı
print(dim(runset))
head(runset)
  diagnosis cins yas agri kanbas serkol kansek elkardio kalphizi egzagri stdep stegim anadamar talyum
1         1    0  70    4    130    322      0        2      109       0   2.4      2        3      3
2         0    1  67    3    115    564      0        2      160       0   1.6      2        0      7
3         1    0  57    2    124    261      0        0      141       0   0.3      1        0      7
4         0    0  64    4    128    263      0        0      105       1   0.2      2        1      7
5         0    1  74    2    120    269      0        2      121       1   0.2      1        1      3
6         0    0  65    4    120    177      0        0      140       0   0.4      1        0      7
# diagnosis=0 Saglam    diagnosis=1 Hasta
# cins = 0 Erkek  cins = 1 Kadın
table(runset$diagnosis)
  0   1
150 120  # 150 saglam 12o hasta verisi
table(runset$cins)
0 1
183 87  # 183 Erkek 87 Kadın verisi
table(runset$diagnosis,runset$cins)

0 1
0 83 67
1 100 20 # Saglam-Hasta, Erkek-Kadın Tablosu

# Train ve Test verisetlerini oluşturmak
m <- dim(runset)[1]
sec <- sample(1:m, size = round(m/3), replace = FALSE)
egit <- runset[-sec,]
test <- runset[ sec,]
dim(egit)
dim(test)
#logistic regression model
Bununla ilgili komutlar R/stats paketinde bulunur ve default olarak yüklenmiştir. Başka bir paket yüklemeyi gerektirmez. Standart komutu

model <- glm (diagnosis ~ . ,  data = egit, family = binomial)

summary(model)
Call:
glm(formula = diagnosis ~ ., family = binomial, data = egit)
Deviance Residuals:
    Min       1Q   Median       3Q      Max
-2.3704  -0.5455  -0.1746   0.4308   2.2358
Coefficients:
             Estimate Std. Error z value Pr(>|z|)
(Intercept) -7.984631   3.785080  -2.110  0.03490 *
cins        -1.528814   0.648458  -2.358  0.01839 *
yas          0.008788   0.032749   0.268  0.78843
agri         0.879513   0.271776   3.236  0.00121 **
kanbas       0.023181   0.013700   1.692  0.09065 .
serkol       0.009089   0.005147   1.766  0.07743 .
kansek      -0.477673   0.645693  -0.740  0.45943
elkardio     0.270866   0.236109   1.147  0.25130
kalphizi    -0.020249   0.012697  -1.595  0.11076
egzagri      0.518696   0.513305   1.011  0.31226
stdep        0.469280   0.289491   1.621  0.10501
stegim      -0.054201   0.493763  -0.110  0.91259
anadamar     0.724204   0.314289   2.304  0.02121 *
talyum       0.313090   0.130102   2.406  0.01611 *
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 248.73  on 179  degrees of freedom
Residual deviance: 127.37  on 166  degrees of freedom
AIC: 155.37
Number of Fisher Scoring iterations: 6

# Predict fonksiyonu ile tahmin değerleme

predict <- predict(model, newdata=test, type = ‘response’)
#confusion matrix
tm <- table(test$diagnosis, predict > 0.5)
str(tm)
 ‘table’ int [1:2, 1:2] 45 4 9 32
 – attr(*, “dimnames”)=List of 2
  ..$ : chr [1:2] “0” “1”
  ..$ : chr [1:2] “FALSE” “TRUE”
print(tm)
    FALSE TRUE
  0    45    9
  1     4   32
top <- sum(tm)

 # Hesaplanmış performans metrikleri

(tm[1]+tm[4])/top # Accuracy
[1] 0.8555556
tm[1]/(tm[1]+tm[2]) # Sensitivity
[1] 0.9183673
tm[4]/(tm[4]+tm[3]) # Specificity
[1] 0.7804878
tm[1]/(tm[1]+tm[3]) # Precision
[1] 0.8333333
tm[1]/(tm[1]+tm[2]) # Recall
[1] 0.9183673
(tm[1]+tm[2])/top # Prevalence
[1] 0.5444444
tm[1]/top # Detection Rate
[1] 0.5
(tm[1]+tm[3])/top # Detection Prevalence
[1] 0.6

#ROCR Curve

library(ROCR)
p <- predict(model, newdata=test, type=”response”)
pr <- prediction(p, test$diagnosis)
prf <- performance(pr, measure = “tpr”, x.measure = “fpr”)
plot(prf, colorize = TRUE)
auc <- performance(pr, measure = “auc”)
auc <- auc@y.values[[1]]auc
print(auc)
[1] 0.9393004

 

#plot glm (ggplot2  ile)

library(ggplot2)
ggplot(egit, aes(x=yas, y=diagnosis)) + geom_point() +
stat_smooth(method=”glm”, se=FALSE) + facet_wrap(~cins)

Logistic Regression Model Performansı

Logistic regression modelinin performansını belirlemek için kullanılan araçlardan bağımsız bir kaç metriğe sahibiz.
1. AIC (Akaike Information Criteria) – Logistic regression için R^2 karşılığı AIC dir. AIC model parametrelerinin sayısına bağlı olarak modeli cezalandıran bir katsayıdır. Buna göre AIC si en küçük model en iyi modeldir.
2. Confusion Matrix: Gerçek ve tahmin sonuçlarının tablo formunda karşılaştırılmasıdır. Modeldeki accuracy için
     accuracy = (gerçek pozitif + gerçek negatif)/(gerçek pozitif+gerçek negatif+yanlış pozitif+yanlış negatif)
oranı kullanılır. Bizim modelimizde;
(tm[1]+tm[4])/top # Accuracy
[1] 0.85
elde edildi. 1 e yakın ve iyi bir sonuç olarak görülebilir.
3. ROC Curve: Receiver Operating Characteristic(ROC) modelin performansını gerçek pozitif oran ve yanlış pozitif oran ilşikisi şeklinde grafik olarak özetler. Eğrilik sol üst köşeye yaklaştıkça model performansı iyi sayılır.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail