Machine Learning

[ML]과적합 방지 - 데이터 규제(L1, L2)

yeonny_do 2023. 11. 21. 08:19

* 독립변수가 많을수록 과적합 발생 확률 높음

 

■ 데이터 규제

- 규제란 데이터에 과적합을 방지하기 위한 방법 중 하나로 모델이 학습하는데 사용되는 가중치에 규제 값을 주어 과적합이 되는 것을 막고, 모델의 일반화 성능이 증가하게 됨. (가중치 값을 규제하는 이유는, 손실이 최소화 되는 점을 찾는 목적으로 가중치가 매우 커지게 되는 경우가 존재하기 때문임.)

 

- 모델의 일반화? 약간의 오차는 허용하면서 적절하게 분리하여 전체적인 특징을 잘 반영하는 모델을 만드는 것을 말함. 그래프 상에서 모형의 주름을 핀다고 생각하면 됨.

 

- 결국, 가중치의 모든 원소를 0에 가깝게 만드는 것인데, 이는 모든 특성이 출력에 주는 영향을 최소한으로 만들어 과적합이 발생하지 않도록 모델을 강제로 제한하는 것임. (★가중치 최소화)

 

 

※ 벡터의 노름 (norm)

 

 - 벡터의 이동거리를 노름이라고 함

 - 맨해튼 거리 (L1규제) : 벡터 성분의 절댓값을 모두 합한 것

 - 유클리드 거리 (L2 규제) : 빗변의 길이를 구하는 식 즉, 피타고라스 정리와 같음

 

 

 

□ L1규제

 

 ★  덜 중요한 변수의 가중치를 0으로 하여 제거함.

 

▶ 규제가 적용된 손실함수 

- 기존 비용함수는  loss가 최소인 최적화점만 찾다보니, weight가 커지게 될 수 있음.

- 그래서 기존의 비용함수에 (규제의 양을 조절하는 상수(람다) * weight의 절댓값) 을 빼줌

 

 L1규제가 적용된 손실함수의 미분식

※ 람다 * sin(w) : 고정상수

※ sin(w) 

1   if w>0
0   if w=0
-1  if w<0

 

 

- 결국, 자잘한 가중치들은 0으로 수렴하고 중요한 가중치만 남아서 feature 수가 줄어들게 됨. 그러면 과적합 현상을 막을 수 있게 됨.

 

L1규제가 적용된 선형회기모델을 라쏘(Lasso)라고 함

 

 

□ L2규제

 

  L2규제가 적용된 손실함수의 미분식

  람다 * weight : weight값에 비례해서 가중치에 minus연산이 이루어짐 =>모든 가중치가 0으로 수렴하지 않음

 

- L2 규제 적용된 선형회귀 모델  : 릿지(Ridge)

 

 

 

□ 엘라스틱(Elastic) : L1+L2

 

 


■ 구현

 

□ 보스톤 집값 예측

1) 패키지 불러오기 & 데이터 로드 및 확인

 
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Lasso, Ridge, ElasticNet
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
import pandas as pd
import numpy as np
 

 

 
# 데이터 로드 및 확인

boston = pd.read_csv('HousingData.csv')
print(boston.shape)
display(boston.head())
 

 

 

 
boston.isna().sum()
 

 

결측치 존재하는 행 제거

 

 
boston.dropna(inplace=True)
 

 

 

2)  독립변수, 종속변수 나누기

 
# 독립변수, 종속변수
x = boston.drop('MEDV', axis=1)
y = boston['MEDV']
x.head()
 

 

독립변수 확인

 

3) 학습 데이터, 평가 데이터 나누기

 
# 학습 데이터, 평가 데이터 분리
scaled_data = StandardScaler().fit_transform(x)
x_train,x_test,y_train,y_test = train_test_split(scaled_data,y,test_size=0.3,random_state=10)
 

 

 

알파값 변화에 따른 회귀계수 및 상관계수 계산

 

- 알파값 : 규제강도,  회귀계수 : 가중치, 상관계수: R2

- 알파값은 규제 강도를 제어하는 상수 [0,inf)범위의 부동 소수점 값을 사용할 수 있음

- alpha=0 : LinearRegression 에서 사용하는 일반적인 최소 제곱법과 같아짐  (규제 사용X)

 

 

4) 다양한 회귀 모델 생성을 위한 함수 

 
# alpha는 리스트로 받음
def regulation_compare (alpha, model_name):
    df = pd.DataFrame()
    for a in alpha:
        print('회귀모형 이름 :',model_name)
        print('알파값 :',a)

        if model_name == 'Ridge':
            model = Ridge(alpha=a)
        elif model_name =='Lasso':
            model = Lasso(alpha=a)
        elif model_name == "ElasticNet":
            model = ElasticNet(alpha=a,l1_ratio=0.5) # 라쏘(L1), 릿지(L2) 비율 정해줘야 함

        model.fit(x_train,y_train)
        print(f'결정계수 : {model.score(x_test,y_test):.3f}')
        weight = {f:w for f,w in zip(x.columns,model.coef_)} # 컬럼명 : 가중치

        y_hat = model.predict(x_test)
        print(f'RMSE : {np.sqrt(mean_squared_error(y_test, y_hat)):.3f}')
        print('-'*40)
        df['alpha='+str(a)] = pd.Series(weight) #각 키값이 index가 됨

    return df
 

 

 

5) 라쏘 회귀모형

 
# Lasso 회귀모델 생성 (L1규제 적용)
alpha = [0.07,0.1,0.5,1,3]
regulation_compare(alpha,'Lasso')
 

 

 

 

 

6) 릿지 회귀모형

 
# 릿지 회귀모델 생성 (L2규제)
# L1보다 높은 규제 강도 지정 가능
# 자잘한 독립변수 0으로 만들지는 않음
# 모든 항들이 종속변수에 일정 부분 관여한 것에 대한 영향을 완전히 배제하지 않음

alpha = [0,1,5,10,100]
regulation_compare(alpha, 'Ridge')
 

 

 

 

 

 

7) 엘라스틱 회귀모형

 
# 엘라스틱 회귀 모델 생성 (L1+L2 규제)
alpha = [0,1,5,10,100]
regulation_compare(alpha, 'ElasticNet')
 

 

L1과 L2의 특징 모두 가짐