k-초근접이웃 (K-Nearest-Neighbor)
2023. 7. 24. 21:19ㆍ'혼자 공부하는 머신러닝' 실습
k-nearest-neighbor algorithm(KNN)은 machine learning 중 지도학습에 속하며,
분류와 회귀에 사용됩니다.
- 지도학습(supervised learning) : 정답을 알려주며 학습시키는 것
- 분류(classification) : 데이터를 특정한 범주 내로 분류하는 것
- 회귀(regression) : 데이터들의 특징을 통해 값을 예측하는 것
- KNN 알고리즘과 같은, 모델을 별도로 구축하지 않아도 되는 모델을 게으른 모델(lazy model)이라고 부르기도 합니다.
KNN 분류(classification)
KNN 분류는 데이터로부터 거리가 가까운 다른 데이터들의 레이블을 'k개' 참조하여 분류하는 알고리즘입니다.
이 알고리즘에서의 hyperparameter는 탐색할 이웃 수 'k'와 거리 측정 방법입니다.
혼자공부하는 머신러닝 01-3
- KNN 알고리즘을 이용해 생선의 길이와 무게에 따라, 해당 생선이 도미인지 방어인지 예측하는 모델 만들기
- 도미 데이터 만들기 (길이 & 무게 기준)
# 첫번째 도미의 무게, 길이가 각각 리스트에 들어가 있습니다.
# feature1 도미 길이
bream_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0,
31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0,
35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0]
# feature2 도미 무게
bream_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0, 500.0,
500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0,
700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0]
- matplotlib을 통한 데이터 산점도 확인
import matplotlib.pyplot as plt
plt.scatter(bream_length, bream_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
- 방어 데이터 만들기 (길이 & 무게 기준)
# 방어
smelt_length = [9.8, 10.5, 10.6, 11.0, 11.2, 11.3, 11.8, 11.8, 12.0, 12.2, 12.4, 13.0, 14.3, 15.0]
smelt_weight = [6.7, 7.5, 7.0, 9.7, 9.8, 8.7, 10.0, 9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9]
- 추가된 방어 데이터 & 도미 데이터 산점도 확인
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show
# matplotlib은 자동으로 두 데이터의 산점도를 구분해서 보여주는 것을 알 수 있습니다
최근접이웃 (K-Nearest-Neighbors) 알고리즘 사용해 도미와 방어 데이터 구분해보기
length = bream_length + smelt_length
weight = bream_weight + smelt_weight
# sklearn 을 사용하려면 데이터를 2차원 리스트 형태로 준비해야해요
# zip() 함수 사용 -> 나열된 리스트 각각에서 원소를 하나씩 꺼내 반환하는 함수
# 리스트 내포 사용
fish_data = [[l,w] for l,w in zip(length, weight)]
- 데이터가 잘 들어갔는지 확인
- 테스트 생선이 도미일때 1, 방어일때 0을 반환할 수 있도록 정답 만들기
- 보통 머신러닝을 통해 두개를 구분하는 경우, 찾으려는 대상을 1로 놓고 아닌 경우를 0으로 설정해요.
# 정답도 fish data 와 같은 2차원 리스트로 만들어줘야합니다.
# 1 * 도미 데이터의 수 / 0 * 도미가 아닌 방어의 수 --> 우리는 도미를 찾을거니까요
fish_target = [1]*35 + [0]*14
- 학습 데이터가 준비되었으므로 사이킷런 패키지에서 KNN클래스 호출
from sklearn.neighbors import KNeighborsClassifier
# 위와 같은 호출 방식이지만 보통은 위의 코드를 씀
import sklearn
model = sklearn.neighbors.KNeighborsClassifier()
knn = KNeighborsClassifier()
- KNN모델 테스트
Question : 모든 데이터를 참고하거나, 많은 데이터를 참고하는 게 더 좋은 성능을 내지 않을까요?
데이터 전체를 매개변수로 지정해버리면 생기는 문제
fish-data 전체 수 49개 중, 도미 수가 35개로 다수이기때문에 어떤 데이터가 들어와도 도미로 예측할 수밖에 없습니다.
-> 이렇게 만들어진 모델은 방어를 분류할 수 없어지므로 이때 해당 모델의 정확도는 0.714정도가 되어버립니다.
( 총 49개의 데이터중 35개만 제대로 분류하므로 35 / 49 => 0.7142857142857143)
KNN에서 가장 가까운 데이터중 몇개를 참고할 것인지는 매개변수로 설정해 정할 수 있습니다. (기본값은 5개)