from IPython.core.display import display, HTML
display(HTML("<style>.container { width:1200px !important; }</style>"))
다항회귀 : 회귀가 독립변수의 단항식이 아닌 2차, 3차 방정식과 같은 다항식으로 표현되는 것을 다항회귀.
다항회귀는 선형회귀
from sklearn.preprocessing import PolynomialFeatures
import numpy as np
# 다항식으로 변환한 단항식 생성, [[0,1],[2,3]]의 2X2 행렬 생성
X = np.arange(4).reshape(2,2)
print('일차 단항식 계수 feature:\n',X )
# degree = 2 인 2차 다항식으로 변환하기 위해 PolynomialFeatures를 이용하여 변환
poly = PolynomialFeatures(degree=2)
poly.fit(X)
poly_ftr = poly.transform(X)
print('변환된 2차 다항식 계수 feature:\n', poly_ftr)
일차 단항식 계수 feature: [[0 1] [2 3]] 변환된 2차 다항식 계수 feature: [[1. 0. 1. 0. 0. 1.] [1. 2. 3. 4. 6. 9.]]
3차 다항식 결정값을 구하는 함수 polynomial_func(X) 생성. 즉 임의 회귀식은 결정값 y = 1+ 2x_1 + 3x_1^2 + 4x_2^3
def polynomial_func(X):
y = 1 + 2*X[:,0] + 3*X[:,0]**2 + 4*X[:,1]**3
print(X[:, 0])
print(X[:, 1])
return y
X = np.arange(0,4).reshape(2,2)
print('일차 단항식 계수 feature: \n' ,X)
y = polynomial_func(X)
print('삼차 다항식 결정값: \n', y)
일차 단항식 계수 feature: [[0 1] [2 3]] [0 2] [1 3] 삼차 다항식 결정값: [ 5 125]
3차 다항식 계수의 피처값과 3차 다항식 결정값으로 학습
# 3 차 다항식 변환
poly_ftr = PolynomialFeatures(degree=3).fit_transform(X)
print('3차 다항식 계수 feature: \n',poly_ftr)
from sklearn.linear_model import LinearRegression
# Linear Regression에 3차 다항식 계수 feature와
# 3차 다항식 결정값(y = polynomial_func(X))으로 학습 후 회귀 계수 확인
model = LinearRegression()
model.fit(poly_ftr,y)
print('Polynomial 회귀 계수\n' , np.round(model.coef_, 2))
print('Polynomial 회귀 Shape :', model.coef_.shape)
3차 다항식 계수 feature: [[ 1. 0. 1. 0. 0. 1. 0. 0. 0. 1.] [ 1. 2. 3. 4. 6. 9. 8. 12. 18. 27.]] Polynomial 회귀 계수 [0. 0.18 0.18 0.36 0.54 0.72 0.72 1.08 1.62 2.34] Polynomial 회귀 Shape : (10,)
사이킷런 파이프라인(Pipeline)을 이용하여 3차 다항회귀 학습
사이킷런의 Pipeline 객체는 Feature 엔지니어링 변환과 모델 학습/예측을 순차적으로 결합해줍니다.
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
import numpy as np
def polynomial_func(X):
y = 1 + 2*X[:,0] + 3*X[:,0]**2 + 4*X[:,1]**3
return y
# Pipeline 객체로 Streamline 하게 Polynomial Feature변환과 Linear Regression을 연결
model = Pipeline([('poly', PolynomialFeatures(degree=3)),
('linear', LinearRegression())])
X = np.arange(4).reshape(2,2)
y = polynomial_func(X)
model = model.fit(X, y)
print('Polynomial 회귀 계수\n', np.round(model.named_steps['linear'].coef_, 2))
Polynomial 회귀 계수 [0. 0.18 0.18 0.36 0.54 0.72 0.72 1.08 1.62 2.34]
다항 회귀는 피처의 직선적 관계가 아닌 복잡한 다항 관계를 모델링할 수 있다. 다항식의 차수가 높아질수록 과적합의 문제가 발생
cosine 곡선에 약간의 Noise 변동값을 더하여 실제값 곡선을 만듬
import numpy as np
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
%matplotlib inline
# random 값으로 구성된 X값에 대해 Cosine 변환값을 반환.
def true_fun(X):
return np.cos(1.5 * np.pi * X)
# X는 0 부터 1까지 30개의 random 값을 순서대로 sampling 한 데이타 입니다.
np.random.seed(0)
n_samples = 30
X = np.sort(np.random.rand(n_samples))
# y 값은 cosine 기반의 true_fun() 에서 약간의 Noise 변동값을 더한 값입니다.
y = true_fun(X) + np.random.randn(n_samples) * 0.1
plt.scatter(X, y)
<matplotlib.collections.PathCollection at 0x7fdc9f19b3c8>
예측 결과를 비교할 다항식 차수를 1, 4, 15로 변경하면서 예측 결과 비교
다항식 차수별로 수행한 뒤 cross_val_score() 로 MSE 값을 구해 채수별 예측 성능을 평가 0~1까지 균일하게 구성된 100개의 테스트용 데이터 세트를 이용해 차수별 회귀 예측 곡선을 그린다
plt.figure(figsize=(14, 5))
degrees = [1, 4, 15]
# 다항 회귀의 차수(degree)를 1, 4, 15로 각각 변화시키면서 비교합니다.
for i in range(len(degrees)):
ax = plt.subplot(1, len(degrees), i + 1)
plt.setp(ax, xticks=(), yticks=())
# 개별 degree별로 Polynomial 변환합니다.
polynomial_features = PolynomialFeatures(degree=degrees[i], include_bias=False)
linear_regression = LinearRegression()
pipeline = Pipeline([("polynomial_features", polynomial_features),
("linear_regression", linear_regression)])
pipeline.fit(X.reshape(-1, 1), y)
# 교차 검증으로 다항 회귀를 평가합니다.
scores = cross_val_score(pipeline, X.reshape(-1,1), y,scoring="neg_mean_squared_error", cv=10)
coefficients = pipeline.named_steps['linear_regression'].coef_
print('\nDegree {0} 회귀 계수는 {1} 입니다.'.format(degrees[i], np.round(coefficients),2))
print('Degree {0} MSE 는 {1:.2f} 입니다.'.format(degrees[i] , -1*np.mean(scores)))
# 0 부터 1까지 테스트 데이터 세트를 100개로 나눠 예측을 수행합니다.
# 테스트 데이터 세트에 회귀 예측을 수행하고 예측 곡선과 실제 곡선을 그려서 비교합니다.
X_test = np.linspace(0, 1, 100)
# 예측값 곡선
plt.plot(X_test, pipeline.predict(X_test[:, np.newaxis]), label="Model")
# 실제 값 곡선
plt.plot(X_test, true_fun(X_test), '--', label="True function")
plt.scatter(X, y, edgecolor='b', s=20, label="Samples")
plt.xlabel("x"); plt.ylabel("y"); plt.xlim((0, 1)); plt.ylim((-2, 2)); plt.legend(loc="best")
plt.title("Degree {}\nMSE = {:.2e}(+/- {:.2e})".format(degrees[i], -scores.mean(), scores.std()))
plt.show()
Degree 1 회귀 계수는 [-2.] 입니다. Degree 1 MSE 는 0.41 입니다. Degree 4 회귀 계수는 [ 0. -18. 24. -7.] 입니다. Degree 4 MSE 는 0.04 입니다. Degree 15 회귀 계수는 [-2.98300000e+03 1.03899000e+05 -1.87415100e+06 2.03715130e+07 -1.44872551e+08 7.09311979e+08 -2.47064676e+09 6.24558367e+09 -1.15676035e+10 1.56894317e+10 -1.54005437e+10 1.06456871e+10 -4.91375763e+09 1.35919168e+09 -1.70380199e+08] 입니다. Degree 15 MSE 는 180526263.29 입니다.
편향-분산 트레이드오프¶
위에서 degree 1 은 고편향성을 가졌고, degree 15 는 고분산성을 가졌다. 일반적으로 편향과 분산은 한 쪽이 높으면 한 쪽이 낮아지는 경향이 있다. 즉,편향이 높으면 분산은 낮아지고(과소적합) 반대로 분산이 높으면 편향이 낮아진다(과적합).
편향이 너무 높으면 전체 오류가 높고, 편향을 점점 낮추면 동시에 분산이 높아지고 전체 오류도 낮아진다.
편향을 낮추고 분산을 높이면서 전체 오류가 가장 낮아지는 '골디락스' 지점을 통과하면서 분산을 지속적으로 높이면 전체 오류 값이 오히려 증가하면서 예측 성능이 다시 저하된다.
높은 편향/낮은 분산에서 과소적합되기 쉬우며 낮은 편향/높은 분산에서 과적합되기 쉽다. 편향과 분산이 서로 트레이드오프를 이루면서 오류cost값이 최대로 낮아지는 모델을 구축하는 것이 가장 효율적인 머신러닝 예측 모델을 만드는 방법이다.
'머신러닝' 카테고리의 다른 글
[파이썬 머신러닝] 5장. 로지스틱 회귀, 회귀 트리 (0) | 2021.01.27 |
---|---|
[파이썬 머신러닝] 5장. 규제 선형 모델 - 릿지, 라쏘, 엘라스틱넷 (0) | 2021.01.27 |
[파이썬 머신러닝] 5장. LinearRegression을 이용한 보스턴 주택 가격 예측 (0) | 2021.01.21 |
[파이썬 머신러닝] 4장. 스태킹 앙상블 (0) | 2021.01.20 |
[파이썬 머신러닝] 4장. 신용카드 사기 검출 (0) | 2021.01.19 |