준비하는 대학생

[기계학습] KNN 분석 (분류 및 회귀) 본문

Programming/Machine learning

[기계학습] KNN 분석 (분류 및 회귀)

Bangii 2023. 4. 6. 18:58

KNN(K-Nearest Neighbors) 이란?

KNN 알고리즘은 이름에서도 알 수 있듯이 가장 가까운 이웃을 찾아 분류하는 방법입니다. KNN은 새로운 데이터 포인트를 가장 가까운 'K개'의 이웃에 따라 분류하는데, 이웃의 범주 중 가장 많은 수를 가진 범주로 새로운 데이터 포인트를 분류합니다.

KNN 알고리즘의 주요 단계는 다음과 같습니다.

  1. K값 설정
  2. 데이터 포인트 간 거리 측정
  3. 새로운 데이터 포인트와 가장 가까운 K개의 이웃 찾기
  4. 다수결로 새로운 데이터 포인트의 클래스 결정

Python을 사용한 KNN 분류

먼저 필요한 라이브러리를 설치하고 가져옵니다.

!pip install numpy pandas matplotlib scikit-learn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix

데이터셋 로딩 및 전처리

이 예제에서는 붓꽃 데이터셋(Iris dataset)을 사용하겠습니다. 데이터를 불러오고, 학습 데이터와 테스트 데이터로 분할합니다.

from sklearn.datasets import load_iris

iris = load_iris()
X = iris.data
y = iris.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2023)
  • X: 독립 변수 데이터셋
  • y: 종속 변수 데이터셋
  • test_size: 테스트 데이터셋의 비율. 여기서는 전체 데이터의 30%를 테스트 데이터로 사용합니다.
  • random_state: 데이터 분할 시 랜덤 시드 값을 설정합니다. 동일한 시드 값이 사용되면 동일한 분할 결과가 생성됩니다.

KNN 모델 훈련 및 예측

KNeighborsClassifier를 이용하여 KNN 모델을 생성하고, 훈련 데이터를 사용해 모델을 훈련시킵니다. 이후 테스트 데이터를 사용하여 예측을 수행합니다.

k = 3
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
  • n_neighbors: 가장 가까운 이웃의 수, 여기서는 3입니다.

모델 성능 평가

분류 리포트와 혼동 행렬을 이용하여 모델의 성능을 평가합니다.

print("Classification Report:")
print(classification_report(y_test, y_pred))

print("Confusion Matrix:")
print(confusion_matrix(y_test, y_pred))
Classification Report:
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        17
           1       0.94      1.00      0.97        17
           2       1.00      0.91      0.95        11

    accuracy                           0.98        45
   macro avg       0.98      0.97      0.97        45
weighted avg       0.98      0.98      0.98        45

Confusion Matrix:
[[17  0  0]
 [ 0 17  0]
 [ 0  1 10]]

Classification Report

classification_report는 precision, recall, f1-score, 그리고 support를 표시합니다. 이 예에서는 3개의 클래스(0, 1, 2)에 대한 결과가 표시되어 있습니다.

  • Precision: 각 클래스별로 정밀도를 확인할 수 있습니다. 클래스 0은 1.00, 클래스 1은 0.94, 클래스 2는 1.00입니다. 이는 모델이 클래스 0과 2의 경우에는 완벽하게 예측했으며, 클래스 1의 경우에는 약 94%의 정밀도를 보였음을 의미합니다.
  • Recall: 각 클래스별로 재현율을 확인할 수 있습니다. 클래스 0은 1.00, 클래스 1은 1.00, 클래스 2는 0.91입니다. 이는 모델이 클래스 0과 1의 경우에는 실제 해당 클래스의 모든 샘플을 정확하게 예측했으며, 클래스 2의 경우에는 약 91%의 재현율을 보였음을 의미합니다.
  • F1-score: 각 클래스별로 F1 스코어를 확인할 수 있습니다. 클래스 0은 1.00, 클래스 1은 0.97, 클래스 2는 0.95입니다. F1 스코어는 정밀도와 재현율의 조화 평균이므로, 이 값이 높을수록 모델의 성능이 좋다고 판단할 수 있습니다.
  • Support: 각 클래스별로 테스트 데이터셋에 포함된 샘플 수를 나타냅니다. 클래스 0은 17개, 클래스 1은 17개, 클래스 2는 11개의 샘플이 테스트 데이터셋에 포함되어 있습니다.

Confusion Matrix

Confusion Matrix는 모델의 예측 결과와 실제 결과를 비교하는 표입니다. 행은 실제 클래스를, 열은 예측된 클래스를 나타냅니다.

  • 대각선 요소(17, 17, 10)는 각 클래스별로 모델이 올바르게 분류한 샘플의 개수입니다.
  • 이 경우, 클래스 0은 모두 올바르게 분류되었고, 클래스 1은 하나의 샘플이 클래스 2로 잘못 분류되었습니다. 클래스 2의 경우 모든 샘플이 올바르게 분류되었습니다.

최종적으로, 이 모델은 전체적으로 높은 정확도(98%)를 보이며, 각 클래스별 성능도 대체로 높은 수준입니다

K값에 따른 성능 변화 확인

K값을 변경하면서 모델의 성능을 비교해 보겠습니다. K값을 1부터 15까지 변경하며 오차를 계산하고 시각화해 봅시다.

error_rate = []

for i in range(1, 16):
    knn_i = KNeighborsClassifier(n_neighbors=i)
    knn_i.fit(X_train, y_train)
    y_pred_i = knn_i.predict(X_test)
    error_rate.append(np.mean(y_pred_i != y_test))

plt.figure(figsize=(10, 6))
plt.plot(range(1, 16), error_rate, marker='o', linestyle='dashed', markersize=8, markerfacecolor='red')
plt.title("Error Rate vs. K Value")
plt.xlabel("K Value")
plt.ylabel("Error Rate")
plt.show()

위의 코드를 실행하면 K값에 따른 오차를 시각화한 그래프가 생성됩니다. 그래프를 통해 최적의 K값을 찾을 수 있으며, 해당 K값을 이용해 새로운 KNN 모델을 생성하여 예측을 수행할 수 있습니다.

오차율 결과를 보면 다음과 같이 해석할 수 있습니다.

  • K값이 1부터 6까지의 경우 오차율이 약 2.22%입니다. 이는 K값이 작을 때 모델이 상당히 정확하게 예측함을 나타냅니다.
  • K값이 7부터 15까지의 경우 오차율이 0%로 나타납니다. 이는 이 범위의 K값에서 모델이 완벽하게 예측했다는 것을 의미합니다.

이 결과를 토대로, 최적의 K값을 선택하는 것이 중요합니다. 여기서는 K값이 7 이상일 때 오차율이 0%로 최적의 성능을 보이므로, K값을 7 또는 그 이상의 값으로 설정하여 모델을 구축하는 것이 좋습니다.

그러나, 실제 상황에서는 오차율이 0%인 경우가 드물며, 이는 데이터셋의 특성이나 노이즈 등으로 인해 다양한 오차율이 나타납니다. 이러한 경우, 오차율이 가장 낮은 지점을 찾아 최적의 K값으로 설정합니다. 또한, 모델의 복잡성과 일반화 성능 간의 균형을 고려하여 K값을 선택해야 합니다. K값이 너무 작으면 과적합(overfitting)이 발생할 가능성이 높아지며, 너무 크면 모델이 과소적합(underfitting)될 수 있습니다.

KNN 회귀

KNN 회귀는 KNN 분류와 비슷한 원리로 작동하지만, 예측하고자 하는 값이 연속적인 수치일 때 사용됩니다. KNN 회귀에서는 새로운 데이터 포인트의 값을 가장 가까운 'K개'의 이웃 값의 평균으로 예측합니다.

Python을 사용한 KNN 회귀

먼저 필요한 라이브러리를 설치하고 가져옵니다.

!pip install numpy pandas matplotlib scikit-learn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error, r2_score

데이터셋 로딩 및 전처리

이 예제에서는 보스턴 주택 가격 데이터셋(Boston Housing dataset)을 사용하겠습니다. 데이터를 불러오고, 학습 데이터와 테스트 데이터로 분할합니다.

from sklearn.datasets import fetch_openml

boston = fetch_openml(name='Boston', version=1, as_frame=True)
X = boston.data
y = boston.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2023)

KNN 회귀 모델 훈련 및 예측

KNeighborsRegressor를 이용하여 KNN 회귀 모델을 생성하고, 훈련 데이터를 사용해 모델을 훈련시킵니다. 이후 테스트 데이터를 사용하여 예측을 수행합니다.

k = 3
knn_regressor = KNeighborsRegressor(n_neighbors=k)
knn_regressor.fit(X_train, y_train)
y_pred = knn_regressor.predict(X_test)

모델 성능 평가

평균 제곱 오차(Mean Squared Error, MSE)와 결정 계수(R-squared)를 이용하여 모델의 성능을 평가합니다.

print("Mean Squared Error:", mean_squared_error(y_test, y_pred))
print("R-squared:", r2_score(y_test, y_pred))
Mean Squared Error: 46.483742690058484
R-squared: 0.49006128345164135

모델 성능 평가 결과를 해석하는 방법은 다음과 같습니다.

  1. Mean Squared Error (MSE) MSE는 예측값과 실제값의 차이를 제곱한 값들의 평균입니다. MSE 값이 작을수록 예측 정확도가 높다고 판단할 수 있습니다. 이 예에서 MSE는 46.48입니다. 이 값을 이용해 모델의 성능을 다른 모델들과 비교할 수 있으며, 낮은 MSE 값을 가진 모델이 더 성능이 좋다고 판단할 수 있습니다.
  2. R-squared (결정 계수) R-squared는 회귀 모델의 설명력을 나타내는 지표입니다. R-squared 값은 0부터 1 사이의 값을 가지며, 1에 가까울수록 모델이 데이터를 잘 설명한다고 판단할 수 있습니다. 이 예에서 R-squared 값은 0.49입니다. 이는 모델이 전체 변동의 약 49%를 설명할 수 있다는 것을 의미합니다. 더 높은 R-squared 값을 가진 모델을 찾거나, 데이터 전처리 및 변수 선택을 개선하여 모델의 성능을 높일 수 있습니다.

최종적으로 이 KNN 회귀 모델의 성능은 MSE 값이 46.48, R-squared 값이 0.49로 평가되었습니다. 이를 바탕으로 모델의 성능을 개선하거나, 다른 회귀 알고리즘을 적용하여 비교해 볼 수 있습니다.

K값에 따른 성능 변화 확인

K값을 변경하면서 회귀 모델의 성능을 비교해 보겠습니다. K값을 1부터 15까지 변경하며 오차를 계산하고 시각화해 봅시다.

mse_values = []

for i in range(1, 16):
    knn_i = KNeighborsRegressor(n_neighbors=i)
    knn_i.fit(X_train, y_train)
    y_pred_i = knn_i.predict(X_test)
    mse_values.append(mean_squared_error(y_test, y_pred_i))

plt.figure(figsize=(10, 6))
plt.plot(range(1, 16), mse_values, marker='o', linestyle='dashed', markersize=8, markerfacecolor='red')
plt.title("Mean Squared Error vs. K Value")
plt.xlabel("K Value")
plt.ylabel("Mean Squared Error")
plt.show()

이 결과를 통해 알 수 있는 것은 다음과 같습니다.

  1. k값이 증가함에 따라 MSE 값이 감소하다가 어느 지점에서 다시 증가하는 추세를 보입니다. 이를 통해 적절한 k값을 찾을 수 있습니다.
  2. 이 경우, k = 4일 때 MSE 값이 가장 낮으므로, k = 4가 최적의 k값으로 판단할 수 있습니다. 이 값을 사용해 KNN 회귀 모델을 훈련하면 좋은 성능을 기대할 수 있습니다.

최적의 k값을 찾은 후 해당 k값을 사용하여 모델을 훈련하고 다시 성능을 평가해 보는 것이 좋습니다. 그리고 다양한 하이퍼파라미터를 조절하거나, 데이터 전처리 및 변수 선택을 개선하여 모델의 성능을 높일 수 있습니다.

결론

이렇게 K-Nearest Neighbors (KNN) 알고리즘을 이용하여 데이터를 분류하고 회귀하는 방법을 Python을 사용해 알아보았습니다. KNN은 간단하면서도 효과적인 분류 및 회귀 알고리즘이며, 다양한 데이터셋에서 사용될 수 있습니다. 

Comments