UOMOP

k-최근접 이웃 model의 문제점 본문

Ai/ML

k-최근접 이웃 model의 문제점

Happy PinGu 2022. 1. 25. 13:38

k-최근접 이웃 모델에는 한가지 대표적인 문제점이 있다.

 

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_absolute_error
from sklearn.neighbors import KNeighborsRegressor
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]
     )

perch_length = perch_length.reshape(-1, 1)  # input 세트를 2차원 배열로 

train_input, test_input, train_target, test_target = train_test_split(perch_length, 
                                                               perch_weight, random_state = 42)
# 학습/검증 데이터 분리

knr = KNeighborsRegressor()          # 학습 모델 호출
knr.n_neighbors = 3                  # 최근접 이웃 갯수 초기화
knr.fit(train_input, train_target)   # 학습

print("50cm의 아주 큰 농어의 무게를 예측해본 결과 {}이 나왔다.".format(knr.predict([[50]])))
50cm의 아주 큰 농어의 무게를 예측해본 결과 [1033.33333333]이 나왔다.
50cm의 농어의 무게를 3-최근접 이웃 회귀 모델로 예측 해본 결과 1033.333g이 나왔다.
과연 이 결과는 신뢰할만한가?

 

distances, indexes = knr.kneighbors([[50]])
print("길이가 50일 때 최근접한 3개의 접의 길이 : {}".format(distances))
print("길이가 50일 때 최근접한 3개의 접의 인덱스 : {}".format(indexes))
길이가 50일 때 최근접한 3개의 접의 길이 : [[6. 7. 7.]]
길이가 50일 때 최근접한 3개의 접의 인덱스 : [[34 8 14]]
plt.scatter(train_input, train_target)
plt.scatter(train_input[indexes], train_target[indexes], marker = "D", color = "r")
plt.scatter(50, knr.predict([[50]]), marker = "^", color = "y")
plt.xlabel("length")
plt.ylabel("weight")
plt.show()
노란 세모는 50cm 농어
빨간 마름모는 노란 세모에 최근접한 점 3개

만약 길이가 100cm인 농어의 무게를 예측하면 어떤 결과가 나올지 확인해보자

 

distances, indexes = knr.kneighbors([[100]])
print("길이가 100일 때 최근접한 3개의 접의 길이 : {}".format(distances))
print("길이가 100일 때 최근접한 3개의 접의 인덱스 : {}".format(indexes))
길이가 100일 때 최근접한 3개의 접의 길이 : [[56. 57. 57.]]
길이가 100일 때 최근접한 3개의 접의 인덱스 : [[34 8 14]]
plt.scatter(train_input, train_target)
plt.scatter(train_input[indexes], train_target[indexes], marker = "D", color = "r")
plt.scatter(100, knr.predict([[100]]), marker = "^", color = "y")
plt.xlabel("length")
plt.ylabel("weight")
plt.show()
print("100cm의 아주 큰 농어의 무게를 예측해본 결과 {}이 나왔다.".format(knr.predict([[100]])))
다음과 같이 크기가 100cm인 농어의 무게를 예측해도 1033.333g이 나온 것을 확인할 수 있다.

다음과 같은 상황으로 보아,
         "k-최근접 이웃 모델은 훈련 세트 범위 밖의 샘플에 대한 예측이 힘들다."는 것을 알 수 있다.

이와 같은 한계를 극복하기 위해 "선형 회귀" 모델을 알아보자.
Comments