AI/혼자공부하는머신러닝딥러닝

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

inthyes 2024. 1. 20. 22:47

다중 회귀

다중 회귀(multiple regression) : 여러 개의 특성을 사용한 선형 회귀

특성 공학(feature engineering) : 기존 특성을 사용해 새로운 특성을 뽑아내는 작업

 

데이터 준비

판다스의 read_csv()함수에 주소를 넣은 후 to_numpy()메서드를  사용해 넘파이 배열로 변경한다.

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

타깃 데이터는 이전과 동일한 방식으로 준비한다.

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를 훈련 세트와 테스트 세트로 분리한다.

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)

 

 

사이킷런의 변환기

변환기(transformer) : 특성을 만들거나 전처리하기 위한 클래스

 

모든 변환기 클래스는 fit(), transform() 메서드를 제공한다.

PolynomialFeatures 클래스를 활용하여 2개의 특성 2와 3으로 이루어진 샘플 하나를 적용하기 위해 객체를 생성한 후에 fit(), transform() 메서드를 차례대로 호출한다.

 

fit()메서드 : 새롭게 만들 특성 조합을 찾는 역할

transform()메서드 : 실제로 데이터 변환

from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures()
poly.fit([[2, 3]])
print(poly.transform([[2, 3]]))

 

0차항(1)을 포함시키지 않기 위해서는 include_bias를 False로 설정해주어야 한다.

include_bias = False로 지정하지 않아도 사이킷런 모델은 자동으로 특성에 추가된 절편 항을 무시하기 때문에 필수적으로 설정할 필요는 없다.

poly = PolynomialFeatures(include_bias = False)

poly.fit([[2, 3]])
print(poly.transform([[2, 3]]))

 

 

train_input에 이 방식을 적용한 후에 변환한 데이터를 train_poly에 저장하고 배열의 크기를 출력한다.

poly = PolynomialFeatures(include_bias = False)

poly.fit(train_input)
train_poly = poly.transform(train_input)
print(train_poly.shape)

 

get_feature_names_out()메서드를 호출하면 9개의 특성이 각각 어떤 입력의 조합으로 만들어졌는지 확인할 수 있다.

poly.get_feature_names_out()

 

테스트 세트 또한 변환한다.

test_poly = poly.transform(test_input)

 

다중 회귀 모델 훈련하기

다중 회귀 모델을 훈련하는 것은 선형 회귀 모델을 훈련하는 것과 같다.

사이킷런의 LinearRegression 클래스를 임포트하고 앞에서 만든 train_poly를 사용해 모델을 훈련시킨다.

 

from sklearn.linear_model import LinearRegression
lr = LinearRegression()

lr.fit(train_poly, train_target)
print(lr.score(train_poly, train_target))

 

테스트 세트에 대한 점수를 출력해보았을 때, 테스트 세트에 대한 점수는 높아지지 않았지만 과소적합 문제는 해결이 되었음을 알 수 있다.

print(lr.score(test_poly, test_target))

 

 

특성을 더 추가한 상태로 5제곱까지 특성을 만들어 출력한다.

poly = PolynomialFeatures(degree = 5, include_bias = False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
test_poly = poly.transform(test_input)
print(train_poly.shape)

훈련 세트의 점수가 아주 우수하게 나오는 것을 확인할 수 있다.

lr.fit(train_poly, train_target)
print(lr.score(train_poly, train_target))

다만 테스트 세트의 경우 큰 음수가 출력된다.

print(lr.score(test_poly, test_target))

 

 

특성의 개수를 크게 늘리면  훈련 세트에 대해 거의 완벽하게 학습이 가능하지만 훈련 세트에 과대적합되므로 테스트 세트에서는 형편없는 점수를 만들게 된다.

 

규제

규제는 머신러닝 모델이 훈련 세트를 과도하게 학습하지 못하도록 훼방하는 것을 말한다.

선형 회귀 모델의 경우 특성에 곱해지는 계수(또는 기울기)의 크기를 작게 만드는 것을 의미한다.

 

규제를 적용하기 전에 정규화를 먼저 수행해야한다.

 

사이킷런의 StandardScaler 클래스의 객체 ss를 초기화한 후 PolynomialFeatures 클래스로 만든 train_poly를 사용해 이 객체를 훈련한다.

from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_poly)
train_scaled = ss.transform(train_poly)
test_scaled = ss.transform(test_poly)

 

릿지 회귀

모델 객체를 만들고 fit()메서드에서 훈련한 다음 score()메서드로 평가한다.

from sklearn.linear_model import Ridge
ridge = Ridge()
ridge.fit(train_scaled, train_target)
print(ridge.score(train_scaled, train_target))

 

테스트 세트에 대한 점수도 정상으로 돌아온 것을 확인할 수 있다.

print(ridge.score(test_scaled, test_target))

릿지와 라쏘 모델을 사용할 때 규제의 양을 임의로 조절할 수 있다.

모델 객체를 만들 때 alpha 매개변수로 규제의 강도를 조절한다.

alpha값이 크면 규제 강도가 세지므로 계수 값을 더 줄이고 조금 더 과소적합되도록 유도한다.

작을 경우 계수를 줄이는 역할이 줄어들고 선형 회귀 모델과 유사해지므로 과대적합될 가능성이 커진다.

 

적절한 alpha값을 찾는 방법 중 하나는 alpha값에 대한 결정계수값의 그래프를 그리는 것이다.

이를 구현하기 위해서는 alpha값을 바꿀 때마다 score()메서드의 결과를 저장할 리스트가 필요하다.

import matplotlib.pyplot as plt
train_score = []
test_score = []

 

alpha값을 0.001에서 100까지 10배씩 늘려가며 릿지 회귀 모델을 훈련한 다음 훈련 세트와 테스트 세트의 점수를 파이썬 리스트에 저장한다.

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값은 두 그래프가 가장 가깝고 테스트 세트의 점수가 가장 높은 -1, 즉 0.1이다.

이후 alpha값을 0.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))

수치를 통해 이 모델이 훈련 세트와 테스트 세트의 점수가 비슷하게 모두 높고 과대적합과 과소적합 사이에서 균형을 맞추고 있음을 판단할 수 있다.

라쏘 회귀

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

train_score = []
test_score = []
alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
for alpha in alpha_list:
  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()

 

 

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으로 만들 수 있다. 아래 코드를 실행시켜 이를 확인할 수 있다.

 

print(np.sum(lasso.coef_ == 0))

55개의 특성을 모델에 주입하였는데 라쏘 모델이 사용한 특성은 15개이다. 이런 특징 때문에 라쏘 모델을 유용한 특성을 골라내는 용도로도 활용이 가능하다.

'AI > 혼자공부하는머신러닝딥러닝' 카테고리의 다른 글

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