- 릿지 회귀(Ridge Regression)
- 릿지 회귀는 선형 회귀를 개선
- 릿지 회귀는 선형 회귀와 비슷하지만, 가중치의 절대값을 최대한 작게 만든다는 것이 다름
- 각 특성이 출력값에 주는 영향을 최소한으로 하도록 규제
- 규제를 사용하면 다중공선성(multicollinearity) 문제를 방지하여 모델의 과대적합 방지
- 다중공선성 문제는 두 특성이 일치에 가까울 정도로 관련성(상관관계)가 높을 때 발생
- 릿지 회귀는 다음과 같은 함수를 최소화하는 파라미터 \(w\)를 찾음
$$ RidgeMSE=\frac{1}{N}\sum_{i=1}^{N}(y_{i}-\hat{y_{i}})^{2}+\alpha\sum_{i=1}^{p}w_{i}^2 $$
- \(\alpha\): 사용자가 지정하는 하이퍼 파라미터
- \(\alpha\)가 크면 규제 효과가 커지고, \(\alpha\)가 작으면 규제 효과가 작아짐(\(\alpha\)가 작을수록 일반 선형 회귀와 동일한 형태)
# 당뇨병 환자 데이터에 릿지 회귀 적용
from sklearn.linear_model import Ridge
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
# return_X_y는 특성 변수와 타겟 변수를 미리 X와 y로 구분하여 불러옴
X, y = load_diabetes(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y)
// alpha값을 하이퍼 파라미터로 지정하여 Ridge모델에 데이터 피팅
model = Ridge(alpha = 0.1)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(alpah = 0.1)
학습 데이터 점수: 0.5036670060593883
평가 데이터 점수: 0.5151286628940492
# 출력 결과(alpah = 0.2)
학습 데이터 점수: 0.49043581005514436
평가 데이터 점수: 0.5303117309693495
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.5136038374290528
평가 데이터 점수: 0.5063114437093292
# 시각화
predicted = model.predict(X_test)
expected = y_test
plot_diabetes(expected, predicted)
- 릿지 회귀는 가중치에 제약을 두어 선형 회귀 모델보다 훈련 데이터 점수가 낮을 수 있음
- 일반화 성능은 릿지 회귀가 더 높아 평가 데이터 점수는 릿지 회귀가 더 좋음
- 일반화 성능에 영향을 주는 하이퍼 파라미터인 \(\alpha\)값을 조정해 보면서 릿지 회귀의 성능이 어떻게 변하는지 확인 필요
# 캘리포니아 주택 가격 데이터에 릿지 회귀 적용
from sklearn.datasets import fetch_california_housing
california = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(california.data, california.target, test_size = 0.2)
model = Ridge(alpha = 0.1)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(alpha = 0.1)
학습 데이터 점수: 0.604254843729662
평가 데이터 점수: 0.613608636245419
# 출력 결과(alpha = 0.2)
학습 데이터 점수: 0.6019439765084587
평가 데이터 점수: 0.6225652128169401
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.6067992442029464
평가 데이터 점수: 0.6022552622453919
# 시각화
predicted = model.predict(X_test)
expected = y_test
plot_california(expected, predicted)
- 라쏘 회귀(Lasso Regression)
- 선형 회귀에 규제를 적용한 또 다른 모델
- 라쏘 회귀는 릿지 회귀와 비슷하게 가중치를 0에 가깝게 만들지만, 조금 다른 방식 사용
- 라쏘 회귀에서는 다음과 같은 함수를 최소화하는 파라미터 \(w\)를 찾음
$$ LassoMSE=\frac{1}{N}\sum_{i=1}^{N}(y_{i}-\hat{y_{i}})^{2}+\alpha\sum_{i=1}^{p}\left|w_{i}\right| $$
- 라쏘 회귀도 하이퍼 파라미터 \(\alpha\)값을 통해 규제의 강도 조절
# 당뇨병 환자 데이터에 라쏘 회귀 적용
from sklearn.linear_model import Lasso
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
# return_X_y는 특성 변수와 타겟 변수를 미리 X와 y로 구분하여 불러옴
X, y = load_diabetes(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y)
model = Lasso(alpha = 0.1)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(alpha = 0.1)
학습 데이터 점수: 0.46683101421965556
평가 데이터 점수: 0.5875532568592793
# 출력 결과(alpha = 0.2)
학습 데이터 점수: 0.4923536651989784
평가 데이터 점수: 0.46314670980636674
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.5136038374290528
평가 데이터 점수: 0.5063114437093292
# 캘리포니아 주택 가격 데이터에 라쏘 회귀 적용
from sklearn.datasets import fetch_california_housing
california = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(california.data, california.target, test_size = 0.2)
model = Lasso(alpha = 0.2)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(alpha = 0.1)
학습 데이터 점수: 0.5433203729425291
평가 데이터 점수: 0.5490112288455995
# 출력 결과(alpha = 0.2)
학습 데이터 점수: 0.5059361673257636
평가 데이터 점수: 0.5011330883335348
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.6067992442029464
평가 데이터 점수: 0.6022552622453919
- 신축망(Elastic Net)
- 신축망은 릿지 회귀와 라쏘 회귀, 두 모델의 규제 모두 사용하는 선형 모델
- 두 모델의 장점을 모두 가져 좋은 성능
- 데이터 특성이 많거나 서로 상관관계가 높은 특성 존재 시, 위의 두 모델보다 좋은 성능
- 신축망은 다음 함수를 최소화하는 파라미터 \(w\)를 찾음
$$ ElasticMSE=\frac{1}{N}\sum_{i=1}^{N}(y_{i}-\hat{y_{i}})+\alpha\rho\sum_{i=1}^{p}\left|w_{i}\right|+\alpha(1-\rho)\sum_{i=1}^{p}w_{i}^{2} $$
- \(\alpha\): 규제의 강도를 조절하는 하이퍼 파라미터
- \(\rho\): 라쏘 규제와 릿지 규제 사이의 가중치를 조절하는 하이퍼 파라미터
# 당뇨병 환자 데이터에 신축망 적용
from sklearn.linear_model import ElasticNet
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
# return_X_y는 특성 변수와 타겟 변수를 미리 X와 y로 구분하여 불러옴
X, y = load_diabetes(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y)
model = ElasticNet(alpha = 0.01, l1_ratio = 0.5)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(alpha = 0.01, l1_ratio = 0.5)
학습 데이터 점수: 0.39452567238560965
평가 데이터 점수: 0.34426906645229316
# 모델을 Ridge로 사용하였을 때 점수
학습 데이터 점수: 0.5036670060593883
평가 데이터 점수: 0.5151286628940492
# 모델을 Lasso로 사용하였을 때 점수
학습 데이터 점수: 0.46683101421965556
평가 데이터 점수: 0.5875532568592793
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.5136038374290528
평가 데이터 점수: 0.5063114437093292
# 캘리포니아 주택 가격 데이터에 신축망 적용
from sklearn.datasets import fetch_california_housing
california = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(california.data, california.target, test_size = 0.2)
model = ElasticNet(alpha = 0.2, rho = 0.5)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(alpha = 0.01, l1_ratio = 0.5)
학습 데이터 점수: 0.6066539688645749
평가 데이터 점수: 0.5937533298305722
# 모델을 Ridge로 사용하였을 때 점수
학습 데이터 점수: 0.604254843729662
평가 데이터 점수: 0.613608636245419
# 모델을 Lasso로 사용하였을 때 점수
학습 데이터 점수: 0.5433203729425291
평가 데이터 점수: 0.5490112288455995
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.6067992442029464
평가 데이터 점수: 0.6022552622453919
- 직교 정합 추구(Orthogonal Matchin Pursuit)
- 직교 정합 추구 방법은 모델에 존재하는 가중치 벡터에 특별한 제약을 거는 방법
- 직교 정합 추구 방법은 다음을 만족하는 파라미터 \(w\)를 찾는 것이 목표
$$ \underset{w}{arg\ min}\ \left|\left|y-\hat{y}\right|\right|_{2}^2\ subject\ to\ \left|\left|w\right|\right|_{0}\leq k $$
- \(\left|\left|w\right|\right|\): 가중치 벡터 \(w\)에서 0이 아닌 값의 개수
- 직교 정합 추구 방법은 가중치 벡터 \(w\)에서 0이 아닌 값이 \(k\)개 이하가 되도록 훈련됨
- 이러한 방법은 모델이 필요 없는 데이터 특성을 훈련 과정에서 자동으로 제거하도록 만들 수 있음
# 당뇨병 환자 데이터에 직교 정합 추구 적용
from sklearn.linear_model import OrthogonalMatchingPursuit
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
# return_X_y는 특성 변수와 타겟 변수를 미리 X와 y로 구분하여 불러옴
X, y = load_diabetes(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y)
model = OrthogonalMatchingPursuit(n_nonzero_coefs = 7) # 0이 아닌 특성을 7개로 지정
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(n_nonzero_coefs = 7)
학습 데이터 점수: 0.49747193558480873
평가 데이터 점수: 0.5368821270302075
# 모델을 신축망으로 사용하였을 때 점수
학습 데이터 점수: 0.39452567238560965
평가 데이터 점수: 0.34426906645229316
# 모델을 Ridge로 사용하였을 때 점수
학습 데이터 점수: 0.5036670060593883
평가 데이터 점수: 0.5151286628940492
# 모델을 Lasso로 사용하였을 때 점수
학습 데이터 점수: 0.46683101421965556
평가 데이터 점수: 0.5875532568592793
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.5136038374290528
평가 데이터 점수: 0.5063114437093292
- 직교 정합 추구 방법은 위에서 설명한 제약 조건 대신 다음 조건을 만족하도록 변경 가능
$$ \underset{w}{arg\ min}\ \left|\left|w\right|\right|_{0}\ subject\ to\ \left|\left|y-\hat{y}\right|\right|_{2}^2\leq tol $$
- \(\left|\left|y-\hat{y}\right|\right|_{2}^2\)는 \(\sum_{i=1}^{N}(y-\hat{y})^2\)와 같은 의미
- 위의 식을 통해 직교 정합 추구 방법을 \(y\)와 \(\hat{y}\) 사이의 "오차제곱합"을 \(tol\) 이하로 하면서 \(\left|\left|w\right|\right|_{0}\)를 최소로 하는 모델로 대체 가능
# 당뇨병 환자 데이터에 직교 정합 추구 방법 중 tol을 제약하는 방법 적용
...
model = OrthogonalMatchingPursuit(tol = 1.)
model.fit(X_train, y_train)
...
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(tol = 1)
학습 데이터 점수: 0.6032737807873105
평가 데이터 점수: 0.6175096016107812
# 출력 결과(n_nonzero_coefs = 7)
학습 데이터 점수: 0.49747193558480873
평가 데이터 점수: 0.5368821270302075
# 캘리포니아 주택 가격 데이터에 직교 정합 추구 적용
from sklearn.datasets import fetch_california_housing
california = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(california.data, california.target, test_size = 0.2)
model = OrthogonalMatchingPursuit(n_nonzero_coefs = 5) # 0이 아닌 특성을 5개로 지정
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(n_nonzero_coefs = 5)
학습 데이터 점수: 0.5922021375817
평가 데이터 점수: 0.6014385211125419
# 모델을 신축망으로 사용하였을 때 점수
학습 데이터 점수: 0.6066539688645749
평가 데이터 점수: 0.5937533298305722
# 모델을 Ridge로 사용하였을 때 점수
학습 데이터 점수: 0.604254843729662
평가 데이터 점수: 0.613608636245419
# 모델을 Lasso로 사용하였을 때 점수
학습 데이터 점수: 0.5433203729425291
평가 데이터 점수: 0.5490112288455995
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.6067992442029464
평가 데이터 점수: 0.6022552622453919
# 캘리포니아 주택 가격 데이터에 직교 정합 추구 방법 중 tol을 제약하는 방법 적용
model = OrthogonalMatchingPursuit(tol = 1.)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과(tol = 1.)
학습 데이터 점수: 0.6046375004558915
평가 데이터 점수: 0.6026936956740174
# 출력 결과(n_nonzero_coefs = 5)
학습 데이터 점수: 0.5922021375817
평가 데이터 점수: 0.6014385211125419
- 다항 회귀(Polynomail Regression)
- 입력 데이터를 비선형 변환 후 사용하는 방법
- 모델 자체는 선형 모델
$$ \hat{y}=w_{1}x_{1}+w_{2}x_{2}+w_{3}x_{3}+w_{4}x_{1}^2+w_{5}x_{2}^2$$
- 차수가 높아질수록 더 복잡한 데이터 학습 가능(더 구불구불한 그래프 생성 가능)
# 당뇨병 환자 데이터에 다항 회귀 적용
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_diabetes
X, y = load_diabetes(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42)
# make_pipeline으로 ML 과정을 순서대로 배치하여 하나의 파이프라인으로 묶기
model = make_pipeline(
PolynomialFeatures(degree = 2),
StandardScaler(),
LinearRegression()
)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과
학습 데이터 점수: 0.6048153298370548
평가 데이터 점수: 0.4242419459459561
# 모델을 직교 정합 추구로 사용하였을 때 점수
학습 데이터 점수: 0.49747193558480873
평가 데이터 점수: 0.5368821270302075
# 모델을 신축망으로 사용하였을 때 점수
학습 데이터 점수: 0.39452567238560965
평가 데이터 점수: 0.34426906645229316
# 모델을 Ridge로 사용하였을 때 점수
학습 데이터 점수: 0.5036670060593883
평가 데이터 점수: 0.5151286628940492
# 모델을 Lasso로 사용하였을 때 점수
학습 데이터 점수: 0.46683101421965556
평가 데이터 점수: 0.5875532568592793
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.5136038374290528
평가 데이터 점수: 0.5063114437093292
# 캘리포니아 주택 가격 데이터에 다항 회귀 적용
from sklearn.datasets import fetch_california_housing
california = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(california.data, california.target, test_size = 0.2)
model = make_pipeline(
PolynomialFeatures(degree = 2),
StandardScaler(),
LinearRegression()
)
model.fit(X_train, y_train)
print("학습 데이터 점수: {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수: {}".format(model.score(X_test, y_test)))
# 출력 결과
학습 데이터 점수: 0.6824013150066678
평가 데이터 점수: 0.6809334820406576
# 모델을 직교 정합 추구로 사용하였을 때 점수
학습 데이터 점수: 0.5922021375817
평가 데이터 점수: 0.6014385211125419
# 모델을 신축망으로 사용하였을 때 점수
학습 데이터 점수: 0.6066539688645749
평가 데이터 점수: 0.5937533298305722
# 모델을 Ridge로 사용하였을 때 점수
학습 데이터 점수: 0.604254843729662
평가 데이터 점수: 0.613608636245419
# 모델을 Lasso로 사용하였을 때 점수
학습 데이터 점수: 0.5433203729425291
평가 데이터 점수: 0.5490112288455995
# 모델을 LinearRegression으로 사용하였을 때 점수
학습 데이터 점수: 0.6067992442029464
평가 데이터 점수: 0.6022552622453919
'Python > Machine Learning' 카테고리의 다른 글
[머신러닝 알고리즘] K 최근접 이웃 (0) | 2023.01.10 |
---|---|
[머신러닝 알고리즘] 로지스틱 회귀 (0) | 2023.01.04 |
[머신러닝 알고리즘] 선형 회귀(1) (0) | 2022.12.29 |
[머신러닝 알고리즘] 사이킷런 제대로 시작하기(2) (0) | 2022.12.28 |
[머신러닝 알고리즘] 사이킷런 제대로 시작하기(1) (1) | 2022.12.26 |