[ 핸즈 온 머신러닝 2판 ] Polynomial Regression과 Learning Curve란?
어제보다 나은 사람이 되기

걱정보단 실행을, 그러나 계획적으로

Box World 자세히보기

AI/Hands-On Machine Learning 2판

[ 핸즈 온 머신러닝 2판 ] Polynomial Regression과 Learning Curve란?

Box형 2020. 9. 29. 14:01
반응형

 "먼저 행동으로 옮기고 나서 말하라"

- 스티븐 스필버그 -

4.3 Polynomial Regression(다항 회귀)

 Polynomial Regression은 비선형(non-linear) 데이터를 학습하는데 선형 모델을 사용할 수 있게 해줍니다. 다시 말해서 모델이란 것은 데이터를 대표하는 것인데 어떻게 선형 모델이 비선형 데이터를 대표할 수 있게 되는 것일까요? 우선 간단한 이차방정식으로 데이터를 생성해보겠습니다. 

m = 100
X = 6 * np.random.rand(m, 1) - 3 // rand : 0~1의 균일분포 표준 정규분포 난수를 생성
y = 0.5 * X**2 + X + 2 + np.random.randn(m, 1) // randn : 가우시안 표준정규분포 난수를 생성

 

생성된 데이터

 선형 모델은 분명 위 데이터에 적합하지 않을 것입니다. 하지만 sklearn의 PolynomialFeatures를 사용하여 Training data를 변환시키면 적용이 가능합니다. 

from sklearn.preprocessing import PolynomialFeatures
poly_features = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly_features.fit_transform(X)
X[0]
>> array([-0.75275929])
X_poly[0]
>> array([-0.75275929,  0.56664654])

 그렇다면 Polynomial Regression은 어떻게 데이터를 변환하는걸까요? 앞서 우리가 생성한 데이터를 기준으로 생각해보자면, feature가 하나이므로 결과값을 예측할 때는 다음과 같은 식을 사용해볼 수 있습니다.

$$Y = AX+b (A는 가중치입니다.)$$

 그런데 Polynomial Regression에서는 Input data $X$를 제곱하여 이것을 새로운 feature로 추가합니다. 즉 변환후 우리는 $X$ 그리고  $X^2$ 이렇게 두개의 feature를 지니는 셈이 되는 것이죠 그렇게 해서 우리가 학습시키게 될 모델은 다음과 같습니다. 

$$Y = A_1X + A_2X^2 + b$$

 앞서 Polynomial Regression을 이용하면 선형 모델에 비선형 데이터를 학습 시킬 수 있음을 언급하였습니다. 머신러닝이 어려우신 분들의 이해를 돕기 위해 쉽게 설명드리자면, 아래 식을 보시면 차수가 올라간 것을 보실 수 있는데요 바로 이 차수가 높아지면서 비선형 데이터에 선형 모델이 fit할 수 있게 되는 것입니다.

 이제 확장된 Training data에 Linear regression을 적용해보겠습니다.

//Linear Regression 적용
lin_reg = LinearRegression()
lin_reg.fit(X_poly, y)
lin_reg.intercept_, lin_reg.coef_

// 데이터 시각화
X_new=np.linspace(-3, 3, 100).reshape(100, 1) // -3~3 사이 100개의 수를 가지는 매트릭스 생성
X_new_poly = poly_features.transform(X_new) // 데이터 확장
y_new = lin_reg.predict(X_new_poly)
plt.plot(X, y, "b.")
plt.plot(X_new, y_new, "r-", linewidth=2, label="Predictions")
plt.xlabel("$x_1$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.legend(loc="upper left", fontsize=14)
plt.axis([-3, 3, 0, 10])
save_fig("quadratic_predictions_plot")
plt.show()

 Polynomial Regression의 또 다른 특징은 기존 데이터의 feature가 여러개일 때 feature 간의 관계를 찾을 수 있습니다. 예를 들어 두개의 feature $a$,$b$가 있고, degree = 3으로 설정하여 PolynomialFeatures를 적용하면 $a^3, a^2, b^3, b^2$뿐 아니라 $ab,a^2b,ab^2$과 같은 항들도 feature로 추가하게 됩니다.

 다만 이 과정에서 feature의 수가 엄청나게 증가할 수 있기 때문에 이 점은 주의하셔야 합니다.

 

 

 

 

 


4.4 학습곡선(Learning Curve)

 우선 Learning Curve가 무엇인지 배우기 전에, Polynomial Regression에 대한 얘기를 좀 더 해보면서 Learning Curve가 어떻게 사용될 수 있는지도 함께 배워보겠습니다.

 Polynomial Regression을 통해 degree가 올라가게 되면 모델은 Training data에 더 fit해집니다. 다음 그래프는 300차와 2차 Polynomial Regression 그리고 단순 Linear Regression 모델 세 개를 비교하는데, 300차가 가장 구불구불하면서 fit한 모습을 보여주고 있습니다. 

 참고로 여기서 Polynomial Regression 모델이 300차라는 것은 $Y = AX+b$이던 모델을 $Y = A_1X + ... + A_300X^300 + b$으로 확장한 것을 의미합니다.

from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

for style, width, degree in (("g-", 1, 300), ("b--", 2, 2), ("r-+", 2, 1)):
    polybig_features = PolynomialFeatures(degree=degree, include_bias=False)
    std_scaler = StandardScaler()
    lin_reg = LinearRegression()
    polynomial_regression = Pipeline([
            ("poly_features", polybig_features),
            ("std_scaler", std_scaler),
            ("lin_reg", lin_reg),
        ])
    polynomial_regression.fit(X, y)
    y_newbig = polynomial_regression.predict(X_new)
    plt.plot(X_new, y_newbig, style, label=str(degree), linewidth=width)

plt.plot(X, y, "b.", linewidth=3)
plt.legend(loc="upper left")
plt.xlabel("$x_1$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([-3, 3, 0, 10])
save_fig("high_degree_polynomials_plot")
plt.show()

 그리고 위 300차 모델은 Training data에 Overfit되어있습니다. 반면 1차 모델은 Underfit되어 있고, 가장 적합한 건 셋 중 2차 모델일 것입니다. 그렇다면 다른 데이터를 사용할 때 얼마나 복잡한 모델을 사용해야할지, 확장된 데이터가 Overfit 혹은 Underfit되어있는지 어떻게 알 수 있을까요? 여기서 Learning Curve가 등장합니다.


 Learning Curve란 Training set 그리고 Validation set에 대한 모델의 성능을 함수로 나타냅니다. 다음은 단순한 Linear regression에 대한 Learning Curve입니다.

from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

def plot_learning_curves(model, X, y):
    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=10)
    train_errors, val_errors = [], []
    for m in range(1, len(X_train)):
        model.fit(X_train[:m], y_train[:m])
        y_train_predict = model.predict(X_train[:m])
        y_val_predict = model.predict(X_val)
        train_errors.append(mean_squared_error(y_train[:m], y_train_predict))
        val_errors.append(mean_squared_error(y_val, y_val_predict))

    plt.plot(np.sqrt(train_errors), "r-+", linewidth=2, label="train")
    plt.plot(np.sqrt(val_errors), "b-", linewidth=3, label="val")
    plt.legend(loc="upper right", fontsize=14)   # 책에는 없음
    plt.xlabel("Training set size", fontsize=14) # 책에는 없음
    plt.ylabel("RMSE", fontsize=14)              # 책에는 없음
lin_reg = LinearRegression()
plot_learning_curves(lin_reg, X, y)
plt.axis([0, 80, 0, 3])                         # 책에는 없음
save_fig("underfitting_learning_curves_plot")   # 책에는 없음
plt.show()   

  X축은 Training set의 크기에 해당합니다. 즉 Training set의 개수가 0개일 때, 1개 일때, 2개일 때 ... 80개일때까지 반복적으로 학습하여 각 학습에 대한 Cost 값을 함수로 표현한 것입니다.

 그래프를 좀 더 구체적으로 살펴보자면, Training set에 대한 성능의 경우 처음에 데이터가 한 두개일 때는 Cost가 거의 0에 가까우므로 완벽하게 모델이 작동함을 확인할 수 있습니다.

 그러나 데이터가 커질 수록 Noise의 개입이나 데이터가 non-linear한 특성 때문에 모델이 Training set을 완벽하게 학습하는 것이 불가능해지면서 Cost가 점점 커지게 됩니다.

 

 이번엔 Validation set입니다. 이 경우엔 처음 0개부터 시작할 때는 적은 데이터로 모델을 일반화할 수 없기때문에 Cost가 높습니다. 그러나 데이터가 커질 수록 점점 학습해가면서 Cost가 줄어들면서 Training set의 그래프와 가까워집니다.

 이제 동일한 데이터를 10차 Polynomial Regression으로 확장한 후 이에 대한 Learning Curve를 그려보겠습니다.

from sklearn.pipeline import Pipeline

polynomial_regression = Pipeline([
        ("poly_features", PolynomialFeatures(degree=10, include_bias=False)),
        ("lin_reg", LinearRegression()),
    ])

plot_learning_curves(polynomial_regression, X, y)
plt.axis([0, 80, 0, 3])           # 책에는 없음
save_fig("learning_curves_plot")  # 책에는 없음
plt.show()                        # 책에는 없음


왼쪽은 Linear Regression, 오른쪽은 10차 Polynomial Regression

 위 두 그래프의 차이점을 살펴보겠습니다. Polynomial Regression은 Training set의 Cost가 Linear Regression에 비해 현저히 낮습니다. 왜 그럴까요?

 Polynomial regression은 degree가 높아지기 때문에 당연히 주어진 데이터에 더 fit 해지기 때문입니다

 두번째는 Validation set과 Training set 사이에 공간이 있습니다. 이는 Training set에서의 모델 성능이 Validation set의 성능보다 낫다는 말인데,  본래 좋은 모델이라면 Training set에서 뿐아니라 Validation set에서도 동일하게 성능이 좋아야할 것입니다. 

 결론을 짓자면 우리가 사용한 모델은 Overfit 되어있다는 뜻이 됩니다. 이러한 Overfit을 해결하기 위해서는 더 큰 Training set을 사용하면 두 곡선이 가까워지면서 해결되게 됩니다.


 다음 시간에는 regularization이 들어간 Linear Model에 대해 공부해보겠습니다.

긴 글 읽어주셔서 감사합니다. 행복한 하루 보내시길 바랍니다 :)

반응형