Lineer Regresyon
Bir hedef değişkeninin bir veya daha fazla kaynak değişkenine olan bağlantısını bulmak için en basit yöntemlerden biri bu ilişkinin lineer olduğunu kabul etmektir, yani eldeki değişkenlerin belli ağırlıklar ile çarpımının toplamı olarak. İlk başta bilinmeyen bu ağırlıkları, ya da katsayıları bulmak için En Az Kareler (Least Squares) en iyi bilinen yöntemlerden biri; En Az Kareler daha önce pek çok değişik ders notlarında, yazıda türetildi. Mesela [7], [8], ya da [9].
Lineer Regresyonun sadece iki değişken temelli işlemek gerekirse,
$$ Y = \beta_0 + \beta_1 x + \epsilon$$
olabilir. Eğer iki değişkenden fazlası var ise bu bir düzlem uydurulacak demektir. Değişken $\epsilon$, $N(0,\sigma^2)$ dağılımından gelen hatadır ve $\sigma$ bilinmez. Eğer veriyi $(x_1,y_1),...(x_n,y_n)$ ikili olarak grafiklesek
gibi gözükebilirdi, lineer regresyon ile yapmaya çalıştığımız tüm noktalara olabilecek en yakın düz çizgiyi (üstte görüldüğü gibi) bulmaktır.
Bu düz çizgiyi (ki boyutlu ortamda bu çizgi bir hiper düzlem olurdu, $\beta_2,\beta_3,..$ gibi daha fazla katsayı gerekirdi), En Az Kareler ile bulduktan sonra elimize geçenler katsayı değerlerinin tahminidir, ki bunlar bazı kaynaklarda $\hat{\beta}_0,\hat{\beta}_1$ olarak tanımlanır, bu notasyon istatistikteki "tahmin edici (estimator)" notasyon ile uyumlu. Bu tahmin ediciler ile elde edilen $y$'nin kendisi de bir tahmin edici haline gelir ve bir düz çizgiyi tanımlar,
$$ \hat{y} = \hat{\beta}_0 + \hat{\beta}_1x $$
Katsayıların tahmin edicilerinin de dağılımı vardır ve bu dağılım, ideal şartlarda bir normal dağılımdır. İspat için bu yazının sonuna bakınız.
Örnek olarak lineer regresyon için tarihte kullanılan neredeyse ilk veri setini seçeceğim. Bu veri çocukların ve onların ebeveynlerinin boy uzunluğunu içeren Galton'un 19. yüzyılda analiz ettiği veri setidir. Hatta öyle ki regresyon kelimesinin bile bu problem ile alakası var, İngilizce regress kelimesi baştaki (çoğunlukla daha iyi olmayan) bir hale dönmek anlamında kullanılır, ve problemde çocukların boyunun ebeveyn boyuna "geri döndüğü" ya da ondan ne kadar etkilendiği incelenmektedir.
import pandas as pd
df = pd.read_csv('galton.csv',sep=',')
print df.head(4)
child parent
0 61.7 70.5
1 61.7 68.5
2 61.7 65.5
3 61.7 64.5
Şimdi regresyonu işletelim, sadece bağımsız tek değişken olacak, ebeveyn
boyu parent
, hedef değişken ise çocuk child
içinde.
import statsmodels.formula.api as smf
results = smf.ols('child ~ parent', data=df).fit()
print results.summary()
OLS Regression Results
==============================================================================
Dep. Variable: child R-squared: 0.210
Model: OLS Adj. R-squared: 0.210
Method: Least Squares F-statistic: 246.8
Date: Thu, 03 Nov 2016 Prob (F-statistic): 1.73e-49
Time: 09:11:04 Log-Likelihood: -2063.6
No. Observations: 928 AIC: 4131.
Df Residuals: 926 BIC: 4141.
Df Model: 1
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [95.0% Conf. Int.]
------------------------------------------------------------------------------
Intercept 23.9415 2.811 8.517 0.000 18.425 29.458
parent 0.6463 0.041 15.711 0.000 0.566 0.727
==============================================================================
Omnibus: 11.057 Durbin-Watson: 0.046
Prob(Omnibus): 0.004 Jarque-Bera (JB): 10.944
Skew: -0.241 Prob(JB): 0.00420
Kurtosis: 2.775 Cond. No. 2.61e+03
==============================================================================
Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 2.61e+03. This might indicate that there are
strong multicollinearity or other numerical problems.
print pd.Series(results.resid).describe()
count 9.280000e+02
mean 4.484995e-13
std 2.237339e+00
min -7.805016e+00
25% -1.366144e+00
50% 4.869321e-02
75% 1.633856e+00
max 5.926437e+00
dtype: float64
Bu çıktıda gösterilenler ne anlama gelir?
1) coef
altında görülen değerler sırasıyla $\beta_o,\beta_1$
tahminleridir, yani $\hat{\beta}_o,\hat{\beta}_1$. Bunlar bulmak istediğimiz
katsayılar. İki boyutta olduğumuz için düz bir çizgiden bahsediyoruz, bu
çizginin $y$ eksenini kestiği yer kesi (intercept) $\hat{\beta}_0$'da ve ebeyne
(parent
) tekabül eden katsayı $\hat{\beta}_1$.
Teorik olarak eğer bir katsayı sıfır ise bu işe yaramaz bir katsayıdır, çünkü modele hiçbir şey "eklemez". Fakat Basit En Az Kareler (ordinary least squares -OLS-)'in hesapladığı bir tahmindir nihayetinde ve hiçbir zaman sıfır olmayacaktır. O zaman soruyu biraz daha değiştirmek gerekir: istatistiki olarak düşünürsek gerçek katsayının sıfır olma olasılığı nedir? Katsayı yanında görülen $t$ ve $P>|t|$ (diğer ismiyle p-değeri) bunun için kullanılır.
$t$ değeri bir katsayı için onun tahminini ve standart hatasına bölerek elde edilir. Üstteki çıktıda mesela 23.9415/2.811=8.517. Bu değer katsayı tahmininin veriden veriye ne kadar değişik sonuçlar verebileceğini (variability) gösterir, ve bir bakıma bu katsayı tahmininin kesinliği (precision) hakkında bir rapordur. Eğer bir katsayı tahmini, standart hatasına göre büyük ise (ki bölüm bunu gösterir) bu katsayının sıfır olmadığına dair güçlü bir işaret olarak alınabilir.
Peki ne kadar büyük bir sayı büyük sayılmalıdır? Bunun için p-değerine başvuruyoruz. P-değerini hesaplamak için t değeri ve standart hatasının dağılımından bahsetmek lazım.
t değeri bir rasgele değişken olduğu için bir dağılımı vardır, ve bu dağılım Öğrenci t (Student t) dağılımıdır. Sebep şu, t değerinin kendisi de iki rasgele değişkeninin bölümüdür, bu değişkenlerden biri katsayının kendisidir, ki bu değer nüfustaki "gerçek" katsayı etrafında normal olarak dağılmış bir rasgele değişken olarak kabul edilir. Diğeri ise, yani bölen, tahmin edici $S$'tır ki bir chi kare rasgele değişkenin kareköküdür. Bu bölümün Öğrenci t dağılımına sahip olduğu daha önce gösterildi.
Standart hata ise, artık / kalıntı değerlerle (residuals) alakalıdır
(results.resid
içinde), ve bu değerler model uydurulduktan sonra o modeli
kullanarak gerçek veriye ne kadar uzak düştüğümüzü gösterir. Formül olarak her
veri noktası $i$ için $r_i = y_i - \beta_1x_i - \beta_o$. Her katsayı için de
ayrı ayrı kalıntı hesaplanabilir.
İdeal durumda, yani modelin doğru, veriye uyduğu durumda artıkların mükemmel bir Normal dağılıma sahip olması gerekir, çünkü veri içindeki tüm örüntü, kalıp model tarafından "bulunmuştur" ve geri kalanlar gürültüdür (gürültü tabii ki Normal dağılımda). İdeal ortamda OLS algoritmasının, matematiksel olarak, ortalaması (mean) sıfır olan artıklar üretmesi garantidir. Bir diğer varsayım uyduralan değişkenlerin katsayılarının onların "gerçek" değerleri etrafında merkezlenen bir Normal dağılıma sahip olduğudur (ispat için [10] yazısının sonuna bakılabilir). Bu normallik önemli çünkü katsayı tahmini ile standart hatayı bölünce başka bir Öğrenci t dağılımı ortaya çıkacak.
Kalıntıların normalliği QQ grafiği ile kontrol edilebilir, bkz [11],
import statsmodels.api as sm
sm.qqplot(results.resid)
plt.savefig('stat_linreg_01.png')
Oldukça düz bir çizgi, uyum başarılı demek ki..
Şimdi, katsayı için olan kalıntı değerlerinin karesini alıp toplarsak ve karekökü alırsak, bu rasgele değişkenin Chi Kare (Chi Square) olarak dağıldığı bilinir, ve yine bilinir ki standart normal rasgele değişken, bolu, chi kare karekökü bize bir Öğrenci t dağılımını verir, mesela
$$ t = \frac{Z}{\sqrt{V / m}} = t_m$$
serbestlik derecesi $m$ olan bir Öğrenci t rasgele değişkenidir.
Öğrenci t'den p-değeri üretmek için t değerinin sıfırdan ne kadar uzağa düştüğü bir Öğrenci t olasılık hesabına dönüştürülür. Önce katsayının tam değeri (absolute value) alınır, eksileri artı yaparız, çünkü sıfırdan uzaklık ile ilgileniyoruz sadece ve Öğrenci t dağılımı simetriktir, sonra bu değer $t_m$ dağılımı üzerinden bir olasılık hesabına dönüştürülür. Yani "katsayı / standart hata bir $t_m$ ile dağılmış ise, elde edilen bölümün o dağılımdan gelme olasılığı nedir?" gibi bir soru. Olasılık hesabı yoğunluk fonksiyonu üzerinde bir alan hesabıdır, t değeri 2 ise ve $t_5$ için bu alan hesabı şöyle,
Ayrıca bu olasılık sonucu sıfır ile karşılaştırmak kolay olsun diye 1'den çıkartılır ve 2 ile çarpılır, istatistiğin böylece iki taraflı (two-sided) olduğu belirtilir. $m$, veri nokta sayısı, eksi katsayı sayısı, artı bir olarak hesaplanıyor. Eğer sonuç 0.05'ten küçük ise bu iyiye işarettir, 0.05'ten büyük olan değerler iyi değildir. Galton örneğinde $\hat{\beta_0}$ için,
from scipy.stats import t
print 2*(1-t(927).cdf(np.abs(8.517)))
0.0
Üstteki sonuç 0.0 değeri çok iyi. Demek ki bu katsayı önemli (significant).
2) Artıklarda sıfırdan sapma, herhangi bir yöne doğru yamukluk (skew) OLS
uyumsuzluğunun işareti olabilir, üstte artıklar üzerinde describe
çağrısı ile medyanı (\%50 noktası) hesaplattık, bu değerin 0.04 ile sıfırdan
çok az sağa doğru saptığını görüyoruz. \%25, \%75 bölgelerinin işaretlerine
bakmadan tam (absolute) değerlerine bakalım, 1.36 ve 1.63, çok az
farklılar. İdealde hiç fark olmamasını isteriz çünkü normal dağılım
simetriktir, her iki tarafında da bu bölgelerin yakın değerde olmasını
bekleriz. Fakat bu değerler alarm yaratacak nitelikte değil.
Artıkların minimum, maksimum (min,max
) değerleri verideki ekstrem, aykırı
değerlere (outlier) dair bir işaret olabilir.
3) $R^2$, ya da R-squared
, modelin kalitesiyle alakalıdır, ne kadar
büyükse o kadar iyidir. Matematiksel olarak bu değer $y$'nin değişiminin /
varyansının oran olarak ne kadarının regresyon modeli tarafından
"açıklanabildiğini" belirtir. Üstteki örnekte $R^2=0.21$ ise model varyansın
yüzde 21'ini açıklıyor. Ya da "bir çocuğun boyunun yüzde 21'i ebeveyn boyu ile
açıklanabilir" sözü de söylenebilir. Geri kalan 0.75'lik yani yüzde 75'lik
"açıklanamayan" kısmın değişik sebepleri olabilir; belki hesaba katmadığımız
değişkenler vardır, ya da örnekleme prosedüründe hatalar yapılmıştır, ya da
lineerlik bu probleme uygun değildir, vs.
Tavsiyemiz düz $R^2$ yerine OLS çıktısında görülen "düzeltilmiş $R^2$" yani
Adj. R-squared
bilgisinin kullanılmasıdır, çünkü bu bilgi modeldeki
değişken sayısını da hesaba katar ve daha iyi bir ölçüttür.
4) F istatistiği: Bu istatistik tüm modelin önemli mi önemsiz mi olduğunu irdeler. Eğer modelde sıfır olmayan en az bir katsayı var ise model önemlidir (herhangi bir $i$ için $\beta_i \ne 0$). Eğer tüm katsayılar sıfır ise model önemsizdir ($\beta_0=\beta_1,\dots,\beta_n=0$). Örnekte
... F-statistic: 246.8
... Prob (F-statistic): 1.73e-49
Prob (F-statistic)
bir p-değeri, ve bu değer 0.05'ten küçük ise model
büyük bir ihtimalle önemlidir, eğer 0.05'ten büyük ise büyük ihtimalle önemli
değildir. Üstteki p-değeri 1.73e-49 gösteriyor, çok ufak bir değer, yani bu iyi.
Not: Çoğu kişi OLS çıktısında ilk önce $R^2$'ye bakar, fakat bilgili istatistikçi F'e bakar, çünkü bir model önemli değilse, geri kalan hiçbir ölçütün önemi yoktur.
Nihai analiz olarak bu veride parent
katsayısının pozitif olan değerine
bakarak çocuk ve ebeveyn boyu arasında bir bağlantı olduğunu söyleyebiliriz.
Basamaklı Regresyon (Stepwise Regression)
Eğer elimizde çok fazla değişken var ise, bu değişkenlerden hangilerinin en iyi olduğunu seçmek oldukça zor olabilir. Önemlilik sayıları burada biraz yardımcı olabilir, fakat değişkenlerin eklenip, çıkartılması regresyonun tamamını etkilediği için deneme / yanılma ile ekleme / çıkartma işleminin yapılması gerekebilir, ki bu işlemi elle yapmak külfetli olur. Acaba bu yöntemi otomize edemez miyiz?
R dilindeki lm
'in step
adlı özelliği burada yardımcı
olabilir. Önce yapay bir veri üretelim,
import pandas as pd
n = 100
df = pd.DataFrame()
np.random.seed(10)
df['x1'] = np.random.normal(size=n)
df['x2'] = np.random.normal(size=n)
df['x3'] = np.random.normal(size=n)
df['x4'] = np.random.normal(size=n)
df['y'] = 10 + -100*df['x1'] + 75*df['x3'] + np.random.normal(size=n)
Yapay veride farkedileceği üzere x2,x4
modele eklenmedi bile. Bu
değişkenler önemsiz, ürettiğimiz için biz bunu biliyoruz. Bakalım regresyon bunu
keşfedecek mi? Şimdi tüm değişkenlerle bir OLS yapalım,
%load_ext rpy2.ipython
%R -i df
%R fullmodel <- lm(y~x1+x2+x3+x4,data=df)
%R -o res res = summary(fullmodel)
print res
Call:
lm(formula = y ~ x1 + x2 + x3 + x4, data = df)
Residuals:
Min 1Q Median 3Q Max
-3.15789 -0.63251 -0.01537 0.58051 2.30127
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.94953 0.09378 106.098 <2e-16 ***
x1 -99.95333 0.09686 -1031.975 <2e-16 ***
x2 -0.04103 0.09500 -0.432 0.667
x3 75.14720 0.10240 733.851 <2e-16 ***
x4 0.04863 0.10015 0.486 0.628
---
Residual standard error: 0.9292 on 95 degrees of freedom
Multiple R-squared: 0.9999, Adjusted R-squared: 0.9999
F-statistic: 4.23e+05 on 4 and 95 DF, p-value: < 2.2e-16
Görüldüğü gibi daha baştan x2,x4
önemsiz bulundu. Ama daha karmaşık bir
modelde bu o kadar rahat bulunmayabilirdi. Şimdi step
ile tam modelden bu
değişkenler çekip çıkartılabiliyor mu ona bakacağız.
R dilinde basamaklı regresyon iki şekilde işler. Ya tam modelden geriye gidersiniz yani tam modelden ise yaramayan değişkenleri atarsınız, ya da en baz (boş) modelden başlayıp ileri gidersiniz yani ekleye ekleye en iyi değişkenlere erişmeye uğraşırsınız. İlk önce eliminasyonu görelim,
%R reducedmodel <- step(fullmodel, direction="backward")
%R -o resred resred<-summary(reducedmodel)
print resred
Call:
lm(formula = y ~ x1 + x3, data = df)
Residuals:
Min 1Q Median 3Q Max
-3.1667 -0.6078 -0.0256 0.5732 2.3592
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.95039 0.09251 107.6 <2e-16 ***
x1 -99.95181 0.09540 -1047.7 <2e-16 ***
x3 75.14514 0.10101 744.0 <2e-16 ***
---
Residual standard error: 0.9217 on 97 degrees of freedom
Multiple R-squared: 0.9999, Adjusted R-squared: 0.9999
F-statistic: 8.599e+05 on 2 and 97 DF, p-value: < 2.2e-16
Doğru sonuçlar bulundu. Bu yöntem fena değildir, ama bazen o kadar çok değişken
vardır ki tam modelle başlamak iyi bir fikir olmayabilir, o zaman boş başlayıp
ileri gitmek daha mantıklı olabilir. Boş modelde sadece y ~ 1
olacak,
biraz garip gelebilir, çünkü hiç değişken yok (ki bu durumda uydurulan tüm
değişkenler sadece $y$'nin ortalamasıdır). Neyse, ileri giden modelde
step
'e hangi değişkenlerin aday / potansiyel değişken olduğunu belirtmek
gerekir, bunu scope
ile yaparız,
%R minmodel <- lm(y ~ 1,data=df)
%R fwd <- step(minmodel, direction="forward", scope = ( ~ x1 + x2 + x3 + x4))
%R -o fwdres fwdres <- summary(fwd)
print fwdres
Call:
lm(formula = y ~ x1 + x3, data = df)
Residuals:
Min 1Q Median 3Q Max
-3.1667 -0.6078 -0.0256 0.5732 2.3592
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.95039 0.09251 107.6 <2e-16 ***
x1 -99.95181 0.09540 -1047.7 <2e-16 ***
x3 75.14514 0.10101 744.0 <2e-16 ***
---
Residual standard error: 0.9217 on 97 degrees of freedom
Multiple R-squared: 0.9999, Adjusted R-squared: 0.9999
F-statistic: 8.599e+05 on 2 and 97 DF, p-value: < 2.2e-16
Yine aynı sonuca geldik. Tabii bu çok basit bir yapay veri, o yüzden aynı yere gelmiş olmamız şaşırtıcı değil. Gerçek problemlerde geriye ve ileri giden modellerin ikisini de deneyip sonuçları karşılaştırmak iyi oluyor. Sonuçlar şaşırtıcı olabilir.
Bir diğer tavsiye basamaklı regresyonu her derda deva bir yöntem olarak görmemek, çünkü üstteki çıktılara göre sihirli bir şekilde en kullanışlı alt kümeyi buluveriyor, vs, fakat bu metot, değişkenleri iyi tanıyan birisi tarafından dikkatli bir şekilde alt kümenin elenip, seçilerek bulunması yerine geçemez. Bunu özellikle belirtiyoruz, çünkü bazılarının aklına şöyle bir şey gelebilir,
%R full.model <- lm(y ~ (x1 + x2 + x3 + x4)^4)
%R reduced.model <- step(full.model, direction="backward")
Üstte görülen ^4
kullanımı dört değişken arasındaki tüm mümkün
etkileşimleri (interaction) ortaya çıkartır, yani
x1:x2,x1:x2:x3:x4,x3:x4,..
gibi ve bunların tamamını basamaklı
regresyona sokar, çünkü bu cinliğe göre nasılsa eliminasyon metotu ise yaramayan
değişkenleri atacaktır (!). Bu metot iyi işlemeyecektir, çoğu etkileşimin hiçbir
anlamı yoktur, step
fonksiyonu herhalde çok fazla seçenek arasında
boğulur, sonuçta elimizde bir sürü ise yaramaz değişken kalacaktır.
Soru
Diyelim ki elimde bir veri seti var ve üzerinde OLS uyguladım, sonuçlara baktım. Eğer bu veri setini alıp, kendisine eklersem, yani veriyi iki katına çıkartırsam, ilk işlettiğim OLS'teki katsayılara, ve standart hataya ne olur?
Cevap
Dikkat, bu soru bir mülakat sorusudur! :) Düşünelim, sezgisel bir şekilde, 2 boyutta, uydurulan tek çizginin altında ve üstünde yine aynı verilerin bir kez daha tekrarlanacağını farkederiz, ki bu çizginin yerini değiştirmezdi. Yani katsayılar aynı kalırdı. Fakat standart sapmaya ne olurdu? Artıklardan başlayalım,
$$ r_i = y_i - \beta_0 + \beta_1x_i $$
Veriyi ikiye katlayınca,
$$ 2y_i - 2\beta_0 + 2\beta_1x_i \Rightarrow 2r_i $$
Standart hata hesabı, kolaylık için $n-1$ yerine $n$, ve $C = r_i^2$,
$$ \sqrt{\frac{\sum_i (2r_i)^2}{2n}} =
\sqrt{\frac{4 \sum_i r_i^2}{2n}} =
\sqrt{\frac{4 C}{2n}}
$$
Eski veri seti için aynı hesap $\sqrt{C/n}$. İki tarafta da karekök var, sadece karekök içine bakalım,
$$
\frac{C}{n} \quad ? \quad \frac{4 C}{2n}
$$
Aradaki ilişki nedir? Eğer veriyi ikiye katlarsak $C$ 4 katına çıkıyor, ama herhangi bir $n > 2$ için, $2n$ bu büyümeyi geçer, ve sağdaki büyüklük soldakina nazaran küçülür.
$$
\frac{C}{n} \quad > \quad \frac{4 C}{2n}, \qquad n>2 \textrm{ için }
$$
Demek ki yeni veri setinde standard hata küçülür. Eğer bu değer küçülürse, katsayılara ait olan standart hatalar da, ki onlar biraraya gelerek standart hatayı oluşturacaklar, küçülecektir. Standart hatanın küçülmesi aslında şaşırtıcı olmamalı, aynı yönde daha fazla veri alınca elimizdeki katsayılarından daha "emin" hale geldik. Bu iyi bir şey olarak görülebilirdi belki, ama bu durumun modelin geri kalanı üzerindeki etkilerini şimdi düşünelim. Eğer katsayı aynı kalır, hata küçülürse katsayı / hata olarak hesaplanan t değeri buyur. Daha büyüyen t değeri daha küçülen p-değeri demektir! Yani veriyi ikiye katlayınca birden bire önemsiz olan ($>0.05$) bir değişken, önemli hale gelebilir. Altta örneğini görüyoruz,
import statsmodels.formula.api as smf
results = smf.ols('y~x1+x2+x3+x4', data=df).fit()
print results.summary()
OLS Regression Results
==============================================================================
Dep. Variable: y R-squared: 1.000
Model: OLS Adj. R-squared: 1.000
Method: Least Squares F-statistic: 4.230e+05
Date: Sat, 14 Mar 2015 Prob (F-statistic): 5.97e-201
Time: 15:56:03 Log-Likelihood: -131.99
No. Observations: 100 AIC: 274.0
Df Residuals: 95 BIC: 287.0
Df Model: 4
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [95.0% Conf. Int.]
------------------------------------------------------------------------------
Intercept 9.9495 0.094 106.098 0.000 9.763 10.136
x1 -99.9533 0.097 -1031.975 0.000 -100.146 -99.761
x2 -0.0410 0.095 -0.432 0.667 -0.230 0.148
x3 75.1472 0.102 733.851 0.000 74.944 75.350
x4 0.0486 0.100 0.486 0.628 -0.150 0.247
==============================================================================
Omnibus: 3.126 Durbin-Watson: 2.267
Prob(Omnibus): 0.210 Jarque-Bera (JB): 2.795
Skew: -0.191 Prob(JB): 0.247
Kurtosis: 3.724 Cond. No. 1.26
==============================================================================
Veriyi ikiye katlayıp bir daha OLS,
df2 = pd.concat((df,df))
results = smf.ols('y~x1+x2+x3+x4', data=df2).fit()
print results.summary()
OLS Regression Results
==============================================================================
Dep. Variable: y R-squared: 1.000
Model: OLS Adj. R-squared: 1.000
Method: Least Squares F-statistic: 8.683e+05
Date: Sat, 14 Mar 2015 Prob (F-statistic): 0.00
Time: 15:56:41 Log-Likelihood: -263.98
No. Observations: 200 AIC: 538.0
Df Residuals: 195 BIC: 554.4
Df Model: 4
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [95.0% Conf. Int.]
Intercept 9.9495 0.065 152.006 0.000 9.820 10.079
x1 -99.9533 0.068 -1478.512 0.000 -100.087 -99.820
x2 -0.0410 0.066 -0.619 0.537 -0.172 0.090
x3 75.1472 0.071 1051.389 0.000 75.006 75.288
x4 0.0486 0.070 0.696 0.487 -0.089 0.186
==============================================================================
Omnibus: 4.922 Durbin-Watson: 2.274
Prob(Omnibus): 0.085 Jarque-Bera (JB): 5.589
Skew: -0.191 Prob(JB): 0.0611
Kurtosis: 3.724 Cond. No. 1.26
==============================================================================
Görüldüğü gibi x4
artık $<0.05$ altında!
OLS'in bu tür nüanslarını bilmek iyi olur. Eğer veride tekrar varsa, herhangi bir sebeple, tekrarlayan verileri çıkartmak belki de mantıklı olacaktır.
ABD Başkanlık Yarışını Tahmin Etmek
ABD başkanlık yarışlarının oldukça tahmin edilebilir olduğu uzunca süredir iddia
edilmektedir. Bu alanda pek çok model var, Andrew Gelman'ın oldukça çetrefil,
MCMC kullanan modelinden [4] (ki bunun için başkasının yazdığı kod [5]'te
bulunabilir), ya da daha öz, basit bir metot [3] mevcuttur. En basit ve etkili
yöntem Değişim Zamanı (Time for Change) modeli, bu modele göre
başkanlık yarışının olduğu Haziran ayı itibariyle ekonomik büyüme yüzdesi
(gdp_growth
), mevcut başkanın net destek oranı (net_approval
, ki
bu rakam destek yüzdesinden desteklemeyen yüzdesi çıkartılarak hesaplanır) ve o
anki başkanının partisinin, 2 dönem ya da daha fazladır Beyaz Ev'de olup
olmadığı bilgisi 1/0 değeri ile kodlanarak (two_terms)
lineer regresyona
verilir ve hedef değişken olarak, yönetimi elinde tutan partinin ülke genelinde
tüm oyların (popular vote) yüzde kaç alacağı tahmin edilmeye uğraşılır.
Örnek olarak Clinton ve Bush I arasındaki 1992 yarısında Cumhuriyetçi adayın
(çünkü o zamanki başkan Cumhuriyetçi) yüzde kaç oy alacağı tahmin edilecek,
two_terms=1
çünkü iki dönem Cumhuriyetçi Reagan ardından bir dönem
Cumhuriyetçi Bush gelmiş, Cumhuriyetçiler uzun süredir baştalar.
Gore / Bush arasındaki 2000 yılı yarısında Demokratların yüzdesini tahmin etmeye uğraşıyoruz, çünkü başta Demokrat Clinton var, ve iki dönemdir orada. Net popülarite ve büyüme hep o anki başkan ve onun partisinin performansı ile alakalı. Bu regresyonu işlettiğimizde, sonuçlar şöyle,
import statsmodels.formula.api as smf
import pandas as pd
df = pd.read_csv('prez.csv')
print df.head() , '\n'
regr = 'incumbent_vote ~ gdp_growth + net_approval + two_terms'
results = smf.ols(regr, data=df).fit()
print results.summary()
year gdp_growth net_approval two_terms incumbent_vote
0 2012 1.3 -0.8 0 52.0
1 2008 1.3 -37.0 1 46.3
2 2004 2.6 -0.5 0 51.2
3 2000 8.0 19.5 1 50.3
4 1996 7.1 15.5 0 54.7
OLS Regression Results
==============================================================================
Dep. Variable: incumbent_vote R-squared: 0.901
Model: OLS Adj. R-squared: 0.878
Method: Least Squares F-statistic: 39.52
Date: Fri, 11 Sep 2015 Prob (F-statistic): 8.50e-07
Time: 21:57:48 Log-Likelihood: -32.747
No. Observations: 17 AIC: 73.49
Df Residuals: 13 BIC: 76.83
Df Model: 3
Covariance Type: nonrobust
================================================================================
coef std err t P>|t| [95.0% Conf. Int.]
--------------------------------------------------------------------------------
Intercept 51.4363 0.811 63.409 0.000 49.684 53.189
gdp_growth 0.5799 0.118 4.903 0.000 0.324 0.835
net_approval 0.0987 0.021 4.764 0.000 0.054 0.143
two_terms -4.2983 1.032 -4.164 0.001 -6.528 -2.069
==============================================================================
Omnibus: 0.333 Durbin-Watson: 1.545
Prob(Omnibus): 0.847 Jarque-Bera (JB): 0.484
Skew: -0.169 Prob(JB): 0.785
Kurtosis: 2.246 Cond. No. 71.4
==============================================================================
İnanılmaz bir başarı, Prob (F-statistic)
değeri neredeyse sıfır,
Adj. R-squared
değeri yüzde 80'den daha fazla, tüm değişkenler
istatistiki olarak önemli (P>|t|
değerleri 0.05'ten küçük).
Acaba bu modeli kullanarak geçmişteki yarışları "tahmin etsek" sonuç ne olurdu diye merak ediyoruz, bunun için tahmin edeceğimiz senenin veri noktasını dışarıda bırakarak (out-of-sample) regresyon işletip o seneyi bilmiyormuş gibi yapıp tahmin ediyoruz,
def out_of_sample_pred(year):
df2 = df[df['year'] != year]
results2 = smf.ols(regr, data=df2).fit()
conf = results2.conf_int()
pred = np.array(df[df['year'] == year])[0][:-1]; pred[0] = 1.
return np.dot(pred, conf)
# o senenin verisinin disarida birakarak gecmisi tahmin et
print 'bush/clinton'; print out_of_sample_pred(1992)
print 'gore/bush'; print out_of_sample_pred(2000)
print 'bush/kerry'; print out_of_sample_pred(2004)
print 'mccain/obama'; print out_of_sample_pred(2008)
print 'obama/romney'; print out_of_sample_pred(2012)
bush/clinton
[ 43.68758927 52.47911415]
gore/bush
[ 48.31291287 60.68132985]
bush/kerry
[ 50.66667848 55.79188333]
mccain/obama
[ 41.05409775 46.15966954]
obama/romney
[ 49.81182614 54.45584122]
Tahmin hesabında değişken katsayılarının \%95 güven aralıklarını veren
conf_int()
çağrısını kullandık, değişkenlerin noktasal değerlerini
kullanmadık, bu şekilde tahmine olan güvenimizi aralığın büyüklüğüne bakarak
görebilmiş olacağız. Dikkat: aslında tahminin güven aralığını hesaplamak
biraz daha ek iş gerektiriyor, türetilmesi [12] bölümünde.
Şimdi sonuçlara bakalım; Bush / Kerry yarışı için kesin Bush diyor (çünkü güven aralığının iki ucu da yüzde 50 üstünde), Bush kazandı. McCain / Obama için McCain kesin kaybedecek diyor, McCain kaybetti. Obama / Romney yarışı için Obama (neredeyse) kesin kazanacak diyor, Obama kazandı. Tahminler iyi!
Gore / Bush ilginç bir durum, Gore çok, çok daha şanslı, ama Gore kaybetti. Fakat bu seçimin ne kadar yakın olduğunu o zaman yarısı takip edenler hatırlar, ayrıca, Florida'da bir takım "şaibeli" işlerin (!) olduğu biliniyor, ve model ülke genelinde oyu tahmin etmeye uğraşıyor, ki ülke genelinde bakılınca Gore daha fazla oy almıştı. Amerikan sistemine göre başkanlık seçimleri de eyalet bazında hesaplanır, bir eyalette kazanan tüm oyları alır, bu sebeple ülke geneli ile eyalet bazı arasında uyumsuzluk ortaya çıkabiliyor.
Gore / Bush olayına bir diğer bakış açısı şöyle: oy yüzdesi tahminini yüzdenin kendisi için değil, kazanma / kazanmama için bir sinyal olarak kabul etmek, yani popüler oyun kime gittiğine bakmamak, o zaman modelimizin Göre / Bush seçimini başarısız tahmin ettiğini kabul etmek lazım. Bu şaşırtıcı değil aslında çünkü 2000'de Bush kazandığına kendisi bile şaşırmıştı.
2016 senesindeki yarışta kim kazanacak? Demokratların şansı şöyle (dikkat belli bir adaydan bahsetmiyoruz bile); Haziran 2016 itibariyle büyüme 2\%, Obama'nın net popülaritesi sıfır olduğu durumda (bu değişkenlerin ne olduğuna o tarihte tekrar bakılmalı),
conf = results.conf_int()
pred = [1., 2.0, 0.0, 1]
print np.dot(pred, conf), np.dot(pred, results.params)
[ 43.80446415 52.79105137] 48.2977577583
Yani Demokrat adayın kaybetme şansı daha fazla, her ne kadar kesin bir şey söylenemezse de, güven aralığının iki ucu da yüzde 50 altında (ya da üstünde) değil, Hillary Clinton'un işi zor olacaktı, ki kaybetti. Trump ülke genelinde oy çoğunluğunu kaybetti, ama eyalet bazında kazandı. Demek ki model tahminini kazanma sinyali olarak almak daha uygun.
Analiz
Model oldukça basit, 3 değişken ile tahmin yapılıyor, fakat bu basitlik aldatıcı olabilir. Modele neyin dahil edildiği yanında neyin dahil edilmediği de önemlidir, mesela.. ham petrol fiyatı, işsizlik, seçim yılındaki suç oranı, iklim vs kullanılmamış, sadece bu 3 değişken kullanılmış. Ya da model, Cumhuriyetçiler için ayrı, Demokratlar için ayrı bir tahmin üretmiyor, {\em o an başta hangi parti varsa} onun başarısını tahmin etmeye uğraşıyor. Yani bir bakıma iddiası şu, insanlar aslında başta olan partiye göre oy verirler, bir süre sonra (2 dönem ardından) onu değiştirmeye meyilli olurlar, ve o anda başta olan başkanın popülaritesi ve genel bir ekonomik performansını kullanarak onun partisi hakkında bir tamam / devam kararını verirler. Bu tür modelcilik yetenek ister. Basitlik zor iş!
Tahmin edilirliğin yüksekliği ve değişkenlerin azlığı hakkında bir diğer yorum; bu durum aslında o kadar da şaşırtıcı olmamalı belki de, çünkü başkanlık seçimi son derece kaba hatlı bir karar, tek bir kişi / parti hakkında karar veriliyor, ve doğal olarak seçim için kullanılan parametreler de oldukça genel. Bir bakıma, bu tahmin edilirlik iyi olarak ta görülebilir, stabilite, sakin ortamın işareti olarak algılanabilir. "Vay o taraf ne dedi, bu taraf ne dedi" gibi faktörlerle oylar haldır huldur inip çıkmıyor, belli genel parametreler ışığında sonuç ta dört ay önceden oldukça belli (baz veri Haziran sonu itibariyle alınır, seçim Kasım ayında).
Model Karşılaştırmak
Bu alanda, mesela gazetelerde, yorumlara rastlanıyor. Bunlardan biri "mevcut başkanın (incumbent) ikinci dönem için yarışa girerse avantajlı olduğu" söylemidir, ki üstteki modelin ilk halini keşfeden Abromitz de bunu söylemektedir. Bizim referans aldığımız model [6] o söylemi biraz değiştirmiş, avantajlı olan yerindeki başkan değil, dezavantajlı olan 2 dönemden fazla başta kalan parti. İnsanlar 2 veya daha dönemden fazla başta olan partiyi görevden almaya meyilli oluyor. Tabii eğer parti yeni başa gelmişse, o zaman dezavantaj olmadığı için bazı durumlarda "ilk dönem başkan avantajlıymış gibi" durmuş olabilir. Şimdi bu faraziyeyi test edelim, hangi model daha doğru? Yeni bir veri setinde bu değişikliği test edebiliriz,
import statsmodels.formula.api as smf
import pandas as pd
df = pd.read_csv('prez_incumb.csv')
regr = 'incumbent_vote ~ gdp_growth + net_approval + incumb_prez'
results = smf.ols(regr, data=df).fit()
print results.aic
84.6742088339
AIC sonucu arttı, bu modelin daha kötüleştiği anlamına gelir.
Not: Gayri-safi yurtiçi hasıla (GDP) 2. çeyrekteki artışına bakılıyor. Bu artış bir sene önceye kıyasla değil (year-over-year) bir önceki çeyreğe göre artıştır dikkat, ve sonra bu artış, yıl ölçeğine çıkartılır, $d$ artışı diyelim $(1+\d)^4 - 1$ formülü üzerinden. Yani "her çeyrekte artış $d$ olsaydı, tüm sene artışı nereye gelirdi?" sorusunun cevabı.
Kaynaklar
[1] Teetor, R Cookbook
[2] The Yhat Blog ,Fitting \& Interpreting Linear Models in R, http://blog.yhathq.com/posts/r-lm-summary.html
[3] Abramowitz, {\em Fasten Your Seat Belts: Polarization, Weak Economy Forecast Very Close Election}, http://www.centerforpolitics.org/crystalball/articles/abramowitzpolarizationmodel/
[4] Gelman, A., Bayesian Data Analysis
[5] Bayramlı, Books Data, https://github.com/burakbayramli/books/tree/master/Gelman_BDA_ARM/bda/election
[6] Linzer, R Code, https://github.com/dlinzer/BayesBARUG/blob/master/Linzer-BayesBARUG.R
[7] Bayramlı, Çok Değişkenli Calculus, Ders 9
[8] Bayramlı, Lineer Cebir, Ders 15
[9] Bayramlı, Bilgisayar Bilim, Yapay Zeka, Regresyon, En Az Kareler
[10] Bayramlı, Istatistik, Tahmin Aralıkları
[11] Bayramlı, Istatistik, Güven Aralıkları, Hipotez Testleri
[12] Bayramlı, Istatistik, Tahmin Aralıkları (Prediction Interval)
Yukarı