본문 바로가기

머신러닝 & 딥러닝

[혼자 공부하는 머신러닝] 03-2 선형회귀 그리고 다항회귀

<알아두어야 할 키워드>

K최근접 이웃 알고리즘의 한계: 학습데이터 밖의 샘플이 들어오면, return이 학습 데이터에서 벗어나지 못함(이웃에 의존하기 때문)

 

머신러닝 모델은 주기적으로 훈련해야 한다: 시간과 환경이 변하면서 데이터도 바뀌기 때문에 주기적으로 새 훈련 데이터로 모델을 다시 훈련해야 하기 때문 이다.

 

선형회귀 클래스 또한 sklearn 라이브러리에 존재한다.(데이터 트렌드 직선을 찾음)

일반적 선형회귀

모델 기반 학습: 최적의 모델 파라미터(기울기, 절편)을 찾는 알고리즘 (coef_, intercept_ 처럼 기울기, 절편이 모델 파라미터에 속함)

사례 기반 학습: 훈련 세트를 저장한뒤 단순하게 활용하는 것 (K최근접 이웃 알고리즘이 여기에 속함)

 

다항회귀: 직선으로 데이터트렌드를 나타내기 어려운경우, 곡선으로 나타내는것이 유리하다.(2차 방정식 형태)

단, 이때 입력 데이터가 [[10]] 이라면, [[10^2, 10]] 이런 형태로 바꾸어 주어야 정상작동 한다.

 

2차 방정식도 선형 회귀?

보통은 비선형이라고 생각한다 곡선이니깐, BUT 길이^2을 왕길이라고 치환하면, 왕길이와 길이의 선형 관계로 표현할수가 있다. 이런 방정식을 다항식이라 부르며, 다항식을 사용한 선형회귀를 다항 회귀 라고 부른다.

다항회귀를 활용한 데이터 트렌드 분석

 

<유용힌 코드>

# 사이킷런 선형회귀 불러오기
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(train_input, train_target)
lr.coef_    # 기울기
lr.intercept_    # Y 절편    y=ax+b 직선의 방정식 생각하면 편함
plt.plot([15,50], [15*lr.coef_+lr.intercept_, 50*lr.coef_+lr.intercept_])


# 다항회귀 (2차원 방정식)으로 진행하는 법
# 2차원 방정식 이상이므로, **2해주어서 train,test 데이터 형태를 바꾸어 주어여 함을 유의
train_poly = np.column_stack((train_input**2,train_input))
test_poly  = np.column_stack((test_input**2 , test_input))
lr.fit(train_poly, train_target)    # target값은 **2 안해도 됨
print(lr.predict([[50**2, 50]]))    # 쿼리문 던질때도 바꾸어 주어야 함
print(lr.coef_, lr.intercept_)    # y=ax^2 + bx +c

 

 

전체 코드는 아래와 같다

#%% 선형회귀를 활용하여 아무리 큰 샘플을 넣어도 
# 학습 데이터 이상의 값을 측정하지 못하는 K-최근접 이웃 알고리즘의 한계를 극복해보자
import numpy as np
from sklearn.model_selection import train_test_split

#농어의 길이와 무게 입력 받음
perch_length = np.array(
    [8.4, 13.7, 15.0, 16.2, 17.4, 18.0, 18.7, 19.0, 19.6, 20.0,
     21.0, 21.0, 21.0, 21.3, 22.0, 22.0, 22.0, 22.0, 22.0, 22.5,
     22.5, 22.7, 23.0, 23.5, 24.0, 24.0, 24.6, 25.0, 25.6, 26.5,
     27.3, 27.5, 27.5, 27.5, 28.0, 28.7, 30.0, 32.8, 34.5, 35.0,
     36.5, 36.0, 37.0, 37.0, 39.0, 39.0, 39.0, 40.0, 40.0, 40.0,
     40.0, 42.0, 43.0, 43.0, 43.5, 44.0]
     )
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]
     )

train_input, test_input, train_target, test_target = train_test_split(perch_length,perch_weight, random_state=42)
train_input = train_input.reshape(-1,1)
test_input = test_input.reshape(-1,1)




#%% 선형회귀 모델 클래스 생성
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt

lr = LinearRegression()
lr.fit(train_input, train_target)
lr.predict([[50]])

# 직선의 방정식 그려 보기
plt.scatter(train_input, train_target)
plt.plot([15,50], [15*lr.coef_+lr.intercept_, 50*lr.coef_+lr.intercept_])
plt.savefig('선형회귀_직선방정식.png')




#%% 다향회귀 모델을 산포도형태로 그려서 확인해보기
# 3차원 방정식 이상이므로, **2해주어서 train,test 데이터 형태를 바꾸어 주어여 함을 유의
train_poly = np.column_stack((train_input**2,train_input))
test_poly  = np.column_stack((test_input**2 , test_input))

lr.fit(train_poly, train_target)
print(lr.predict([[50**2, 50]]))  

print(lr.coef_, lr.intercept_)
'''
[  1.01433211 -21.55792498] 116.05021078278264    각각 x^2, x^1, x^0에 가중치에 해당함
'''


# %% 3차 방정식을 그림으로 나타내자

point = np.arange(15,50)
plt.scatter(train_input, train_target)
plt.plot(point,1.01*point**2 -21.6*point + 116.05)
plt.scatter([50],[1574], marker='^')
plt.xlabel('length')
plt.xlabel('weight')
plt.savefig('3차원 다항회귀 방정식.png')