k-최근접 이웃 회귀

Jaeseok Han·2024년 4월 15일

머신러닝&딥러닝

목록 보기
5/22

지도 학습 알고리즘은 주로 분류와 회귀로 나눠진다.

  • 분류
    샘플을 몇 개의 클래스 중 하나로 분류하는 문제를 다룬다.

  • 회귀
    클래스 중 하나로 분류하는 것이 아니라, 임의의 숫자를 예측하는 문제를 다룬다.

k-최근접 이웃 분류와 회귀 차이

1. k-최근접 이웃 분류

샘플에 가장 가까운 이웃 k개를 선택하여 샘플들의 다수 클래스를 새로운 샘플의 클래스로 예측한다.

k = 3 (k는 이웃의 개수)이라 가정할 때,
X의 클래스의 최근접 이웃이 A가 2개, B가 1개라면 A로 예측한다.

2. k-최근접 이웃 회귀**

분류와 동일하게 최근접 이웃 샘플을 선택하지만, 샘플의 타깃은 클래스가 아닌 임의의 수치이다

k = 3 이라 가정할 때,
X의 클래스의 이웃 샘플의 타깃값이 100, 80, 60인 경우 이를 평균으로 X의 예측 타깃값(80)을 예측한다.

데이터 준비

농어의 길이로 무게를 예측하기 위한 데이터를 사용

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

# 산점도
import matplotlib.pyplot as plt
plt.scatter(perch_length, perch_weight)
plt.xlabel('length')
plt.ylabel('length')
plt.show()


길이가 늘어날수록 무게가 증가하는 그래프를 띈다.

훈련 및 테스트 세트

사이킷런에 사용할 훈련 세트는 2차원 배열이어야 하므로 2차원 배열로 만들어 줘야한다.
넘파이 배열은 크기를 바꿀 수 있는 reshape() 메서드를 제공한다.

1. 2차원 배열

reshape() 인자로 크기와 원소의 개수를 넣어주면 2차원 배열로 만들어주며, 크기에 -1을 지정하면 나머지 원소 개수로 모두 채워준다. (길이를 구하지 않고 사용하는데 용이)

from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight, random_state=42)

# 2차원 배열로 수정
train_input = train_input.reshape(-1, 1)
test_input = test_input.reshape(-1, 1)
print(train_input.shape, test_input.shape)
# 출력 (42, 1) (14, 1)

결정계수

결정계수눈 회귀에서 모델의 성능을 평가하는 지표로 사용된다.
[참고] 결정계수

KNeghborsRegressor()

사이킷런에서 k-최근접 이웃 회귀 알고리즘을 구현한 클래스이다.
fit() 메서드를 사용하여 회귀 모델을 훈련한다.

from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor()
knr.fit(train_input, train_target)
print(knr.score(test_input, test_target))
# 출력 0.992809406101064

평균 절대값 오차

1. mean_absolute_error

skleran.metrics 패키지 에서 mean_absolute_error는 타깃과 예측의 절대값 오차를 평균하여 반환한다.

from sklearn.metrics import mean_absolute_error
# 테스트 세트에 대한 예측을 만든다.
test_prediction = knr.predict(test_input)
print(test_prediction)
# 출력 [  60.    79.6  248.   122.   136.   847.   311.4  183.4  847.   113.  1010.    60.   248.   248. ]

# 테스트 세트에 대한 평균 절대값 오차를 계산
mae = mean_absolute_error(test_target, test_prediction)
print(mae)
# 출력 19.157142857142862

# 훈련한 모델을 사용해 훈련 세트의 절대계수 확인
print(knr.score(train_input, train_target))
# 출력 0.9698823289099254

훈련 세트보다 테스트 세트의 점수가 더 높다(과소적합)

과대적합과 과소적합

1. 과대적합

훈련 세트에서 점수가 높고 테스트 세트에서 점수가 낮으면 훈련 세트에 과대적합되었다고 한다. 훈련 세트에만 적합한 모델로 실전에서 예측을 만들 때 잘 동작하지 않는다.

2. 과소적합

훈련 세트보다 테스트 세트의 점수가 높거나 두 점수 모두 낮으면 훈련 세트에 과소적합되었다고 한다. 모델이 단순하여 훈련 세트에 적절히 훈련되지 않은 경우이다.

print(knr.score(test_input, test_target))
# 출력 0.992809406101064

print(knr.score(train_input, train_target))
# 출력 0.9698823289099254

훈련 세트보다 테스트 세트의 결정계수가 높으므로 과소적합이다.

3. 과대적합과 과소적합 해결방법

과대적합일 경우 모델을 덜 복잡하게 만들어야 하기때문에 k값을 늘려 일반적인 패턴을 따르게 하고,
과소적합일 경우 모델을 복잡하게 만들기 위해서 k값을 줄여 국지적인 패턴에 민감하게한다.

과소적합 해결

이웃의 개수를 줄이면 국지적인 패턴에 민감해며, 반대로 이웃의 개수를 늘리면 일반적인 패턴을 따르게된다.

# 이웃 개수 3으로 설정
knr.n_neighbors = 3
# 모델을 다시 훈련
knr.fit(train_input, train_target)
print(knr.score(train_input, train_target))
# 0.9804899950518966
print(knr.score(test_input, test_target))
# 0.9746459963987609

0개의 댓글