본문 바로가기
혼공학습단

[혼공머신] 2주차(2)_특성 공학과 규제

by netsgo 2024. 1. 7.
 

혼자 공부하는 머신러닝+딥러닝 - 예스24

- 혼자 해도 충분하다! 1:1 과외하듯 배우는 인공지능 자습서 이 책은 수식과 이론으로 중무장한 머신러닝, 딥러닝 책에 지친 ‘독학하는 입문자’가 ‘꼭 필요한 내용을 제대로’ 학습할 수 있

www.yes24.com

 

다중 회귀(Multiple Regression)


1개의 특성을 사용했을 때 선형 회귀 모델이 학습하는 것은 직선이다. 특성이 2개면 선형 회귀는 평면을 학습한다. 특성이 많은 고차원에서는 선형 회귀가 매우 복잡한 모델을 표현할 수 있다.

 

 

기존의 특성을 사용해 새로운 특성을 뽑아내는 작업을 특성 공학(featrue engineering)이라고 한다. 사이킷런은 특성을 만들거나 전처리하기 위한 다양한 클래스를 제공한다. 이러한 클래스를 변환기(transformer)라고 부른다. 사이킷런의 모델 클래스에 일관된 fit(), score(), predict() 메서드가 있는 것처럼 transformer 클래스는 모두 fit(), transform() 메서드를 제공한다.

 

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)

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

print(lr.score(train_poly, train_target) # 0.99
print(lr.score(test_poly, test_target) # 0.97

 

규제(Regularlization)


규제(regularlization)는 머신러닝 모델이 훈련 세트를 너무 과도하게 학습하지 못하도록 방지하는 것을 말한다. 모델이 훈련 세트에 overfitting하지 않도록 만드는 것이다. 선형 회귀 모델의 경우 특성에 곱해지는 계수의 크기를 작게 만드는 일이다.

 

 

특성의 스케일이 정규화되지 않으면 여기에 곱해지는 계수 값도 차이가 나게 된다. 일반적으로 선형 회귀 모델에 규제를 적용할 때 계수 값의 크기가 서로 많이 다르면 공정하게 제어되지 않을 것이다. 따라서 규제를 적용하기 전에 먼저 정규화를 진행한다. 사이킷런에서 제공하는 StandardScaler 클래스를 사용하면 쉽게 평균과 표준편차를 구할 수 있다.

 

from sklearn.preprocessing import StandardScaler

ss = StandardScaler()
ss.fit(train_poly) # PolynomialFeatures 클래스로 처리한 데이터
train_scaled = ss.trasform(train_poly)
test_scaled = ss.transform(test_poly)

 

선형 회귀 모델에 규제를 추가한 모델을 릿지(ridge)와 라쏘(lasso)라고 부른다. 두 모델은 규제를 가하는 방법이 서로 다르다. ridge는 계수를 제곱한 값을 기준으로 regularlization을 적용하고, lasso는 계수의 절댓값을 기준으로 regularlization을 적용한다. 일반적으로 ridge를 조금 더 선호하며 두 알고리즘 모두 계수의 크기를 줄이지만 lasso는 아예 0으로 만들 수도 있다.

 

ridge와 lasso를 사용할 때 규제의 양을 임의로 조절할 수 있다. 모델 객체를 마들 때 alpha 매개변수로 규제의 강도를 조절한다. alpha 값이 크면 규제 강도가 세지므로 계수 값을 더 줄이고 alpha 값이 작으면 계수를 줄이는 역할이 줄어들어 선형 회귀 모델과 유사해진다.

 

from sklearn.linear_model import Ridge

# Ridge 회귀
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)

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

 

적절한 alpha를 찾는 한 가지 방법은 alpha에 대한 R^2의 그래프를 그려 보는 것이다. 훈련 데이터와 테스트 데이터의 점수가 가장 가까운 지점이 최적의 alpha 값이 된다. 이때 alpha 값을 적절히 표현하기 위해 로그 함수로 바꾸어 표현한다.(상용로그 np.log10() 함수 사용)

 

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_index = np.argmin(np.array(train_score) - np.array(test_score))
print(f'alpha_index: {alpha_index}, ahpha: {alpha_list[alpha_index]}')

 

 

특성을 많이 추가하면 선형 회귀는 매우 강력한 성능을 나타낸다. 하지만 특성이 너무 많으면 선형 회귀 모델을 제약하기 위한 도구가 필요하다. 이를 위해 ridge와 lasso 모델을 사용할 수 있다.