[혼공머신] k-최근접 이웃 회귀

강민우·2022년 1월 13일
0
post-thumbnail

[혼자 공부하는 머신러닝+딥러닝] 책에 기반한 정리글입니다.
전체 소스코드는 아래 Github 링크에서 확인할 수 있습니다.

Github 링크

0. 개요

이번 포스팅에서는 회귀를 이해하고 k-최근접 이웃 회귀에 대해 알아본다.

회귀
임의의 어떤 숫자를 예측하는 문제
k-최근접 이웃 회귀
예측하려는 샘플에 가장 가까운 샘플 k개르 선택하여 이 수치들의 평균을 구해 샘플의 수치 예측

1. 훈련 데이터 준비하기

이 책에서는 농어의 길이와 무게가 주어지고, 샘플의 길이가 주어졌을 때 무게를 예측할 수 있게 모델을 훈련하려고 한다.

1-1. 데이터의 특성과 타깃 준비하기

import numpy as np

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

1-2. 산점도를 그려 데이터 형태 확인하기

import matplotlib.pyplot as plt

plt.scatter(perch_length, perch_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()


길이와 무게가 비례함을 확인했다.

1-3. 훈련 세트와 테스트 세트로 나누기

train_test_split() 메서드로 쉽게 나눌 수 있다.
reshape() 메서드로, 쉽게 2차원 배열로 만들 수 있다.

from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight)

#사이킷런에 사용할 훈련 세트는 2차원 배열이어야함
train_input = train_input.reshape(-1, 1) #-1은 원소의 갯수만큼을 의미
test_input = test_input.reshape(-1, 1)

훈련 세트와 테스트 세트 모두 2차원 배열로 만들어준다.

2. 결정계수와 과대적합·과소적합 찾기

회귀에서는 분류와 다르게 샘플을 정확한 값으로 예측하는 것은 거의 불가능해, 결정계수(R^2)로 표현한다.
R^2 = 1 - ( (타깃-예측)^2의 합 / (타깃-평균)^2 의 합 )

결정계수
모델이 타깃의 평균정도를 예측하는 수준이라면 0에 가까워진다.
예측이 타깃에 아주 가까워지면 1에 가까운 값이 된다.

2-1. 훈련세트와 테스트세트의 결정계수 확인하기

from sklearn.neighbors import KNeighborsRegressor

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

print(knr.score(train_input, train_target)) #훈련 세트의 결정계수
print(knr.score(test_input, test_target)) #테스트 세트의 결정계수

출력
0.9793744047335786 (훈련 세트의 결정계수)
0.9589006077491291 (테스트 세트의 결정계수)

from sklearn.metrics import mean_absolute_error

test_prediction = knr.predict(test_input)

mae = mean_absolute_error(test_prediction, test_target)
print(mae) #예측이 평균적으로 이정도로 타겟값과 다름

출력 29.84
평균 약 29.84g 정도 타깃값과 예측값이 다르다.

2-2. 이 모델은 과대·과소적합인가?

과대적합

  • 결정계수가 훈련세트는 좋지만 테스트세트의 점수가 나쁜 경우 과대적합
  • 새로운 샘플의 예측이 잘 맞지 않는다.

과소적합

  • 훈련세트보다 테스트세트의 결정계수가 높거나 둘다 낮은 경우 과소적합
  • 모델이 단순해 잘 훈련되지 않은 경우이다.
  • 이웃의 갯수 k를 줄여 모델을 복잡하게 만들 수 있다.

위의 결과에서, 훈련세트가 테스트세트의 결정계수보다 높고 테스트세트의 점수가 나쁘지 않으므로 잘 훈련된 모델이다.

knr.n_neighbors = 3

이렇게 이웃의 갯수를 줄여 학습할 수 있다.

3. k-최근접 이웃의 한계

가장 가까운 이웃샘플들의 평균으로 샘플을 예측하기 때문에
샘플이 훈련 세트의 범위를 벗어나면 엉뚱한 값을 예측한다.
이를 위해 선형 회귀를 이용한다.

profile
어제보다 성장한 오늘

0개의 댓글