본문 바로가기
AI/Experiment

04. 다항 회귀( Polynomial Regression )

by _S0_H2_ 2020. 5. 14.
728x90
반응형

다항 회귀란?

비선형 데이터를 학습하는데 선형 모델을 사용하는데, 

각 특성의 거듭제곱을 새로운 특성으로 추가하고, 이 확장된 특성을 포함한 데이터셋에 선형 모델을 훈련시키는 것이다.

 

예시로 1차 선형 회귀와 다항 회귀가 어떻게 다른지 살펴보자.

계절마다의 에어컨 가격 트렌드를 살펴보자.
파란색의 선은 에어컨 가격의 절대적 트렌드이며, 실제 가격은 이 트렌드를 따른다.

x가 1일 때 여름 -> 가장 높은 가격에 팔림
x가 3일 때 겨울 -> 가장 낮은 가격에 팔림
%matplotlib inline

import numpy as np
import pylab as pl

# 사인 곡선
def data(size):
    x = np.linspace(0, 4.5, size)
    y = 2 * np.sin(x * 1.5)
    return(x, y)

# 사인 곡선 + 랜덤값
def sample(size):
    x = np.linspace(0, 4.5, size)
    y = 2 * np.sin(x * 1.5) + pl.randn(x.size)
    return (x,y)
    
    
pl.clf()
data_x, data_y = data(50)
pl.plot(data_x, data_y)

x, y = sample(50)
pl.plot(x, y, 'k.')

위는 인위적으로 그려진 데이터이지만 처음 마주하는 데이터는 패턴을 한눈에 파악하기 어렵다.

아마도  원본 데이터는 다음과 같을 것이다.

이 점들의 패턴을 어떻게 파악할 수 있을까?

 

우선, 직선으로 살펴보자. ( 1차 선형회귀 )

from sklearn.linear_model import LinearRegression

def fit_polynomial(x, y, degree):
    model = LinearRegression()
    model.fit(np.vander(x, degree + 1), y)
    return model

def apply_polynomial(model, x):
    degree = model.coef_.size - 1
    y = model.predict(np.vander(x, degree + 1))
    return y
    
model = fit_polynomial(x, y, 1)
p_y = apply_polynomial(model, x)

pl.plot(x, y, 'k.')
pl.plot(x, p_y,'g')

직선과 데이터들을 보았을 때, 원 데이터가 가지고 있는 패턴을 너무 많이 생략하였다.

이 선을 해석한다면, 시간이 갈수록 가격은 떨어진다가 된다.

 

하지만 원래 의도한 가격 그래프는 시간에 따라 가격이 떨어지는 것을 표현한 것이 아니라 계절에 따라 가격이 변화하는 것이다.

 

따라서 직선으로만 데이터의 패턴을 파악하면, 데이터의 실제 패턴을 오해할 수 있다.

 

따라서 데이터의 트렌드를 직선이 아닌 곡선으로 가정하고자 한다.

= 1차식이 아닌 다항식이라고 규정하고 선을 긋자!

 

Vander 함수 설명
더보기

제곱 수를 만들어주는 간편한 함수이다.

x = np.array([1,2,3])
print(np.vander(x, 4))

# 결과 
[[ 1 1 1 1]
 [ 8 4 2 1]
 [27 9 3 1]]

 마지막 열은 무조건 1이고 직전의 열은 내가 설정한 숫자들이다.

zzz = np.array([2,4,5])
print (np.vander(zzz,5))

# 결과
[[ 16   8   4   2   1]
 [256  64  16   4   1]
 [625 125  25   5   1]]

 

그렇다면  polynomial 다항식을 사용하여 그래프를 그려보자.

 

def fit_polynomial(x, y, degree):
    model = LinearRegression()
    # np.vander(x, degree+1)은 지정된 x를 1부터 시작해서 x의 N승까지 행렬로 표현해서 입력한 것이다.
    model.fit(np.vander(x, degree + 1), y)
    return model

# 8차 다항식의 모델을 만들자
model = fit_polynomial(x, y, 8)
p_y = apply_polynomial(model, x)
pl.plot(x, y, 'k.')
pl.plot(x, p_y,'g')

 

선형 그래프와 동시에 그려보면 다음과 같다 !

아무래도 곡선으로 표현한 것이 대표성을 더 띈다고 할 수 있다.

 

 

 

 

728x90
반응형