본문 바로가기
국비 교육/머신러닝, 딥러닝

[머신러닝] 회귀분석 - 다중공선성, L1 규제 ,L2규제

by 육츠 2023. 11. 20.
Contents 접기

다중공선성 예시

패키지 로딩

from statsmodels.datasets.longley import load_pandas # 통계관련 패키지
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

statsmodels 은 파이썬에서 통계 모델링을 위한 기능을 제공하는 라이브러리이며,
Longley 데이터셋은 공선성이 매우 높은 것으로 알려진 미국 거시경제 지표가 포함 되어있다.

load_pandas() 의 Dataset 객체 속성
- data: DataFrame 객체로 전체 데이터 반환
- endog : Series 객체로 종속변수 값 반환
- exog: DataFrame 객체로 독립변수 값 반환

변수 설명

독립변수 : GNPDFEL - GNP 디플레이터 / GNP - GNP (국민총생산) / UNEMP - 실업자구 / ARMED - 무장세력 규모 / POP - 인구 / YEAR - 연도

종속변수 : TOTEMP - 총 고용

data = load_pandas()
df = data.data # 결과값을 데이터프레임 객체로 받아옴
print(df.shape)
display(df.head())

 

다중공선성 multicollinearity

독립변수의 일부가 다른 독립 변수의 조합으로 표현될 수 있는 경우.

독립변수들이 서로 독립이 아니라 상호 상관관계가 강한 경우에 발생한다.
여부 판단 기준 : 독립변수 상관계수 r >= 0.9 or 각 변수의 분산팽창지수(VIF) >= 10

해결 방법:
    - 다중공선성을 가지는 변수 중 하나를 제거(제거시 R^2가 유지되는 변수를 제거)
    - VIF값이 가장 높은 독립변수를 하나씩 제거하여 모든 VIF 값이 10이하가 되도록 한다.
    - PCA 이용한 변수 축소(독립변수가 많을수록 과적합 확률이 오르기 때문이다.)
    - 정규화(가중치가 계속 커지는 걸 분리시키는)

독립변수와 종속변수 분리

data_x = data.exog
data_y = data.endog

 

독립변수간 상관관계 확인
회귀분석에서 독립변수들 사이에 선형관계가 존재하면 회귀계수의 정확한 추정이 어렵다.
우상향, 우하향 하는 모습 = 선형관계가 있다. (회귀계수 = 가중치)

sns.pairplot(data_x)
plt.show() # 상관관계 도표 확인 가능
data_x.corr() # 상관관계 계산해주는 함수

 

sns.heatmap : 상관관계의 수를 시각적으로 보여준다.

cmap = sns.light_palette('darkgray', as_cmap=True) # 히트맵의 디자인 요소
sns.heatmap(data_x.corr(), annot= True, cmap= cmap) # annot= True : 컬럼 이름 사용 
plt.show()

 

다중공선성VIF(분산팽창지수) 값 확인

의존적인 독립변수를 선택하는 방법으로 VIF(Variance Inflation Factor) 를 사용할 수 있다.

from statsmodels.stats.outliers_influence import variance_inflation_factor

vif = pd.DataFrame()
vif['VIF'] = [ variance_inflation_factor(data_x.values, i) for i in range(data_x.shape[1])] # 전체 레코드(컬럼) 개수 만큼 돈다.
# 모든 컬럼에 대해서 VIF 값 계산하여 리스트로 반환
vif['Features'] = data_x.columns # 데이터 프레임에 컬럼값

vif
# 10이상이면 다중공선성에 문제가 생긴다.

독립변수 스케일링 후 VIF값 확인
: 각 독립 변수들 간의 변동폭이 큰 경우에는 표준화를 진행하면 훨씬 더 좋은 결과를 도출할 수 있다.

StandardScaler() : 표준화

from sklearn.preprocessing import StandardScaler

data_x_scaled = StandardScaler().fit_transform(data_x) # 표준화된 데이터가 담긴다.
vif = pd.DataFrame()
vif['VIF'] = [ variance_inflation_factor(data_x_scaled, i) for i in range(data_x.shape[1])] # 전체 레코드(컬럼) 개수 만큼 돈다.
# data_x_scaled : 넘파이 배열의 형태로 넘어온다.
vif['Features'] = data_x.columns # 데이터 프레임에 컬럼값

vif

 

변수제거

선형회귀분석(다중공선성 제거 전 모델 학습)

필요한 패키지 로드

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

 

학습데이터와 평가데이터로 분할한다.(데이터의 양이 많지 않아, test 사이즈를 증가시켰다.)

x_train, x_test, y_train, y_test = train_test_split(data_x_scaled, data_y,
                                                   test_size= 0.4,random_state = 10) # 6:4 의 비율

 

모델 생성 후 학습(학습: fit())

model = LinearRegression()
model.fit(x_train,y_train)

6 개의 독립변수 모두 사용하여 결정계수 계산한다.

print(f'결정계수: {model.score(x_test,y_test):.3f}')
결정계수: 0.928

 

선형회귀분석(다중공선성 제거 후 모델 학습)

제거 대상 독립 변수 확인 (10 이상이라고 반드시 제거해야하는 것은 아니다.)

data_x_new = data_x[['GNPDEFL','UNEMP','ARMED']] # 상관관계 수치 중 상대적으로 낮은 것들을 임의로 뽑음
data_x_new.head()

 

스케일링(표준화), 데이터 분할

data_x_new_scaled = StandardScaler().fit_transform(data_x_new)

# 데이터 분할
x_train, x_test, y_train, y_test = train_test_split(data_x_new_scaled, data_y,
                                                   test_size= 0.4,random_state = 10) # 6:4 의 비율

 

모델 생성 후 학습, 결정계수 계산

model = LinearRegression()
model.fit(x_train,y_train)
print(f'결정계수: {model.score(x_test,y_test):.3f}') # 3개의 독립변수
# 다중공선성이 높은 변수를 지운다고해서 다 결정계수가 높아지는 것은 아니다.
결정계수: 0.954

 

과대적합 방지(데이터 규제)

규제: 데이터에 과적합을 방지하기 위한 방법 중 하나로 모델이 학습하는데 사용되는 가중치에 규제값을 주어 과적합이 되는 것을 막고, 모델의 일반화 성능을 증가시킨다 (모델의 일반화 = 약간의 오차를 허용하면서도 전체적인 데이터의 특성을 잘 반영하는 모델을 만드는 것을 말함)

결국 가중치의 모든 원소를 0과 가깝게 만드는 것이다.(y에 주는 영향을 최소화하여 편중을 막는 것)

규제 방법

벡터의 노름(norm) : 벡터를 기하학적으로 시각화하려 방향과 거리를 가진 화살표로 그렸을때, 벡터의 이동거리를 말한다.

- L1 노름은 벡터 성분의 절댓값을 모두 더하면된다. (맨하튼거리)
- L2 노름은 유클리드 거리로 구하면 된다.(피타고라스의 대각선 거리 구하는 공식 √(a^2+b^2)이다.)

1. L1 규제

손실함수에 가중치의 L1 노름과 상수 λ를 곱한 것이다. (  λ  : 규제의 양조절)
L1 규제가 적용된 손실함수의 미분식은 아래와 같다.

- 절대값 w를 미분하면 양과 음의 부호만 남으므로 sin(w)로 표현한다.

 - λ 를 이용해 규제의 양을 조절하는데 고정된 상수값(lambda)이 모든항에 대해 일괄적으로 빠지면서 자잘한 가중치들은 0으로 가버리고 중요한 가중치만 남아서  feature 의 수가 줄어드므로 과적합을 막게 된다
(VIF 변수제거와 유사하다.)

- λ 값을 낮추면 모델의 복잡도는 증가하여 학습모델에 대한 성능은 좋아질 수 있으나 규제의 효과가 사라져 과적합이 발생할 수 있다.

- 완전히 제외된다는 특성이 생긴다.
- L1 규제가 적용된 선형회귀 모델을 라쏘 (Lasso) 라고 한다.

w>0, 1
w = 0, 0
w <0, -1

 

2. L2  규제

손실함수에 가중치의 L2 노름과 상수  λ를 곱한값을 더한 것이다.
L2 규제가 적용된 손실함수의 미분식은 아래와 같다.

- 규제항들의 가중치는 모두 w로 미분되어서 결국 lambda*w 라는 일차항이 남게 된다.
각 가중치에 대해 비례하게 값이 빠지게 되어 다중선형 회귀모델 식의 가중치들은 완전히 0이 되지 않는다.

- L2 규제가 적용된 선형회귀 모델을 릿지 (Ridge) 라고 한다.

 

L1 규제 + L2 규제 = 엘라스틱 Elastic