728x90

회귀 모델에서 과소 적합과 과적합을 다루기 위한 최적의 비용 함수

- 잔차 RSS를 줄이는것 뿐만이 아니라 회귀 계수가 급격하게 커지는 것을 막아야 함.

 * 아래의 그림와 같이 과적합의 경우 회귀계수가 매우 크게 증가됨.

- 최적의 비용 함수 = 잔차 최소화 + 회귀 계수 크기 제어

 

 

 

L2 규제와 L1 규제

- 위 비용 함수에서 alpha가 0이라면 RSS가 최소가 되는 모델을 구하게 됨.

- alpha가 무한대라면 가중치 벡터(계수 벡터) W가 매우 작아져야 비용이 최소화됨,

=> alpha가 크면 회귀 계수를 줄여 과적합 개선, 작다면 RSS로 상쇄시킴

- 아래의 경우와 같이 가중치 벡터의 제곱에 패널티를 주는 경우를 L2 규제, L2 규제를 적용한 선형 회귀(릿지 회귀)

- 아래의 경우처럼 가중치 벡터의 절대값에 패널티를 주는 경우 L1 규제, L1규제를 적용한 선형 회귀(라쏘 회귀)

 

 

 

 

릿지 회귀를 통한 보스턴 주택 가격 예측하기

 

라이브러리 임포트하고 출력

from sklearn.linear_model import Ridge
from sklearn.linear_model import Lasso, ElasticNet
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import PolynomialFeatures
from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
import seaborn as sns

warnings.filterwarnings("ignore")
%load_ext autotime

 

 

특징과 라벨 데이터 준비

df = pd.DataFrame(data=boston.data, columns=boston.feature_names)
df["PRICE"] = boston.target
df.head()

X = df.iloc[:,:-1]
y = df.iloc[:, -1]

 

 

alpha = 10일때 릿지 회귀 교차 검증 결과

 

ridge = Ridge(alpha = 10)
neg_mse_scores = cross_val_score(pipeline, X, y, scoring="neg_mean_squared_error",cv = 5)
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)

print("neg_mse_socres : {}".format(neg_mse_scores))
print("rmse_scores : {}".format(rmse_scores))
print("avg_rmse : {}".format(avg_rmse))

 

 

alpha 값에 변화를 줄때 릿지 회귀

- alpha = 0 인 경우(MSE만을 비용함수로 한 경우) avg rmse = 5.82865

- alpha = 100 인 경우(MSE와 L2 규제를 적용한 경우) avg rmse = 5.32959로 가장 작음

alphas = [0, 0.1, 1, 10, 100]
for alpha in alphas:
    ridge = Ridge(alpha = alpha)
    neg_mse_scores = cross_val_score(ridge, X, y, scoring="neg_mean_squared_error",cv = 5)
    rmse_scores = np.sqrt(-1 * neg_mse_scores)
    avg_rmse = np.mean(rmse_scores)
    print("### alpha = {} ###".format(alpha))
    print("neg_mse_socres : {}".format(neg_mse_scores))
    print("rmse_scores : {}".format(rmse_scores))
    print("avg_rmse : {}\n".format(avg_rmse))

 

 

 

 

알파 값에 따른 회귀 계수의 변화 시각화

 

 

alpha가 커지면서 회귀 계수 값들이 전체적으로 작아지는것을 확인할 수 있음.

* 회귀 계수를 0으로 만들지는 않음)

 

fig, axs = plt.subplots(figsize=(18, 6), nrows=1, ncols=5)

coeff_df = pd.DataFrame()

for pos, alpha in enumerate(alphas):
    ridge = Ridge(alpha=alpha)
    ridge.fit(X, y)
    coeff = pd.Series(ridge.coef_, index=X.columns)
    colname="alpha="+str(alpha)
    coeff_df[colname] = coeff
    
    coeff = coeff.sort_values(ascending=False)
    axs[pos].set_title(colname)
    axs[pos].set_xlim(-3, 6)
    sns.barplot(x=coeff.values, y=coeff.index, ax=axs[pos])
plt.show()

 

 

 

 

 

 

라쏘 회귀

- 가중치 벡터 W의 절대값에 패널티 부여하는 L1 규제를 선형 회귀에 적용

 

- alpha값이 커지면서 릿지 회귀떄와는 달리 회귀 계수가 0이 되는 특징이 생김

 -> 회귀 계수가 0인 특징은 제거 가능

alphas = [0.07, 0.1, 0.5, 1, 3]
def get_linear_reg_eval(model_name, params=None, X_data = None, y_target=None):
    fig, axs = plt.subplots(figsize=(18, 6), nrows=1, ncols=5)

    print("#### {} ####".format(model_name))
    for pos, param in enumerate(params):
        if model_name == "Ridge": model = Ridge(alpha=param)
        elif model_name == "Lasso": model= Lasso(alpha=param)
        elif model_name == "ElasticNet": model = ElasticJet(alpha=param, l1_ratio=0.7)
        
        neg_mse_scores = cross_val_score(model, X, y, scoring="neg_mean_squared_error",cv = 5)
        rmse_scores = np.sqrt(-1 * neg_mse_scores)
        avg_rmse = np.mean(rmse_scores)
        print("### alpha = {} ###".format(param))
        print("neg_mse_socres : {}".format(neg_mse_scores))
        print("rmse_scores : {}".format(rmse_scores))
        print("avg_rmse : {}\n".format(avg_rmse))
        
        model.fit(X_data, y_target)
        coeff = pd.Series(model.coef_, index=X_data.columns)
        colname="alpha="+str(param)
        coeff_df[colname] = coeff

        coeff = coeff.sort_values(ascending=False)
        axs[pos].set_title(colname)
        axs[pos].set_xlim(-3, 6)
        sns.barplot(x=coeff.values, y=coeff.index, ax=axs[pos])
    plt.show()
 get_linear_reg_eval("Lasso", params=alphas, X_data=X, y_target=y)

 

 

엘라스틱 회귀

- L2 규제와 L1 규제의 결합

- 라쏘 회귀에서 중요 피처들만 남기고, 나머지를 0으로 만드는 문제를 개선하기 위해 L2 규제를 추가한것

- l1_ratio = alpha1/(alpha1 + alpha2)

* l1_ratio = 0.7 = 7/(7 + 3)

get_linear_reg_eval("ElasticNet", params=alphas, X_data=X, y_target=y)

alpha = 0.5 -> avg_rmse = 5.466으로 가장 낮음.

 

라쏘 회귀보다 사라진 변수가 적음

 

300x250

+ Recent posts