다시 이음

회귀 분석 - 5 (Polynomial Regression) 본문

AI 일별 공부 정리

회귀 분석 - 5 (Polynomial Regression)

Taeho(Damon) 2021. 8. 16. 18:29

Polynomial Regression(다항회귀)

 

 

안녕하세요.

 

오늘은 회귀분석 유형중에 가장 이해가 어려웠던 다항 회귀분석에 대해 집중해보겠습니다.

 

 

 

선형관계 , 비선형관계 , 단조관계

 

1. 선형관계

 

  •  선형 관계는 일반적으로 기울기 절편 형태 y = mx + b로 작성된 선형 방정식으로 설명됩니다. 독립 변수 x는 가로 축에 표시되고 종속 변수 y는 세로 축에 표시됩니다. 상수 m은 직선의 기울기 또는 가파름입니다. 상수 b는 y 절편이라고하며 선이 세로 축을 교차 할 때 y의 값입니다.
  • 일련의 데이터 점이 완벽하게 선형 인 관계를 갖는 경우 해당 점이 직선을 이룹니다.
  • 단순선형회귀분석, 다중선형회귀분석으로 해결

 

2. 비선형관계

 

  • 선형 관계의 정의에 맞지 않는 두 양 간의 관계를 비선형 관계라고합니다.
  • X 값이 증감과 Y값의 증감에 어떤 패턴도 보이지 않는 경우를 말합니다.
  • 이제 설명할 다항회귀분석을 통해 해결

 

3. 단조관계

 

  • 단조 관계에서 두 변수는 동일한 상대적인 방향으로 이동하는 경향이 있지만 반드시 일정한 비율로 변화하는 것은 아닙니다.
  • 예를들어, 두 변수가 동시에 증가하지만 같은 비율로 증가하지는 않음을 볼 수 있습니다.

 

 

 

비선형관계인 데이터는 어떻게 분석할 수 있을까?

 

 

해결법 중 하나는 기존 선형 회귀에 새로운 속성(attribute)을 추가하는 것입니다.

 

이를 통해 우리는 보다 복잡한 비선형 데이터 셋에 선형 회귀에서 사용하던 테크닉을 똑같이 사용할 수 있습니다.

 

새로 추가하는 속성은 원래 속성 X 값에 로그(log), 지수(exp), 제곱근(square root), 제곱(square) 등을 취하여 변환한 형태가 있습니다.

 

예를 들어 데이터 셋에 속성 X가 하나가 있을 때, 새로운 속성 X의 제곱(X2)을 추가하여 다항식으로 만들어줍니다. 이러한 속성은 파이썬 Scikit-learn의 라이브러리 중 PolynomialFeatures를 사용해서 쉽게 변환할 수 있습니다.

 

그 외에도 다음의 속성들을 새로 추가할 수 있습니다.


– 원래 속성 X
– 다항식 변환 : y = β0 + β1x+ β2x2 + β3x3
– 교호작용(interaction) 속성으로의 변환 : x3 = x1 ㆍ x2
– 기저 확장(Basis Expansion) : 다항 회귀는 속성과 계수의 관계가 선형이고, 다항식의 항은 속성이므로 종종 다중 선형 회귀(multivariate linear regression)의 특별한 케이스로 불리기도 합니다.

 

# 새로운 특성 만들기
from sklearn.preprocessing import PolynomialFeatures

X1 = np.arange(6).reshape(3, 2)
print(X1)

poly = PolynomialFeatures(2) # 숫자는 dgree를 의미
X_poly = poly.fit_transform(X1)

## X_poly: [1, a, b, a^2, ab, b^2]

참고) https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html

 

 

다항 회귀의 차수(degree)와 속성의 개수 관계

 

 

쉽게 생각해서 다항 회귀는 속성을 추가하여 선형 모델을 좀 더 복잡하게 표현할 수 있도록 확장한다고 볼 수 있습니다.

 

다항식의 “차수(degree)”에 따라 추가하는 속성의 개수가 달라집니다.

  • 속성: 1개(a), 차수: 3 —> a^2, a^3 추가
  • 속성: 3개(a, b, c), 차수: 2 —> a^2, b^2, c^2, a*b, b*c, c*a 추가
  • 속성: 3개(a, b, c), 차수: 3 —> a^3, b^3, c^3, a^2*b, a^2*c, b^2*a, b^2*c, c^2*a, c^2*b, abc 추가

차수가 높아지면 새로운 속성도 기하급수적으로 늘어나 계산 시간이 오래걸리고 과적합(overfitting) 문제가 생긴다.

따라서 보통 2차식 또는 3차식을 사용합니다.

 

아래는 차수가 늘어남에 따라 다항 회귀식이 어떻게 그려지는지 시각적으로 보여줍니다.

 

 

위에서 다항회귀분석에 대해서 이론적인 부분을 보았습니다.

 

아래에서는 다항회귀분석을 파이썬에서 구현하는 코드를 살펴볼게요.

 

 

from IPython.display import display, HTML
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = (5,5)

# 다항회귀모델도 결국 다중선형회귀모델로 변형하여 모델을 만들 수 있는 선형모델입니다.
def PolynomialRegression(degree=2, **kwargs):
    return make_pipeline(PolynomialFeatures(degree), 
                         LinearRegression(**kwargs))

#kwargs = keyword argument의 줄임말

polynomial_degrees = [1, 3, 4, 6, 10, 20]
train_r2s = []
test_r2s = []

for degree in polynomial_degrees:
    model = PolynomialRegression(degree)
    print(f'Degree={degree}')
    
    model.fit(X_train, y_train)
    train_r2 = model.score(X_train, y_train)
    test_r2 = model.score(X_test, y_test)
    display(HTML(f'<b style="color: blue">train R2 {train_r2:.2f}</b>'))
    display(HTML(f'<b style="color: red">test R2 {test_r2:.2f}</b>'))

    plt.scatter(X_train, y_train, color='blue', alpha=0.5)
    plt.scatter(X_test, y_test, color='red', alpha=0.5)
    

    x_domain = np.linspace(X.min(), X.max())
    curve = model.predict(x_domain)
    plt.plot(x_domain, curve, color='blue')
    plt.axis([-2., 2.0, -0.5, 0.5])
    plt.show()
    display(HTML('<hr/>'))
    
    train_r2s.append(train_r2)
    test_r2s.append(test_r2)

 

 

위의 코드를 실행하면 아래의 그래프가 차수(dgree)가 늘어감에 따라서 과적합되는 과정을 보여줍니다.

또한 train(파란색), test(분홍색) 데이터에 각각 R2값을 적용하여 보여줍니다.

 

결과로는 아래 보이듯이 dgree(차수)가 높아질 수록 과적합이 되는 것을 볼 수 있고, train r2값은 점점 높아지지만 test r2값은 높아지다가 급격히 떨어지는 것을 확인할 수 있습니다.

 

 

결과 그래프(왼쪽 dgree=4, 오른쪽 dgree=20)

 

 

아래는 추가적으로 다항회귀분석을 시각화하는 코드입니다.

 

랜덤 데이터를 생성하는 것부터 같이 보시죠.

import numpy as np

def make_data(N, err=1.0, rseed=1):
    # randomly sample the data
    rng = np.random.RandomState(rseed)
    X = rng.rand(N, 1) ** 2
    y = 10 - 1. / (X.ravel() + 0.1)
    if err > 0:
        y += err * rng.randn(N)
    return X, y

X, y = make_data(40)

 

 

1) 차수에 따른 그래프 변화를 하나의 그래프로 시각화

%matplotlib inline
import matplotlib.pyplot as plt
import seaborn; seaborn.set()  # plot formatting

X_test = np.linspace(-0.1, 1.1, 500)[:, None]

plt.scatter(X.ravel(), y, color='black')
axis = plt.axis()
for degree in [1, 3, 5]:
    y_test = PolynomialRegression(degree).fit(X, y).predict(X_test)
    plt.plot(X_test.ravel(), y_test, label='degree={0}'.format(degree))
plt.xlim(-0.1, 1.0)
plt.ylim(-2, 12)
plt.legend(loc='best');

 

 

2)  특정 데이터 및 모델에 대한 유효성 검사 곡선을 시각화

  • 모델, 데이터, 매개변수 이름 및 탐색할 범위가 주어지면 이 함수는 범위 전체에서 훈련 점수와 검증 점수를 모두 자동으로 계산합니다.
  • 이 시각화를 통해서 최적의 dgree를 확인할 수 있습니다.
from sklearn.learning_curve import validation_curve
degree = np.arange(0, 21)
train_score, val_score = validation_curve(PolynomialRegression(), X, y,
                                          'polynomialfeatures__degree', degree, cv=7)

plt.plot(degree, np.median(train_score, 1), color='blue', label='training score')
plt.plot(degree, np.median(val_score, 1), color='red', label='validation score')
plt.legend(loc='best')
plt.ylim(0, 1)
plt.xlabel('degree')
plt.ylabel('score');