본문 바로가기
AI/머신러닝

[머신러닝] K-최근접 이웃(K-NN) 분류 알고리즘

by snow_white 2022. 4. 11.

분류 (Classification)

K Nearest Neighbors (k-최근접 이웃 분류 알고리즘)

가장 중요한 hyperparameter인 K값은 근처에 참고(reference)할 이웃의 숫자

  • k-최근접 이웃 분류 알고리즘
  • 가장 고전적이고 직관적인 머신러닝 분류 알고리즘
  • 기하학적 거리 분류기
  • 가장 가깝게 위치하는 멤버로 분류하는 방식

  1.  ?  와 가장 가깝게 만나는 이웃들을 지정하여 boundary로 묶음
  2.  ?  가 별 ⭐인지 세모 🔺인지 구분
  3. 이웃하는 데이터의 개수가 홀수인지 짝수인지에 따라 알고리즘 달라진다.
  4. 따라서 k를 몇 개로 지정하느냐에 따라 성능이 달라진다
  5. k가 7이라면 가장 가까운 7개의 모양들의 개수 중 일치하는 개수가 많은 label로 분류
  6. k가 짝수라면 가장 가까운 거리상 비교
  7. k가 홀수라면 가장 가까운 최대 갯수로 비교
  8. k가 1이라면  ? 와 가장 가까운 2개의 🔺로 예측할 것이다.

 

Hyperparameter

머신 학습 결과로 얻어지는 값이 아니라 인간의 경험치로 지정 ⇒ 성능에 직결됨

이 Hyperparameter를 맞춰가는 과정을 모델 튜닝(Art 경지에 오를 수 있다..)

 

 

더미 데이터를 활용한 분류 원리 이해

from sklearn.neighbors import KNeighborsClassifier

 

mnist (손글씨) 데이터셋을 활용한 분류

mnist (손글씨) 데이터셋을 활용하여 0~9까지 분류하는 분류기를 만듭니다.

sklearn.datasets 보다 고해상도 이미지이기 때문에 tensorflow.keras.datasets을 활용합니다.

from tensorflow.keras.datasets import mnist
(x_digit, y_digit), (_, _15) = mnist.load_data()
x_digit, y_digit = x_digit[:5000], y_digit[:5000]
x_digit = x_digit.reshape(-1, 28*28)
x_digit.shape # (5000, 784)

 

mnist (손글씨) 데이터 시각화

w, h = 2, 5
fig, axes = plt.subplots(w, h)
fig.set_size_inches(12, 6)
for i in range(w*h):
    axes[i//h, i%h].imshow(x_digit[i].reshape(-1, 28))
    axes[i//h, i%h].set_title(y_digit[i], fontsize=20)
    axes[i//h, i%h].axis('off')
plt.tight_layout()
plt.show()

 

데이터 셋 분할

학습용(train) 데이터셋과 검증 (혹은 테스트)용 데이터 셋을 분할 합니다.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(x_digit, y_digit, stratify=y_digit, random_state=30, test_size=0.1)
X_train.shape, y_train.shape

 

모델 정의

KNeighborsClassifier를 정의 하고 핵심 hyperparameter 인 n_neighbors를 지정합니다.

임의로 5개의 이웃을 보도록 n_neighbors=5로 지정하겠습니다.

그리고, n_jobs 옵션은 학습에 사용할 코어의 숫자를 지정합니다.

-1로 지정하면, 모든 코어를 사용하도록 합니다.

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5, n_jobs=-1) # k 값 안 주면 디폴트 값 5
# 내가 가지고 있는 CPU가 4개짜리 일 때 -1이면 전부 다 써! 3일 때 3개만 남겨두고 하나만 사용해!

knn # KNeighborsClassifier(n_jobs=-1)

 

학습 (fit)

학습할 데이터는
X_train, y_train => 지도학습은 data와 label이 필요해!

knn.fit(X_train, y_train) # KNeighborsClassifier(n_jobs=-1)

 

예측 (predict)

pred = knn.predict(X_test)
pred
'''
array([6, 2, 0, 5, 4, 1, 3, 4, 7, 0, 8, ...
'''
y_test
'''
array([6, 2, 0, 5, 4, 2, 3, 4, 7, 0, 8, ...
'''
pred == y_test
'''
array([ True,  True,  True,  True,  True, False,  True,  True,  True,
        True,  True, False, 
'''

 

검증 (evaluation)

정확도 (Accuracy) 산출

 

정확도를 검증하는 데에 아래의 1. 방법이 더 좋은 방법이다!

score() 함수는 모든 모델에서 제공하는 함수가 아니기도 하고,
검증 데이터를 가지고 내부적으로 predict를 사용하기 때문에 예측값을 뽑아낸다.
따라서 성능 파악하는 정확하고 대표적인 방법이 1. 이다.

# 1.
(pred == y_test).mean() # 0.938

# 2.score() 이용
knn.score(X_test, y_test) # 0.938

 

최적의 n_neighbors(k) 찾기

for k in range(1, 11):
    knn = KNeighborsClassifier(n_neighbors=k, n_jobs=-1) # -1로 지정해서 모든 CPU로 빨리 계산해줘!
    knn.fit(X_train, y_tarin)
    score = knn.score(X_test, y_test)
    print(f'k:{k}, accuracy: {score*100}')
'''
k:1, accuracy: 95.6
k:2, accuracy: 95.0
k:3, accuracy: 94.6
k:4, accuracy: 93.8
k:5, accuracy: 93.8
k:6, accuracy: 93.4
k:7, accuracy: 93.4
k:8, accuracy: 93.60000000000001
k:9, accuracy: 92.80000000000001
k:10, accuracy: 92.80000000000001
'''

 

Iris 붓꽃 데이터셋을 활용한 실습

  • 필요한 데이터셋 불러오기 (load_iris)
  • 데이터프레임 (DataFrame) 만들기
from sklearn.datasets import load_iris
iris = load_iris()

import pandas as pd
feature = iris['data']
feature_names = iris['feature_names']
label = iris['target']
df = pd.DataFrame(feature, columns=feature_names)
df = pd.DataFrame(iris['data'], columns=iris['feature_names'])

df['target'] = label
df['target'] = iris['target']
df.head()

 

데이터 셋 분할

학습용(train) 데이터셋과 검증 (혹은 테스트)용 데이터 셋을 분할합니다.

X = df.drop('target', axis=1)
y = df['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1234)

# 잘 load가 되었는지 shape를 확인
X_train.shape, y_train.shape # ((120, 4), (120,))
X_test.shape, y_test.shape # ((30, 4), (30,))

# 모델 정의
model = KNeighborsClassifier(n_neighbors=5)

# 학습 (fit)
model.fit(X_train, y_train) # KNeighborsClassifier()

# 예측하기
pred = model.predict(X_test)

# 검증 (evaluation)
(pred==y_test).mean() # 0.9333333333333333

# 최적의 k 값 찾기
for k in range(1, 11):
    knn = KNeighborsClassifier(n_neighbors=k, n_jobs=-1)
    knn.fit(X_train, y_train)
    score = knn.score(X_test, y_test)
    print(f'k:{k}, accuracy: {score*100}')
    
'''
k:1, accuracy: 96.66666666666667
k:2, accuracy: 93.33333333333333
k:3, accuracy: 96.66666666666667
k:4, accuracy: 96.66666666666667
k:5, accuracy: 93.33333333333333
k:6, accuracy: 93.33333333333333
k:7, accuracy: 96.66666666666667
k:8, accuracy: 96.66666666666667
k:9, accuracy: 96.66666666666667
k:10, accuracy: 96.66666666666667
'''

 

댓글