다중선형회귀 : 여러개의 변수(feature)가 target 영향을 주는 경우.

 

선형모델을 만드는 방식은 단순 선형 회귀와 똑같다.  statsmodel이나 sklearn을 쓰면 되는데, 다만 여러개의 변수 중 어떤 변수들을 사용할 지를 결정해줘야 한다. 

 

 

행렬로 나타내 보면 대충 아래와 같다. 

여기서 우리가 구해야하는 것은 베타행렬, 이를 구하려면 x  에 대한 역행렬을 양쪽에 곱해줘야하는데, 

역행렬을 구하는 공식을 보면, 분모 ad-bc가 0 이 되어버리면 값을 구할 수 없다. 

즉, feature 끼리 값이 비슷하면 역행렬이 발산하게 되어 베타 행렬이 의미가 없어진다. 

 

이를 독립변수들 사이의 다중공선성이라고 하고, 다중공선성이 높은 feature들끼리 사용하면

원하는 값을 얻을 수 없다. 

 

다중공선성 : feature끼리의 상관계수가 높으면 같이 feature로 쓸 수 없다. 

따라서, feature 선정 시, feature들 끼리의 다중공선성, 즉 상관계수, 결정계수를 반드시 확인한다. 

 

 

 

 

 

 

 

다중공선성을 확인하기에 앞서서 중요한 개념인 상관계수와 결정계수를 알아보자. 

 

상관 계수 R : -1~1 사이의 수로 변수 사이의 관계를 나타낸다. 주로 feature와 target 사이의 관계를 나타낸다.

1에 가까울 수록 양의 상관도가, -1에 가까울 수록 음의 상관도가 높다. 

아래 두개의 함수 모두 기능은 동일하다. 

 

.corr()   : 일반 함수

np.round(df[["gf", "ga", "points"]].corr(), 2)

np.corrcoef(target, feature)[0,1]   : Numpy 함수

np.corrcoef(point, gf)[0,1]


np.corrcoef 는 [1,  x], [x, 1] 형태의 2x2 행렬로 나온다. 그래서 [0,1] 이나 [1,0] 이 결과 값이다.

 



결정계수 R^2 : 상관계수의 제곱  (0~1)     . . 그냥 상관계수를 제곱하면 된다. 


.corr()**2

 

np.round(df[["gf", "ga", "points"]].corr()**2, 2)


np.corrcoef () [0,1]**2

np.corrcoef(point, gf)[0,1]**2

 

model.rsquared

 

statesmodel로 model을 생성했다면, model.rsquared 로 결정계수를 구할 수 있다. 

 

 

 

 

개념을 알았으니,

다중공선성을 확인하는 방법을 마저 알아보자. 

 

i)  scatter plot 그려서 그림으로 확인. (모델 생성 전)
 - (feature1, target), (feature2, target) .. 간의 plot을 그려 비교.  

 

*scatter(x, y, label="x")

plt.scatter(df["TV"], df["sales"], label="TV")
plt.scatter(df["radio"], df["sales"], label="radio")
plt.scatter(df["newspaper"], df["sales"], label="newspaper")
plt.legend()
plt.show()


스캐터를 보니 radio와 newspaper는 패턴이 거의 같다. 

sales에 대한 radio의 함수,  newspaper의 함수가 거의 똑같이 생겼다고 추측할 수 있다. 

= 다중공선성이 높다. 

따라서, 한개만 feature 로 채택한다. 

 

 


2. heatmap 그려서 확인 : feature들끼리의 결정계수/ 상관계수를 히트맵으로 확인. (모델 생성 전)

 

target을 제외한 나머지 변수들의 계수, 

상관계수의 제곱인 결정계수 

 

sns.heatmap(df.drop(columns=["sales"]).corr(), annot=True)
plt.show()

sns.heatmap(df.corr() ** 2, annot=True)
plt.show()



3. VIF : Variance Inflation Factor. 를 계산해본다. (모델 생성 전 )
분산 팽창 요인. (역행렬 연산 시 1/(ad-bc) 로 연산을 하는데 다중 공선성이 높으면 ad-bc =0 이 되어 분모가 0, 발산하게 된다. ) VIF 지표가 높을 수록 다중공선성이 높다고 판단. 일반적으로 VIF가 10 이상인 경우, 다중공선성으로 판단. (절대적이지는 않음) 

특정 feature를 y값으로 설정하여 모델을 만들었을때 나오는 결정계수(r-squared)로 아래의 수식을 연산한다. 

VIF 구하는 방법 
1) 직접 계산 

feature 끼리 돌아가면서 target으로 설정하고 나머지를 feature로 삼아 모델을 생성했을 때, 
VIF 값을 측정한다. 

 

import statsmodels.api as sm
feature = features_df[["radio", "newspaper"]]
target = features_df["TV"]
model = sm.OLS(target, feature).fit()
1 / (1 - model.rsquared)

 

-> VIF Factor of TV
target으로 삼은 녀석의 VIF 값. 높으면 사용하지 않는게 좋다. 
, radio, newspaper에 대해서도 각각 진행. 

2) 함수로 확인. 

statsmodels에 이미 VIF를 구하는 함수가 있다. 

 

variance_inflation_factor(  feature.values,  feature index  )

ex) ["TV", "Radio","Newspaper"]  

feature index

0 : TV, 

1: Radio

2 : Newspaper

from statsmodels.stats.outliers_influence import variance_inflation_factor

feature = df[ ['', '' ] ]
target = df [ ]
pd.DataFrame({
    "feature": feature.columns,
    "VIF": [variance_inflation_factor(feature.values, idx)
            for idx in range(feature.shape[1])]
})

 

 

 

 

 



4. (모델 생성 후) summary 참조. (05. linear_regression_summary_table)

***summary에서 참고할 만한 수치 : 


Coef : 회귀계수 . 기울기에 해당.  0에 가까울 수록 상관도가 낮다 (target과의). 너무 작은 애는 쓸모없다. 
R-squared : 모델의 결정계수 : 높을수록 좋다. 분산설명력. 
p-value = P> |t| : 우연에 의해 나올 확률 . 보통 0.05 보다 높으면 안좋다고 본다. 5%. 
t = t test : (two sample test) : 회귀계수가 우연인지 확인하는 지표. 0과 가까울 수록 우연일 확률이 높다. 작은게 좋음. 


model.summary()

model.summary2()

feature_1 = sm.add_constant(df[["TV", "radio", "newspaper"]])
model_1 = sm.OLS(df["sales"], feature_1).fit()
print(model_1.summary2())

전체 feature를 넣고 만든 모델, 한개의 메체를 빼고 나머지를 feature로 삼았을 때의 모델들을 모두 생성한다.

 

그리고 각각의 P-Value, MAE 를 확인해본다. 

 

np.round(mean_absolute_error(df["sales"], pred_1), 3)
np.round(mean_absolute_error(df["sales"], pred_2), 3)


.. 모델의 성능이 뭐가 좋은지도 확인해볼 수 있음. 

 

P value 값이 낮으면서 MAE가 높은 모델을 선택한다. 

+ Recent posts