Python/ML & DL 공부

[ML] 03-3 특성 공학과 규제

dori_0 2022. 3. 7. 13:47

혼자 공부하는 머신러닝+딥러닝 책을 바탕으로 공부한 내용입니다.

 

CH3 회귀 알고리즘과 모델 규제 ③

모델의 과대적합 제어하기

 


 

여러 특성을 사용한 다중 회귀에 대해 배우고 사이킷런의 여러 도구를 사용해보자
복잡한 모델의 과대적합을 막기 위한 릿지와 라쏘 회귀에 대해 배워보자

 

 

▶ 다중 회귀

선형 회귀는 특성이 많을수록 더 좋은 효과를 낸다

앞서 만들었던 모델보다 더 좋은 성능을 내기 위해 길이, 높이, 두께 특성을 모두 사용해서 모델을 만들어보자

 

여러 개의 특성을 사용한 선형 회귀를 다중 회귀라고 부른다.

또, 기존의 특성을 사용해 새로운 특성을 뽑아내는 작업을 특성 공학이라고 부른다.

 

 

▶ 데이터 준비

이번에는 판다스를 이용해 농어 데이터를 판다스 데이터프레임에 저장하자

그 후 넘파이 배열로 변환하여 선형 회귀 모델을 훈련해보자

import pandas as pd
df = pd.read_csv("https://bit.ly/perch_csv_data")
perch_full = df.to_numpy()

import numpy as np
perch_weight = np.array([5.9, 32.0, 40.0, 51.5, 70.0, 100.0, 78.0, 80.0, 85.0, 85.0, 110.0,
       115.0, 125.0, 130.0, 120.0, 120.0, 130.0, 135.0, 110.0, 130.0,
       150.0, 145.0, 150.0, 170.0, 225.0, 145.0, 188.0, 180.0, 197.0,
       218.0, 300.0, 260.0, 265.0, 250.0, 250.0, 300.0, 320.0, 514.0,
       556.0, 840.0, 685.0, 700.0, 700.0, 690.0, 900.0, 650.0, 820.0,
       850.0, 900.0, 1015.0, 820.0, 1100.0, 1000.0, 1100.0, 1000.0,
       1000.0])

 

이제 perch_full과 perch_weight를 train set, test set으로 나눠보자

# train set, test set으로 나누기
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(
    perch_full, perch_weight, random_state=42)

 

 

▶ 사이킷런의 변환기

모델의 성능을 높이기 위해 사이킷런의 PolynomialFeatures 클래스를 사용해보자.

이 클래스는 기본적으로 각 특성을 제곱한 항과 특성끼리 서로 곱한 항을 추가해준다.

from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures(include_bias=False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
test_poly = poly.transform(test_input)
train_poly.shape  #(42, 9)
  • train_poly 배열의 열의 개수가 특성의 개수이다.
  • 9개의 특성이 만들어진 것으로 보인다.

 

# 9개의 특성 확인하기
poly.get_feature_names()

다음과 같은 특성들이 만들어졌다. 이를 바탕으로 다중 회귀 모델을 훈련해보자

 

 

▶ 다중 회귀 모델 훈련하기

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(train_poly, train_target)

# train set 점수 확인
lr.score(train_poly, train_target)  #0.9903183436982125
# test set 점수 확인
lr.score(test_poly, test_target)  #0.9714559911594155
  • 특성이 늘어나면 선형 회귀의 능력은 매우 강해진다는 것을 확인할 수 있다.
  • 이전에 있었던 과소적합 문제는 나타나지 않는 것으로 보인다.

 

 

특성을 더 많이 추가하면 어떻게 될까?

PolynomialFeatures 클래스의 degree 매개변수를 사용하면 필요한 고차항의 최대 차수를 지정할 수 있다.

이번에는 5제곱까지 특성을 만들어 출력해보자

poly = PolynomialFeatures(degree=5, include_bias=False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
test_poly = poly.transform(test_input)
train_poly.shape  #(42, 55)
  • 만들어진 특성의 개수는 55개로 확인된다.

 

lr.fit(train_poly, train_target)

lr.score(train_poly, train_target)  #0.9999999999938143
lr.score(test_poly, test_target)  #-144.40744532797535
  • 특성의 개수를 늘리면 선형 모델은 아주 강력해진다.
  • 하지만, 이런 모델은 train set에 과대적합되므로 test set에서는 좋지 않은 점수를 만들기 때문에 이에 대한 규제가 필요하다.

 

 

▶ 규제

규제는 모델이 훈련 세트에 과대적합되지 않도록 만드는 것이다.

선형 회귀 모델에 규제를 추가한 모델을 릿지, 라쏘라고 부른다.

  • 릿지 - 계수를 제곱한 값을 기준으로 규제를 적용, 릿지를 일반적으로 더 선호함
  • 라쏘 - 계수의 절댓값을 기준으로 규제를 적용, 계수의 크기를 0으로 만들 수도 있음

 

 

본격적으로 규제를 적용하기 전에 정규화를 먼저 해주자

사이킷런의 StandardScaler 클래스를 사용하면 표준점수로 바꿀 수 있다.

# 규제 적용하기 전에 먼저 정규화하기
# 표준점수로 변환하기
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_poly)
train_scaled = ss.transform(train_poly)
test_scaled = ss.transform(test_poly)

 

 

 

▶ 릿지 회귀

릿지와 라쏘 모두 sklearn.linear_model 패키지 안에 있다.

# 릿지 모델 훈련
from sklearn.linear_model import Ridge
ridge = Ridge()
ridge.fit(train_scaled, train_target)

# train set 점수
ridge.score(train_scaled, train_target)  #0.9896101671037343
# test set 점수
ridge.score(test_scaled, test_target)  #0.9790693977615386
  • 많은 특성을 사용했음에도 불구하고 훈련 세트에 과대적합되지 않아 테스트 세트에서도 좋은 성능을 내고 있다.

 

 

릿지와 라쏘 모델을 사용할 때 alpha 매개변수를 사용하여 규제의 양을 임의로 조절할 수 있다.

  • alpha 값이 크면 규제 강도가 세지므로 계수 값을 더 줄여 과소적합 되도록 유도
  • alpha 값이 작으면 계수를 줄이는 역할이 줄어들고 선형 회귀 모델과 유사해지므로 과대적합 유도

 

 

적절한 alpha 값을 찾기 위해 alpha 값에 대한 R^2 값의 그래프를 그려보자

훈련 세트와 테스트 세트의 점수가 가장 가까운 지점이 최적의 alpha 값이 된다.

# 적절한 alpha 값 찾기
import matplotlib.pyplot as plt
train_score = []
test_score = []

alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
for alpha in alpha_list:
    # 릿지 모델 만들기
    ridge = Ridge(alpha = alpha)
    # 릿지 모델 훈련
    ridge.fit(train_scaled, train_target)
    # 점수 저장하기
    train_score.append(ridge.score(train_scaled, train_target))
    test_score.append(ridge.score(test_scaled, test_target))
    
# 그래프로 확인
plt.plot(np.log10(alpha_list), train_score)
plt.plot(np.log10(alpha_list), test_score)
plt.xlabel('alpha')
plt.ylabel('R^2')
plt.show()

  • 가장 적절한 alpha 값은 10^(-1)이다.

 

ridge = Ridge(alpha=0.1)
ridge.fit(train_scaled, train_target)
print(ridge.score(train_scaled, train_target))
print(ridge.score(test_scaled, test_target))

  • train set, test set의 점수가 비슷하게 모두 높다.
  • 과대적합과 과소적합 사이에서 균형을 잘 맞추고 있는 것으로 보여진다.

 

 

▶ 라쏘 회귀

이번에는 라쏘 모델을 훈련해보자

from sklearn.linear_model import Lasso
lasso = Lasso()
lasso.fit(train_scaled, train_target)

print(lasso.score(train_scaled, train_target))
print(lasso.score(test_scaled, test_target))

  • 릿지와 마찬가지로 점수가 좋은 것이 확인된다.

 

 

라쏘 모델도 alpha 매개변수로 규제의 강도를 조절해 최적의 alpha 값을 찾아보자

# 적절한 alpha 값 찾기
train_score = []
test_score = []
alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]

for alpha in alpha_list:
    # 라쏘 모델 만들기, 반복 횟수를 10000으로 지정
    lasso = Lasso(alpha=alpha, max_iter=10000)
    # 라쏘 모델 훈련
    lasso.fit(train_scaled, train_target)
    # 점수 저장하기
    train_score.append(lasso.score(train_scaled, train_target))
    test_score.append(lasso.score(test_scaled, test_target))
    
# 그래프 그리기
plt.plot(np.log10(alpha_list), train_score)
plt.plot(np.log10(alpha_list), test_score)
plt.xlabel('alpha')
plt.ylabel('R^2')
plt.show()

  • 최적의 alpha 값은 10^1으로 보여진다.

 

 

이 알파값을 기준으로 다시한번 모델을 훈련해보자

lasso = Lasso(alpha=10)
lasso.fit(train_scaled, train_target)
print(lasso.score(train_scaled, train_target))
print(lasso.score(test_scaled, test_target))

  • 릿지와 마찬가지로 특성을 많이 사용했지만, 과대적합을 잘 억제하고 테스트 세트의 성능을 크게 높인 것을 확인할 수 있다.

 

 

라쏘 모델은 '계수 값을 0으로 만들 수도 있다'는 특징이 있었다.

라쏘 모델 계수 중 0인 것이 몇 개인지 확인해보자

# 라쏘 모델 계수 중 0인 것 개수 확인
np.sum(lasso.coef_ == 0)  #40
  • 55개의 특성 중 40개의 계수가 0이므로 라쏘 모델이 사용한 특성은 15개밖에 되지 않는다.
  • 이런 특징 때문에 라쏘 모델을 유용한 특성을 골라내는 용도로도 사용할 수 있다.

 

 

 

▶ 정리

  1. 선형 회귀는 특성이 많을수록 더 좋은 효과를 낸다
  2. 특성이 너무 많으면 선형 회귀 모델을 제약하기 위한 도구가 필요하다 ( 릿지 회귀, 라쏘 회귀 )
  3. 릿지 회귀 - 계수를 제곱한 값을 기준으로 규제를 적용한다
  4. 라쏘 회귀 - 계수의 절댓값을 기준으로 규제를 적용한다. 계수의 크기를 0으로 만들 수도 있다.

 

 

 

'Python > ML & DL 공부' 카테고리의 다른 글

[ML] 04-2 확률적 경사 하강법  (0) 2022.03.10
[ML] 04-1 로지스틱 회귀  (0) 2022.03.07
[ML] 03-2 선형 회귀  (2) 2022.03.06
[ML] 03-1 k-최근접 이웃 회귀  (0) 2022.03.06
[ML] 02-2 데이터 전처리  (0) 2022.03.05