다중선형회귀 : 여러개의 변수(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가 높은 모델을 선택한다.
'파이썬 > 머신러닝' 카테고리의 다른 글
[분류모델] 02. Decision Tree (0) | 2022.05.30 |
---|---|
[분류모델] 01. 나이브 베이즈 (0) | 2022.05.29 |
[회귀분석] 04. 다항회귀분석 (0) | 2022.05.28 |
[회귀분석] 03. 다중선형회귀 예제 (0) | 2022.05.28 |
[회귀분석] 01. 단순 선형 회귀 (0) | 2022.05.27 |