릿지 회귀(Ridge Regression)
릿지 회귀가 뭐지?
Ridge regression is a method of estimating the coefficients of multiple-regression models in scenarios where independent variables are highly correlated.
- Wikipedia(Ridge regression)
기존의 다중 선형 회귀선을 팽팽한 고무줄이라고 하면, 릿지 회귀는 이 고무줄을 느슨하게 만들어준 것이다.
다중 선형 회귀 모델은 특성이 많아질수록 훈련 데이터에 과적합되기 쉽다. 이는 마치 "나는 훈련에서 무조건 만점을 받겠어!"라고 하여 열심히 훈련을 해서 만점을 받았는데, 정작 실전에서는 뭐 하나 제대로 못하는 병사같다.
이에 반해 릿지 회귀는 훈련은 좀 덜 열심히 했지만, 실전에서는 꽤 쓸만한 병사라고 할 수 있겠다.
릿지 회귀는 어떻게 생겼지?
과적합된 다중 선형 회귀 모델은 단 하나의 특이값에도 회귀선의 기울기가 크게 변할 수 있다. 릿지 회귀는 어떤 값을 통해 이 기울기가 덜 민감하게 반응하게끔 만드는데, 이 값을 람다(lambda, $\lambda$)라고 한다.
릿지 회귀의 식은 아래와 같다.
$$\beta_{ridge} : argmin[\sum_{i=1}^n(y_i - \beta_0 - \beta_1x_{i1}-\dotsc-\beta_px_{ip})^2 + \lambda\sum_{j=1}^p\beta_j^2]$$
(n: 샘플 수, p: 특성 수, λ: 튜닝 파라미터(패널티))
(참고 - 람다 : lambda, alpha, regularization parameter, penalty term 모두 같은 뜻)
식의 앞 부분은 다중 선형 회귀에서의 최소제곱법(OLS, Ordinary Least Square)과 동일하다.
뒤쪽의 람다가 붙어 있는 부분이 기울기를 제어하는 패널티 부분이다.
뒷부분을 자세히 보면 회귀계수 제곱의 합으로 표현되어 있는데, 이는 L2 Loss$^*$$^1$와 같다. 이런 이유로 릿지 회귀를 L2 정규화(L2 Regularization)라고도 한다.
만약 람다가 0이면 위 식은 다중 선형 회귀와 동일하다.
반대로 람다가 커지면 커질수록 다중 회귀선의 기울기를 떨어뜨려 0으로 수렴하게 만든다. 이는 덜 중요한 특성의 개수를 줄이는 효과로도 볼 수 있다.
적합한 람다의 값을 구하는 방법은 아래에서 scikit-learn을 통해 예시를 들겠다.
scikit-learn을 이용하여 릿지 회귀 수행하기
scikit-learn을 통해 릿지 회귀를 사용하는 방법으로 Ridge와 RidgeCV가 있다.
둘 모두 같은 릿지 회귀이나, RidgeCV는 여러 alpha값(=람다)을 모델 학습 시에 한꺼번에 받아서 자기 스스로 각각의 alpha값에 대한 성능을 비교 후 가장 좋은 alpha를 선택한다. (CV : Cross Validation$^*$$^2$)
아래 예시에서는 먼저 다중 선형 회귀와 릿지 회귀의 차이를 간단히 살펴본 후, 보다 구체적인 Ridge 그리고 RidgeCV의 사용을 다루겠다.
- 다중 선형 회귀와 릿지 회귀 간단한 비교
(사용 데이터 : Anscombe's quartet)
# 데이터 불러오기
import seaborn as sns
ans = sns.load_dataset('anscombe').query('dataset=="III"')
baseline = ans.y.mean() # 기준 모델
sns.lineplot(x='x', y=baseline, data=ans, color='red'); # 기준 모델 시각화
sns.scatterplot(x='x', y='y', data=ans);
# 다중 선형 회귀(OLS)
%matplotlib inline
ax = ans.plot.scatter('x', 'y')
# OLS
ols = LinearRegression()
ols.fit(ans[['x']], ans['y'])
# 회귀계수와 intercept 확인
m = ols.coef_[0].round(2)
b = ols.intercept_.round(2)
title = f'Linear Regression \n y = {m}x + {b}'
# 훈련 데이터로 예측
ans['y_pred'] = ols.predict(ans[['x']])
ans.plot('x', 'y_pred', ax=ax, title=title);
# 릿지 회귀
import matplotlib.pyplot as plt
from sklearn.linear_model import Ridge
def ridge_anscombe(alpha):
"""
alpha : lambda, penalty term
"""
ans = sns.load_dataset('anscombe').query('dataset=="III"')
ax = ans.plot.scatter('x', 'y')
ridge = Ridge(alpha=alpha, normalize=True)
ridge.fit(ans[['x']], ans['y'])
# 회귀계수와 intercept 가져오기
m = ridge.coef_[0].round(2)
b = ridge.intercept_.round(2)
title = f'Ridge Regression, alpha={alpha} \n y = {m}x + {b}'
# 예측
ans['y_pred'] = ridge.predict(ans[['x']])
ans.plot('x', 'y_pred', ax=ax, title=title)
plt.show()
# 여러 알파값을 넣어서 기울기의 변화 확인하기
alphas = np.arange(0, 2, 0.4)
for alpha in alphas:
ridge_anscombe(alpha=alpha)
∴ 그래프를 보면 alpha = 0인 경우에는 OLS와 같은 그래프 형태로 같은 모델임을 확인할 수 있고. alpha 값이 커질수록 직선의 기울기가 0에 가까워 지면서 평균 기준모델(baseline)과 비슷해진다.
- Ridge & RidgeCV 구체적인 활용 방법
1) 데이터 불러오기 및 전처리
(사용할 데이터 : Melbourne Housing Market)
import pandas as pd
from sklearn.model_selection import train_test_split
# 데이터 불러오기
df = pd.read_csv('https://ds-lecture-data.s3.ap-northeast-2.amazonaws.com/melbourne_house_prices/MELBOURNE_HOUSE_PRICES_LESS.csv')
# 범주형 특성 중 값의 종류가 너무 많은 특성은 제외
df.drop(columns=['Suburb','Address','SellerG','Date'], inplace=True)
# 결측치인 타겟 값 제거
df.dropna(subset=['Price'], inplace=True)
# 중복된 행 제거
df.drop_duplicates(inplace=True)
from category_encoders import OneHotEncoder
# 사용할 특성들과 타겟을 별도로 분리
target = 'Price'
data = df.drop(target, axis=1)
target = df[target]
# 훈련 / 테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(data, target, train_size=0.8, test_size=0.2, random_state=2)
# 범주형 특성을 수치형으로 변환하는 인코딩 수행
# 자세한 내용은 아래 참고 자료 링크(One-hot Encoder)에 있습니다
encoder = OneHotEncoder(use_cat_names = True)
X_train = encoder.fit_transform(X_train)
X_test = encoder.transform(X_test)
2) Ridge
from sklearn.linear_model import Ridge
alphas = [0, 0.001, 0.01, 0.1, 1]
# Ridge의 경우 alpha값을 이와 같이 따로 따로 넣어주어야 함
for alpha in alphas:
ridge = Ridge(alpha=alpha, normalize=True)
ridge.fit(X_train, y_train)
y_pred = ridge.predict(X_test)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f'Test MAE: ${mae:,.0f}')
print(f'R2 Score: {r2:,.4f}\n')
Test MAE: $255,214
R2 Score: 0.5877
Test MAE: $255,264
R2 Score: 0.5878
Test MAE: $254,701
R2 Score: 0.5874
Test MAE: $252,997
R2 Score: 0.5794
Test MAE: $279,498
R2 Score: 0.4742
3) RidgeCV
from sklearn.linear_model import RidgeCV
from sklearn.metrics import mean_absolute_error, r2_score
alphas = [0, 0.001, 0.01, 0.1, 1]
# RidgeCV는 alpha로 넣고자 하는 값들을 리스트로 전달하면 내부적으로 최적의 alpha값을 찾아냄
ridgecv = RidgeCV(alphas=alphas, normalize=True, cv=5)
# cv : cross-validation -> 데이터를 k등분한 후 각각에 대하여 검증 진행
# 검증 결과 가장 점수가 높은 모델을 채택
ridgecv.fit(X_train, y_train)
y_pred = ridgecv.predict(X_test)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f'Test MAE: ${mae:,.0f}')
print(f'R2 Score: {r2:,.4f}\n')
print(f'alpha: {ridgecv.alpha_}') # 최종 결정된 alpha값
print(f'cv best score: {ridgecv.best_score_}') # 최종 alpha에서의 점수(R^2 of self.predict(X) wrt. y.)
Test MAE: $255,264
R2 Score: 0.5878
alpha: 0.001
cv best score: 0.5705823371670962
*1 L2 Loss란?
L2 Loss는 L2 Norm을 기준으로 만들어진 손실 함수이다.
다만 L2 Norm이 각 원소 제곱의 합에 루트를 씌워준 것이라면 L2 Loss는 루트를 씌우지 않는다는 차이가 있다.
$$L2\ Norm = \sqrt{\sum_{i=1}^{n} x_i^2}$$
$$L2\ Loss = \sum_{i=1}^{n} (y - \hat{y})^2$$
*2 CV : Cross Validation(교차 검증)?
교차 검증은 주어진 데이터를 동일한 크기로 (고등어 자르듯이) 여러 등분한 후, 각각에 대하여 검증을 진행하는 것이다.
이는 모델이 한 가지 경우에만 잘 맞는, 즉 과적합을 줄이고자 행하는 작업이다.
<참고 자료>
- Regularization Part 1: Ridge (L2) Regression - StatQuest
- Modern regression 1: Ridge regression - Ryan Tibshirani
- Ridge regression(릿지 회귀)와 Lasso regression(라쏘 회귀) 쉽게 이해하기 - 우주먼지의 하루
- 선형회귀(linear regression), 라쏘(LASSO), 리지(Ridge) - 오뚝이개발자
- Ridge regression(능형 회귀) 간단한 설명과 장점 - 모던매뉴얼
- Regularization(정규화): Ridge regression/LASSO - 휴블로그
- Ridge and Lasso Regression: L1 and L2 Regularization - Towards Data Science
- L1,L2 Regularization - JINSOL KIM
- L1, L2 Norm, Loss, Regularization? - 생각정리
- 딥러닝 용어 정리, L1 Regularization, L2 Regularization 의 이해, 용도와 차이 설명 - All about
- 교차 검증(cross validation) - 튜토리얼로 익히는 머신러닝/딥러닝
'Machine Learning > Linear Models' 카테고리의 다른 글
[ML] 회귀 모델 평가 지표(Evaluation Metrics for Regression Models) (0) | 2021.10.22 |
---|---|
[ML] 다중 선형 회귀 모델(Multiple Linear Regression Model) (0) | 2021.10.21 |
[ML] 단순 선형 회귀 모델(Simple Linear Regression Model) (0) | 2021.10.18 |