메이플의 개발 스토리
[ML] 3-3 특성 공학과 규제 본문
특성 공학과 규제¶
다중 회귀¶
- multiple regression
- 여러 개의 특성을 사용하는 회귀 모델
- 특성이 많으면 선형 모델은 강력한 성능을 발휘함
특성 공학¶
- feature engineering
- 주어진 특성을 조합하여 새로운 특성을 만드는 일련의 작업 과정
릿지¶
- 규제가 있는 선형 회귀 모델 중 하나
- 선형 모델의 계수를 작게 만들어 과대적합을 완화
라쏘¶
- 규제가 있는 선형 회귀 모델 중 하나
- 릿지와 달리 계수 값을 아예 0으로 만들 수 있음
하이퍼 파라미터¶
- 머신러닝 알고리즘이 학습하지 않는 파라미터
- 대표적으로 릿지와 라쏘의 규제 강도 alpha 파라미터가 있음
0. 데이터 준비¶
In [ ]:
import pandas as pd
df = pd.read_csv('https://bit.ly/perch_csv_data')
perch_full = df.to_numpy()
print(perch_full)
[[ 8.4 2.11 1.41] [13.7 3.53 2. ] [15. 3.82 2.43] [16.2 4.59 2.63] [17.4 4.59 2.94] [18. 5.22 3.32] [18.7 5.2 3.12] [19. 5.64 3.05] [19.6 5.14 3.04] [20. 5.08 2.77] [21. 5.69 3.56] [21. 5.92 3.31] [21. 5.69 3.67] [21.3 6.38 3.53] [22. 6.11 3.41] [22. 5.64 3.52] [22. 6.11 3.52] [22. 5.88 3.52] [22. 5.52 4. ] [22.5 5.86 3.62] [22.5 6.79 3.62] [22.7 5.95 3.63] [23. 5.22 3.63] [23.5 6.28 3.72] [24. 7.29 3.72] [24. 6.38 3.82] [24.6 6.73 4.17] [25. 6.44 3.68] [25.6 6.56 4.24] [26.5 7.17 4.14] [27.3 8.32 5.14] [27.5 7.17 4.34] [27.5 7.05 4.34] [27.5 7.28 4.57] [28. 7.82 4.2 ] [28.7 7.59 4.64] [30. 7.62 4.77] [32.8 10.03 6.02] [34.5 10.26 6.39] [35. 11.49 7.8 ] [36.5 10.88 6.86] [36. 10.61 6.74] [37. 10.84 6.26] [37. 10.57 6.37] [39. 11.14 7.49] [39. 11.14 6. ] [39. 12.43 7.35] [40. 11.93 7.11] [40. 11.73 7.22] [40. 12.38 7.46] [40. 11.14 6.63] [42. 12.8 6.87] [43. 11.93 7.28] [43. 12.51 7.42] [43.5 12.6 8.14] [44. 12.49 7.6 ]]
In [ ]:
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])
1. 훈련 세트와 테스트 세트 분리¶
In [ ]:
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)
2. 다항 특성 만들기¶
- 사이킷런의 변환기 - 예제
In [ ]:
from sklearn.preprocessing import PolynomialFeatures
# degree = 2
poly = PolynomialFeatures()
poly.fit([[2, 3]])
# 1(bias), 2, 3, 2**1, 2*3, 3**2
print(poly.transform([[2, 3]]))
poly.get_feature_names()
[[1. 2. 3. 4. 6. 9.]]
/usr/local/lib/python3.7/dist-packages/sklearn/utils/deprecation.py:87: FutureWarning: Function get_feature_names is deprecated; get_feature_names is deprecated in 1.0 and will be removed in 1.2. Please use get_feature_names_out instead. warnings.warn(msg, category=FutureWarning)
Out[ ]:
['1', 'x0', 'x1', 'x0^2', 'x0 x1', 'x1^2']
- 사이킷런의 변환기로 2차원 배열로 변경
In [ ]:
poly = PolynomialFeatures(include_bias=False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
print(train_poly.shape)
(42, 9)
In [ ]:
poly.get_feature_names()
/usr/local/lib/python3.7/dist-packages/sklearn/utils/deprecation.py:87: FutureWarning: Function get_feature_names is deprecated; get_feature_names is deprecated in 1.0 and will be removed in 1.2. Please use get_feature_names_out instead. warnings.warn(msg, category=FutureWarning)
Out[ ]:
['x0', 'x1', 'x2', 'x0^2', 'x0 x1', 'x0 x2', 'x1^2', 'x1 x2', 'x2^2']
In [ ]:
test_poly = poly.transform(test_input)
3. 다중 회귀 모델 훈련하기¶
In [ ]:
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))
0.9903183436982124 0.9714559911594132
테스트 세트 점수는 높아지지 않았지만 과소적합 문제는 해결됨
- 특성을 3제곱, 4제곱 항까지 추가한 경우
In [ ]:
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)
(42, 55)
In [ ]:
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))
0.9999999999991096 -144.40579242335605
훈련 세트 점수는 1에 가까워졌지만 테스트 세트 점수가 음수가 되어서 과대적합 상태가 됨
4. 규제¶
- regularization
- 머신러닝 모델이 훈련 세트를 너무 과도하게 학습하지 못하도록 훼방하는 것
- 즉, 모델이 훈련 세트에 과대적합하지 않도록 만드는 것
- 선형 회귀 모델의 경우 : 특성에 곱해지는 계수(기울기)의 크기를 작게 만드는 일
In [ ]:
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_poly)
train_scaled = ss.transform(train_poly)
test_scaled = ss.transform(test_poly)
릿지 회귀¶
앞서 준비한 train_scaled 데이터로 릿지 모델을 훈련
In [ ]:
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))
0.9896101671037343 0.9790693977615397
테스트 세트 점수가 정상으로 돌아왔다.
릿지와 라쏘 모델은 alpha 매개변수로 규제의 양을 임의로 조절할 수 있다. alpha 값이 크면 규제 강도가 세지므로 계수 값을 더 줄이고 조금 더 과소적합되도록 유도한다.
적절한 alpha 값 찾기¶
- alpha 값에 대한 R²값의 그래프를 그려보기
- 훈련 세트와 테스트 세트의 점수가 가장 가까운 지점이 최적의 alpha 값이 됨
In [ ]:
import matplotlib.pyplot as plt
# alpha 값을 바꿀 때마다 결과를 저장할 리스트
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(10^-1=0.1)
적절한 alpha 값으로 다시 훈련¶
In [ ]:
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))
0.9903815817570366 0.9827976465386927
라쏘 회귀¶
In [ ]:
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))
0.989789897208096 0.9800593698421883
적절한 alpha 값 찾기¶
- alpha 값에 대한 R²값의 그래프를 그려보기
- 훈련 세트와 테스트 세트의 점수가 가장 가까운 지점이 최적의 alpha 값이 됨
In [ ]:
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()
/usr/local/lib/python3.7/dist-packages/sklearn/linear_model/_coordinate_descent.py:648: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 1.878e+04, tolerance: 5.183e+02 coef_, l1_reg, l2_reg, X, y, max_iter, tol, rng, random, positive /usr/local/lib/python3.7/dist-packages/sklearn/linear_model/_coordinate_descent.py:648: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 1.297e+04, tolerance: 5.183e+02 coef_, l1_reg, l2_reg, X, y, max_iter, tol, rng, random, positive
- 왼쪽 : 훈련 세트와 테스트 세트의 점수 차이가 아주 큼 -> 과대 적합
- 오른쪽 : 훈련 세트와 테스트 세트의 점수가 모두 낮아짐 -> 과소 적합
라쏘 모델의 적절한 alpha 값 = 1(10^1=10)
적절한 alpha 값으로 다시 훈련¶
In [ ]:
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.9888067471131867 0.9824470598706695
라쏘 모델의 계수가 0인 갯수¶
In [ ]:
print(np.sum(lasso.coef_ == 0))
40
55개의 특성 중에 40개의 특성이 계수가 0이라고 나왔다.
이것은 라쏘 모델이 사용한 특성이 15개 밖에 되지 않는다는 의미다.
이런 특징 때문에 라쏘 모델을 유용한 특성을 골라내는 용도로도 사용할 수 있다.
In [ ]:
'ML DL' 카테고리의 다른 글
[ML] 4-2 확률적 경사 하강법 (0) | 2022.01.08 |
---|---|
[ML] 4-1 로지스틱 회귀 (0) | 2022.01.08 |
[ML] 3-2 선형 회귀 (0) | 2022.01.08 |
[ML] 3-1 K-최근접 이웃 회귀 (0) | 2022.01.08 |
[ML] 2-2 데이터 전처리 (0) | 2022.01.08 |
Comments