[혼공머신] 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개의 댓글

관련 채용 정보