다중공선성과 VIF¶
다중공선성과 VIF에 대해 알아보겠습니다.
독립 변수 X 간에는 상관 관계가 없어야 하는데, 독립 변수간 상관 관계를 보이는 것을 다중공선성(Multicollinearity)이라고 합니다
VIF는 다중 회귀 모델에서 독립 변수간 상관 관계가 있는지 측정하는 척도입니다. VIF (Variance Inflation Factors, 분산팽창요인)를 계산 하는것입니다. VIF가 10이 넘으면 다중공선성 있다고 판단하며 5가 넘으면 주의할 필요가 있는 것으로 봅니다.
VIF 계산 방법¶
$ VIF = {1\over 1 - R ^ 2} $
In [1]:
import pandas as pd
from statsmodels.formula.api import ols
In [2]:
df = pd.read_csv("Iris.csv")
df.head(2)
Out[2]:
SepalLengthCm | SepalWidthCm | PetalLengthCm | PetalWidthCm | Species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | Iris-setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | Iris-setosa |
Y : SepalLengthCm X : SepalWidthCm + PetalLengthCm + PetalWidthCm 모델인 경우
In [3]:
formula=\
"SepalLengthCm~SepalWidthCm+PetalLengthCm+PetalWidthCm"
In [4]:
model=ols(formula=formula,data=df).fit()
In [5]:
model.summary()
Out[5]:
Dep. Variable: | SepalLengthCm | R-squared: | 0.859 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.856 |
Method: | Least Squares | F-statistic: | 297.0 |
Date: | Sun, 18 Dec 2022 | Prob (F-statistic): | 6.28e-62 |
Time: | 19:27:57 | Log-Likelihood: | -37.000 |
No. Observations: | 150 | AIC: | 82.00 |
Df Residuals: | 146 | BIC: | 94.04 |
Df Model: | 3 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | 1.8451 | 0.250 | 7.368 | 0.000 | 1.350 | 2.340 |
SepalWidthCm | 0.6549 | 0.067 | 9.823 | 0.000 | 0.523 | 0.787 |
PetalLengthCm | 0.7111 | 0.057 | 12.560 | 0.000 | 0.599 | 0.823 |
PetalWidthCm | -0.5626 | 0.127 | -4.426 | 0.000 | -0.814 | -0.311 |
Omnibus: | 0.265 | Durbin-Watson: | 2.053 |
---|---|---|---|
Prob(Omnibus): | 0.876 | Jarque-Bera (JB): | 0.432 |
Skew: | 0.003 | Prob(JB): | 0.806 |
Kurtosis: | 2.737 | Cond. No. | 54.7 |
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
VIF 구하기¶
1. 계산 식을 이용해서 구하기¶
X에 대해서만 R-squared 값을 구합니다.
In [6]:
vif_cols=["SepalWidthCm","PetalLengthCm","PetalWidthCm"]
In [7]:
for cname in vif_cols:
vif_cols_copy=vif_cols.copy()
vif_cols_copy.remove(cname)
formula = cname + "~" + "+".join(vif_cols_copy)
print(formula)
model=ols(formula=formula,data=df).fit()
print(1/(1-model.rsquared))
SepalWidthCm~PetalLengthCm+PetalWidthCm 1.2638426041908788 PetalLengthCm~SepalWidthCm+PetalWidthCm 15.091611529692765 PetalWidthCm~SepalWidthCm+PetalLengthCm 14.232147823080032
2. variance_inflation_factor 계산 함수 사용¶
In [8]:
from statsmodels.stats.outliers_influence\
import variance_inflation_factor
In [9]:
variance_inflation_factor(df[vif_cols],0)
Out[9]:
5.896727335512338
In [10]:
variance_inflation_factor(df[vif_cols],1)
Out[10]:
61.750178363923474
In [11]:
variance_inflation_factor(df[vif_cols],2)
Out[11]:
42.917554018630476
3. 값이 다른 원인 분석¶
ols summary() 함수의 결과를 보면 ols 내부에서 절편(intercept)을 붙여주도록 되어있습니다.
4. intercept 를 고려하려 다시 계산해보기, 입력에 intercept 값 추가¶
In [12]:
df["intercept"]=1 # 상수값 1 입력
# dmatrices() 함수를 사용하면 자동으로 intercept 1추가됨
In [13]:
df.head(2)
Out[13]:
SepalLengthCm | SepalWidthCm | PetalLengthCm | PetalWidthCm | Species | intercept | |
---|---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | Iris-setosa | 1 |
1 | 4.9 | 3.0 | 1.4 | 0.2 | Iris-setosa | 1 |
In [14]:
vif_cols=\
["SepalWidthCm","PetalLengthCm","PetalWidthCm","intercept"]
In [15]:
variance_inflation_factor(df[vif_cols],0)
Out[15]:
1.2638426041908783
In [16]:
variance_inflation_factor(df[vif_cols],1)
Out[16]:
15.091611529692765
In [17]:
variance_inflation_factor(df[vif_cols],2)
Out[17]:
14.232147823080032