본문 바로가기

ML&DL

[머신러닝] K-NN (K-Nearest Neighbors)

  • 현재 데이터와 가장 가까이 있는 데이터들은 무엇일까? 라는 물음에서부터 시작합니다.
  • 현재 데이터를 특정 카테고리로 분류하기 위해, 가장 가까운 데이터 K개를 찾는 방법입니다. 이후 K개의 데이터에서 다수인 카테고리를 현재 데이터의 카테고리로 분류합니다.
  • 만약 짝수인 경우 반반이 나올 수 있기 때문에, K는 주로 홀수로 설정합니다.
  • 아래 그림은 초록별이 어떤 영화 카테고리일지 구분하는 예시입니다. 

  • 이 경우 만약 K=3 이라면, 초록별과 가장 가까운 3개의 데이터는 액션 영화인 파란원 2개, 로맨스 영화인 빨간하트 1개이기 때문에 초록별은 액션 영화로 분류가 됩니다.

K-NN의 장점과 단점은 다음과 같습니다.

 

장점

  • 구현이 쉬우며 이해하기도 직관적입니다. 
  • 숫자로 구분된 속성에 좋은 성능을 보입니다.
  • 별도의 모델 학습이 필요 없습니다 (이런 학습을 lazy learning이라고도 합니다 => 추후 다룰 예정입니다).

단점 

  • 하나의 데이터를 예측 할때마다 전체 데이터와의 거리를 계산하기 때문에, 예측 속도가 느리고 메모리가 많이 사용됩니다. 
  • 주변에 제대로 되지 않은 데이터가 있으면 결과가 전혀 다르게 나올 수 있습니다 (노이즈 데이터에 민감).

 

실제 코드 예제

국민 데이터인 iris를 sklearn에서 불러 예제 코드를 작성해보겠습니다.

보시는 것과 같이 4개의 특성 (꽃받침 길이/너비 sepal length/width, 꽃잎 길이/너비 petal length/width)을 통해 붗꽃 (iris)이 setosa인지, versicolor인지, virginica인지 구분하는 문제입니다.

dataset['data']: 각 붗꽃의 특성

dataset['target']: setosa - 0, versicolor - 1, virginica - 2

 

 

1. 데이터를 불러온 뒤, sklearn의 tran_test_split을 통해 train, test 데이터를 나눠줍니다. 

예제에서는 train 데이터 80%, test 데이터 20%로 설정을 하였습니다.

random_state는 22 (임의 숫자)로 설정하여 나눠지는 데이터를 항상 동일하게 해주었습니다.

from sklearn.datasets import load_iris
dataset = load_iris()

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(dataset['data'], dataset['target'], test_size = 0.2, random_state=22)

 

다음으론 sklearn.neighbors에서 KNeighborsClassifier를 불러와줍니다.

knn = KNeighborsClassifier, 주변 탐색 데이터는 3으로 설정한 뒤에 knn.fit을 통해 train을 시켜줍시다.

train이 끝났으면, 성능을 측정하기 위해 knn.score로 test 데이터를 입력해줍니다.

from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(x_train, y_train)

accuracy = knn.score(x_test, y_test)
print("정확도: {0:.2f}".format(accuracy))

정확도: 0.97

 

 

정확도가 약 97%가 나왔습니다 (짝짝)

 

전체 코드

from sklearn.datasets import load_iris

dataset = load_iris()

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(dataset['data'], dataset['target'], test_size = 0.2, random_state=22)


from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(x_train, y_train)

accuracy = knn.score(x_test, y_test)
print("정확도: {0:.2f}".format(accuracy))

 

추가적인 데이터들을 예측해보고 싶다면 predict()를 사용해주시면 됩니다 (아래 예시의 경우 각각 1, 0을 예측).

knn.predict([[1.5, 2.5, 3.0, 1.2], [5.5, 7.0, 1.5, 3.5]])

array([1, 0])