본문 바로가기
데이터 분석/데이터 분석

[회귀 분석] 7. 다중공선성 확인하기 - 분산 팽창 인자 with Python

by 부자 꽁냥이 2020. 10. 5.

안녕하세요~ 꽁냥이에요!

 

이번 포스팅에서는 다중공선성이 무엇인지 그리고 어떻게 확인할 수 있는지 알아보려고 합니다.

 

회귀 모형을 적합할 때에는 여러 가지 문제를 고려해야 합니다. 오차의 분포가 정규분포를 따르는지, 오차가 관측치에 관계없이 항상 일정한지와 같은 오차 항의 가정과 관련된 문제가 있고요. 반응 변수와 중요한 연관관계를 갖는 변수가 모형에 다 포함되어 있는가에 대한 변수 선택 문제가 있지요. 또한 변수 간의 다중공선성이 회귀 분석에서 중요한 문제입니다.

 

여기서 다루는 내용은 다음과 같습니다.

 

1. 다중공선성이란?

2. 다중공선성이 왜 문제가 되는 걸까?

3. 다중공선성 확인 방법

4. 다중공선성이 존재할 경우 대책


   1. 다중공선성이란?

다중 회귀 모형(Multiple regression)에서 한 변수가 다른 변수의 선형 결합에 의하여 높은 정확도를 가지고 예측이 가능할 때 다중공선성이 존재한다고 합니다.

 

다음과 같은 다중 회귀 모형이 있다고 해볼게요.

$$y = \beta_0 + \beta_1x_1+\beta_2x_2+\beta_3x_3\tag{1}$$

그리고 $x_1$이 아래와 같이 $x_2$와 $x_3$의 선형 결합으로 표현된다고 가정할게요.

$$x_1 = x_2 + x_3$$

이 경우에는 $x_2$와 $x_3$을 알면 $x_1$을 완벽하게 알아낼 수 있는 경우이지요. 이때  다중 회귀 모형 (1)은 (완벽한) 다중공선성이 존재하게 되는 것입니다.


   2. 다중공선성이 왜 문제가 되는 걸까?

다중공선성이 존재하면 다음과 같은 문제가 발생합니다.

 

1) 다중공선성이 생기게 되면 회귀계수 추정량의 분산이 커지게 됩니다. 회귀계수 추정량의 분산이 커지면 우리가 추정한 회귀계수의 정확성이 떨어지게 되고 이에 회귀계수 추정값을 신뢰할 수 없게 되지요. 이유를 알아보기 위해 데이터가 $(\tilde{x}_i, y_i), i=1,\cdots,n, \tilde{x}_i=(x_{1i}, x_{2i}, x_{3i})^t$ 있고 다음과 같은 다중 회귀 모형을 적합했다고 해보겠습니다.

$$y_i^* = \hat{\beta}_1x_{1i}^* + \hat{\beta}_2x_{2i}^* + \hat{\beta}_3x_{3i}^*, \:\: i=1, 2, \cdots , n \tag{2}$$

여기서 $z_{i}^*=\frac{1}{\sqrt{n-1}}\left(\frac{z_i-\bar{z}}{s_z}\right), s_z = \frac{1}{\sqrt{n-1}}\sum_{i=1}^{n}(z_i-\bar{z})^2$ 입니다. 즉, (2)는 표준화된 변수를 이용하여 적합된 다중 회귀 모형입니다.

 

이때, 회귀 계수 $\hat{\beta}_k (k=1, 2, 3)$의 분산은 다음과 같습니다.

$$var(\hat{\beta}_k) = \frac{var(y^*)}{1-R_{k}^2}$$

여기서 $R_{k}^2$은 변수 $x_k^*$를 반응 변수로 하고 나머지 변수를 설명변수로 하는 회귀 모형의 결정계수입니다. 따라서 $x_1^*$이 $x_2^*$와 $x_3^*$의 선형 결합으로 예측이 가능하다면 $R_{1}^2$의 값이 1에 가까워질 테고 이에 따라 $var(\hat{\beta}_1)$ 값이 커지게 됩니다.

 

2) 또한 하나 변수가 다른 변수의 선형 결합으로 완벽하게 표현된다면 이론적으로 유니크한 회귀계수를 구할 수 없습니다. 만약 모형 (2)에서 최소제곱법을 이용하여 회귀계수 $\beta = (\beta_1, \beta_2, \beta_3)^t$의 추정량은 다음과 같이 정규 방정식을 만족해야합니다.

$$ X^tX\beta = X^ty^*$$

여기서 $X = (x_{ij}^*), (i=1, \cdots, n, j=1,2,3)$ 이고 $y^*=(y_1^*, \cdots, y_n^*)^t$입니다. 이때 한 변수가 다른 변수의 선형 결합으로 완벽하게 표현된다면 모델 매트릭스 $X$는 full rank가 아니게 되고 따라서 $X^tX$의 역행렬이 존재하지 않으므로 유니크한 회귀계수의 추정치를 구할 수 없게 됩니다(위 정규방정식을 만족하는 $\beta$는 무수히 많게 됩니다). 


   3. 다중공선성 확인 방법

다중공선성은 분산팽창인자(Variance Inflation Factor)의 값을 보고 확인할 수 있습니다. 설명변수 $x_k$의  분산팽창인자 $VIF_k$는 다음과 같이 정의합니다.

$$VIF_k = (1-R_k^2)^{-1}$$

여기서 $R_k^2$는 앞에서 정의한 것과 같습니다. 앞에서 보셨다시피 $VIF_k$값이 크다면 다중공선성을 의심해볼 수 있습니다. 경험적으로 $VIF_k$ 값이 10보다 크다면 다중공선성이 존재한다고 판단하게 됩니다.

 

이번에는 실제 데이터를 통하여 분산팽창인자를 확인해보는 과정을 파이썬으로 구현해보겠습니다.

 

먼저 데이터를 다운받아주세요.

 

body_fat_data.csv
0.00MB
body_fat_data_description.txt
0.00MB

 

다음으로 필요한 모듈을 임포트하고 데이터를 불러와주세요.

 

import pandas as pd
import numpy as np

from statsmodels.formula.api import ols
from statsmodels.stats.outliers_influence import variance_inflation_factor

df = pd.read_csv('./body_fat_data.csv') ## 데이터 준비하기

 

 

이제 각 변수별 분산팽창인자를 확인해보겠습니다.

 

def standardize_var(x):
    mean = np.mean(x)
    std = np.sqrt(np.sum(np.square(x-mean))/(len(x)-1))
    return ((x-mean)/std)/np.sqrt(len(x)-1)

sdf = df.apply(standardize_var) ## 데이터 표준화
sdf_X = sdf[['Tricep_ST', 'Thigh_C', 'Midarm_C']]
corr = np.array(sdf_X.corr()) ## 상관계수 행렬
corr_inv = np.linalg.inv(corr) ## 상관계수행렬의 역행렬

## standardized된 변수들로 이루어진 선형 회귀모형은 절편항이 없다. 
## 따라서 절편항은 제외한다. 포함시켜도 절편항이 0에 가까운 값으로 추정된다.
fit = ols('Body_fat~Tricep_ST+Thigh_C+Midarm_C-1',data=sdf).fit()

variables = [] ## 변수 이름
reg_coef = [] ## 해당 변수의 회귀 계수
vif = [] ## 해당 변수의 분산팽창인자
for i in range(len(sdf_X.columns)):
    col_name = sdf_X.columns[i]
    variables.append(col_name)
    reg_coef.append(fit.params[col_name])
    vif.append(corr_inv[i][i])
    
df_res = pd.DataFrame()
df_res['Variable'] = variables
df_res['Estimate'] = reg_coef
df_res['VIF'] = vif

 

line 22

분산팽창인자는 앞서 소개한 결정계수 보다는 설명변수 상관행렬의 역행렬에서 대각 원소를 통해 구하는 것이 편합니다(이렇게할 수 있는 이유는 설명변수가 표준화되어 있기 때문입니다). 

 

위 코드를 실행하고 결과를 확인해보겠습니다.

 

 

분산팽창인자가 굉장히 크네요. 최소 분산팽창인자가 100이 넘네요.

 

분산팽창인자를 직접 구현할 수도 있지만 variance_inflation_factor 통하여 쉽게 구할 수 있습니다.

 

## 모형 정의(실제적합은 일어나지 않는다.)
model = ols('Body_fat~Tricep_ST+Thigh_C+Midarm_C-1',data=sdf)

variables = []
reg_coef = []
vif = []
for i in range(len(model.exog_names)):
    col_name = model.exog_names[i]
    variables.append(col_name)
    reg_coef.append(model.fit().params[col_name])
    vif.append(variance_inflation_factor(model.exog, i))
    
df_res = pd.DataFrame()
df_res['Variable'] = variables
df_res['Estimate'] = reg_coef
df_res['VIF'] = vif

 

결과는 앞에서 본 것과 동일합니다.

반응형

   4. 다중공선성이 존재할 경우 대책

다중공선성이 존재하는 경우 이에 대한 대책은 다음과 같습니다.

 

1) 다중공선성 관계에 있는 변수를 가지고 새로운 변수로 만들어볼 수 있습니다. 예를 들면 수축기 혈압과 이완기 혈압은 양의 상관관계가 있는데요. 수축기 혈압과 이완기 혈압의 평균을 새로운 변수로 한다면 혈압이라는 요인은 유지하면서 다중공선성 문제를 해결할 수 있지요.

 

2) 능형 회귀(Ridge regression) 모형을 생각해볼 수 있습니다. 앞에서 다중공선성이 존재하면 회귀계수의 분산이 커진다고 했는데요. 능형 회귀 모형은 회귀계수의 분산을 줄여주는 방법입니다. 이에 대한 내용은 여기를 참고하세요.


- 참고 자료 -

Kutner, Nachtsheim, Neter - Applied Linear Regression Models 4th Edition


댓글


맨 위로