2 분 소요

❗ 문제점 ❗

길이가 50인 농어의 무게를 예측했을 때, 실제 무게랑 많이 차이가 났다.

🔮 해결책 알아보기

왜 그런 문제가 나타났을까?

1️⃣ 해결책 알아보기

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
import matplotlib.pyplot as plt

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)

knr = KNeighborsRegressor(n_neighbors=3)
knr.fit(train_input, train_target)

print(knr.predict([[50]]))

distance, indexes = knr.kneighbors([[50]])
distance2, indexes2 = knr.kneighbors([[100]])
plt.scatter(train_input, train_target)
plt.scatter(train_input[indexes], train_target[indexes], marker='D')
plt.scatter(train_input[indexes2], train_target[indexes2], marker='d')
plt.scatter(50, 1033, marker='^')
plt.scatter(100, 1033, marker='<')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

download1

앞 장에서 훈련한 방법대로 훈련을 시킨 후, 길이가 50, 100인 농어를 예측해보았더니 1033.33333333이라는 값이 나왔다. 길이가 다르면 예측된 무게도 달라야 하는데,,같은 것을 보니 뭔가 문제가 있는 것은 확실하다.

2️⃣ 해결책

이 문제가 발생한 이유는 k-최근접 이웃 알고리즘 이 갖고 있는 문제이다.

k-최근접 이웃 알고리즘의 경우, 예측하려는 값을 기준으로 주변에 있는 값들의 평균을 구해서 무게를 예측한다. 원래 있던 데이터에서 떨어진 값을 예측해야 된다면, 나오는 무게의 값은 결국 일정하게 될 것이다. 그렇기 때문에 k-최근접 이웃 알고리즘 외의 다른 알고리즘을 사용해야 된다.

🔮 선형 회귀를 통해서 문제 해결하기

1️⃣ 선형 회귀란?

선형 회귀는 널리 사용되는 대표적인 회귀 알고리즘이다. 선형이라는 말에서 알 수 있듯이 어떤 직선을 학습하는 알고리즘이고, 이 직선을 통해서 샘플에 없는 데이터를 예측할 수 있는 것이다.

2️⃣ 문제점 해결하기

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(train_input, train_target)
print(lr.predict([[50]]))

>>> 출력값
[1241.83860323]

선형 회귀는 직선을 통해서 예측한다고 했으므로 직선을 그려본다. 여기서 기울기는 lr.coef_ , y절편은 lr.intercept_ 를 통해서 구한다. 그리고 직선에서의 정의역 부분은 길이 부분이므로 길이에 대한 데이터들이 해당된다.

plt.scatter(train_input, train_target)
plt.plot([15, 50], [15*lr.coef_ + lr.intercept_, 50*lr.coef_+ lr.intercept_])
plt.scatter(50, 1241, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

print(lr.score(train_input, train_target)) #0.939846333997604
print(lr.score(test_input, test_target))   #0.824750312331355

download2

❗ 문제점 ❗

  1. 훈련 세트와 테스트 세트가 점수차이가 많이 난다. 훈련 세트의 점수가 높기 때문에 과대적합되었다고 할 수 있지만 전반적으로 점수가 낮아서 과소적합되었다고 볼 수 있다.

  2. 직선 그래프를 보게 되면 길이가 짧아질 수록 무게가 음수쪽으로 내려가는 것을 확인할 수 있다. 그리고 샘플들을 자세히 보면 일차식 그래프와는 조금 다름을 알 수 있다.

🔮 다항 회귀를 통해서 문제 해결하기

1️⃣ 다항 회귀란?

다항 회귀란 다향식을 사용하여 특성과 타깃 사이의 관계를 나타낸다.

2️⃣ 해결책

2차 방정식 그래프를 그리기 위해서는 길이 2 항이 훈련 세트에 추가되어야 한다.

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_)

>>> 출력값
[1573.98423528]
[  1.01433211 -21.55792498] 116.0502107827827

주의해야 될 점은 예측값의 길이도 제곱을 해주어야 된다는 점

🌗 문제 해결!

point = np.arange(15, 50)
plt.scatter(train_input, train_target)
plt.plot(point, lr.coef_[0] * point ** 2 + lr.coef_[1] * point + lr.intercept_)

plt.scatter(50, 1574, marker = '^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

print(lr.score(train_poly, train_target)) # 0.9706807451768623
print(lr.score(test_poly,test_target))    # 0.9775935108325122

download3

댓글남기기