본문 바로가기
데이터관련공부/Machine Learning

K-Nearest Neighbours (KNN) (Classfication)

by 자유롭고 싶은 키털트 2023. 3. 9.

머신러닝에서 분류 (Classfication) 는 지도 학습 유형 중 하나이다. 데이터의 여러 속성을 기반으로 개별 클래스 세트로 범주화 혹은 분류 하는 방법으로 이해할 수 있다. 지난번에 정리한 Rgression 의 경우, Target Variable 가 숫자형 변수 였다면, Classficiation 의 경우 범주형 변수 라고 할 수 있다.

 

대표적인 예로, 어떤 특정 변수를 갖는 채무자들의 채무 이행여부, 불이행 여부 (Default or not) 를 예측하는 것이 Classficiation 알고리즘이 적용된 예이다. 혹은, 각 환자들에 대해 어떤 약을 투여할지 예측 (Drug A, B, C?) 하는 것도 Classficiation 의 예이다. 

 

머신러닝의 대표적인 분류 알고리즘은 하기와 같다:

  • Decision Tree
  • Naive Bayes
  • K-Nearest Neighbours 
  • Logistics Regression
  • Neural Networks
  • Support Vector Machines (SVM)

오늘은 그 중, 대표적으로 K-Nearest Neighbours 에 대해 정리해 보겠다. 

 

K-Nearest Neighbours 은 분류 (Classfication) 알고리즘 중 하나이다. 가장 인근의 이웃 데이터에 대한 유사도를 기준으로 분류하는 원리이다. 

 

여기서 K 의 의미는 가장 가까운 이웃의 개수이다. K 를 5로 설정했다고 가정하고, 신규 데이터 A 의 클래스를 결정해야 할 때, A 와 가장 가까운 5개의 이웃 데이터가 속해 있는 클래스를 보고 가장 많은 클래스로 A 도 분류 하게 되는 원리이다.

 

K 를 어떻게 설정했느냐에 따라 모델의 신뢰도와 결과가 달라지므로 이 부분이 매우 중요하다고 할 수 있다. 

 

하기 스크린샷을 예시로 살펴보자

 

- 각 고객 id 별로 custcat 을 총 1부터 4 로 분류하고자 한다.

- 8번째 데이터를 1~4 중 분류하고자 할 때, K 값을 5로 가정하였다.

- 현재 제일 주요 변수로 고려하고 있는 age 와 income 을 기준으로 각 datapoint 를 plot 을 하고 기존 데이터를 색깔로 분류하였다. (하기 스크린샷 오른쪽 그래프)

- 이 때, 8번째 데이터 (물음표?) 의 경우, 주변에 있는 5개 (K값) 의 데이터 중 2개가 class 4, 3개가 class 3 이므로 3으로 분류가 될 것이다. 

 

유사도(Similarity), 즉, 데이터간 거리 (Distance) 는 어떻게 측정할까? 다른 방법도 물론 존재하나, 대표적인 방법으로 Euclidean distance 를 들 수 있다. 

https://en.wikipedia.org/wiki/Euclidean_distance

 

  • 하기 예시에서 age, income, education 의 속성이 다른 customer 1 과 customer 2 가 있을 때, 두 고객의 Distance 는 하기와 같이 구할 수 있다. 

 

그렇다면, 가장 중요한 K 값은 어떻게 결정할 수 있을까?

 

  • K값이 너무 작으면 모델 과적합의 가능성이 있다. 즉, 일반화 되기가 어려우며, 모델에 사용된 표본 외 데이터에 적용이 어려울 수 있다. 
  • 그러나 K값이 너무 크면 역시 모델이 과도하게 일반화 될 가능성이 있기 때문에 문제이다. 
  • 그러므로 훈련 데이터 (Train data) 를 바탕으로 만들어진 모델을 테스트 데이터 (Test data) 로 예측의 정확도 및 성능을 테스트 하되 K값을 늘리면서 정확도를 비교해 가며 가장 최적의 K 값을 찾아야 한다. 하기 예시의 경우, K 가 4일 때 가장 정확도가 높음을 알 수 있다. 

 

 

파이썬으로 실행하기 위한 코드 예시는 다음과 같다. 

 

# 학습, 테스트 데이터셋 구분
 
from sklearn.model_selection import train_test_split
 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4# test data 는 20%
 
print('Train set: ', X_train.shape, y_train.shape)
 
print('Test set: ', X_test.shape, y_test.shape)
 
# KNN 라이브러리 임포트
 
from sklearn.neighbors import KNeighborsClassifier
 
# KNeighborsClassifier 모듈을 가져오고, 힋,ㅂ 데이터로 모델 학습 후 neigh 객체에 할당
 
neigh = KNeighborsClassifier(n_neighbors = k).fit(X_train, y_train)
neigh
 
# 테스트 데이터를 입력하여 예측값 구하고 yhat 객체에 할당
 
yhat = neigh.predict(X_test)
 
yhat[0:5]
 
# 정확도 평가를 위해 metrics.accuracy_score 모듈 임포트
 
from sklearn import metrics
 
print("Test set Accuracy: ", metrics.accuracy_score(y_test, yhat))
 
cs

 

만약 Feature 마다 상대적인 데이터 크기가 달라 예측값에 대한 영향력에 차이가 난다면, 이를 비슷한 수준으로 만들기 위한 작업이 필요한데 이를 정규화 혹은 피처 스케일링 이라고 한다. 하기는 피처 스케일링의 예시이다.

 

Scikitlearn 의 StandardScaler() 를 이용하였는데, MinMaxScaler 도 있는 듯 하다. 이렇게 피처 스케일링 작업을 거친 후, 학습+ 테스트 데이터로 분할하는 과정을 거쳐서 모델을 학습 시키면 된다. 

 

# Column 을 보고 feature (일종의 독립변수) 와 y 를 할당해보자. 
# 우리 데이터셋에서는 custcat (customer category) 열을 예측하고자 하므로
# custcat 은 y, 나머지 열(=피처, 변수) 은 X 이다.
 
df.columns
 
'''
Index(['region', 'tenure', 'age', 'marital', 'address', 'income', 'ed',
       'employ', 'retire', 'gender', 'reside', 'custcat'],
      dtype='object')
'''
 
= df[['region''tenure''age''marital''address''income''ed''employ''retire''gender''reside']].values  # numpy array 로 변경해 주기 위해 .values 를 붙임
X[0:5]
 
= df['custcat'].values # numpy array 로 변경해 주기 위해 .values 를 붙임
y[0:5]
 
 
# Feature X 에 대해 Normalization 을 위해 preprocessing.StandardSaler() 를 이용한다. 
# X 의 각 feature 의 데이터가 비슷한 수준으로 변경 되었음을 알 수 있다.
 
from sklearn import preprocessing
 
= preprocessing.StandardScaler().fit(X).transform(X.astype(float))
X[0:5]
 
 
'''
array([[-0.02696767, -1.055125  ,  0.18450456,  1.0100505 , -0.25303431,
        -0.12650641,  1.0877526 , -0.5941226 , -0.22207644, -1.03459817,
        -0.23065004],
       [ 1.19883553, -1.14880563, -0.69181243,  1.0100505 , -0.4514148 ,
         0.54644972,  1.9062271 , -0.5941226 , -0.22207644, -1.03459817,
         2.55666158],
       [ 1.19883553,  1.52109247,  0.82182601,  1.0100505 ,  1.23481934,
         0.35951747, -1.36767088,  1.78752803, -0.22207644,  0.96655883,
        -0.23065004],
       [-0.02696767, -0.11831864, -0.69181243, -0.9900495 ,  0.04453642,
        -0.41625141, -0.54919639, -1.09029981, -0.22207644,  0.96655883,
        -0.92747794],
       [-0.02696767, -0.58672182, -0.93080797,  1.0100505 , -0.25303431,
        -0.44429125, -1.36767088, -0.89182893, -0.22207644, -1.03459817,
         1.16300577]])
'''
cs

 

 

본 포스팅은 Coursera 강의와 정보문화사의 파이썬 딥러닝 머신러닝 입문 책을 참고하였습니다. 

 

https://www.coursera.org/learn/machine-learning-with-python/lecture/s0q1d/k-nearest-neighbours

 

https://www.coursera.org/lecture/machine-learning-with-python/k-nearest-neighbours-s0q1d

 

www.coursera.org

 

반응형