라일락 꽃이 피는 날

[빅분기 실기] K-최근접 이웃법 (KNN) 본문

데이터 분석/빅데이터 분석 기사

[빅분기 실기] K-최근접 이웃법 (KNN)

eunki 2022. 6. 16. 18:49
728x90

K-최근접 이웃법 (K-Nearest Neighbor)

각 데이터들 간의 거리를 측정하여 가까운 k개의 다른 데이터의 레이블을 참조하여 분류하는 방법

주로 유클리디안 거리 계산법 또는 민코브스키 방법을 사용

모델 기반 알고리즘이 아닌 케이스 기반 알고리즘이므로 입력되는 데이터에 따라 결과와 성능이 크게 다름

 

k 값이 작을수록 정교한 분류와 예측이 가능하지만 과대적합(overfitting) 문제 발생

k 값이 클수록 정확도나 성능지표가 좋지 않을 수 있고 과소적합(underfitting) 문제 발생

최적의 k는 일반적으로 3~10 범위 내에서 찾는다.

 

 

[주요 하이퍼파라미터]

- n_neighbors : 1에 가까울수록 과대적합, 클수록 과소적합 발생 (default = 5)

- metric : 거리 측정 방법 (default = minkowski)

 

 

 

 


 

Part 1. 분류 (Classification)

 

1. 분석 데이터 준비

import pandas as pd

# 유방암 예측 분류 데이터
data1=pd.read_csv('breast-cancer-wisconsin.csv', encoding='utf-8')

X=data1[data1.columns[1:10]]
y=data1[["Class"]]

 

 

 

1-2. train-test 데이터셋 나누기

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test=train_test_split(X, y, stratify=y, random_state=42)

 

 

 

1-3. Min-Max 정규화

from sklearn.preprocessing import MinMaxScaler

scaler=MinMaxScaler()
scaler.fit(X_train) 

X_scaled_train=scaler.transform(X_train)
X_scaled_test=scaler.transform(X_test)

 

 

 

 

2. 기본모델 적용

 

2-1. 훈련 데이터

from sklearn.neighbors import KNeighborsClassifier

model=KNeighborsClassifier()
model.fit(X_scaled_train, y_train)

pred_train=model.predict(X_scaled_train)
model.score(X_scaled_train, y_train)  # 0.984375

 

 

 

① 오차행렬 (confusion matrix)

from sklearn.metrics import confusion_matrix

confusion_train=confusion_matrix(y_train, pred_train)
print("훈련데이터 오차행렬:\n", confusion_train)

정상(0) 중 2명이 오분류, 환자(1) 중 6명이 오분류되었다.

 

 

 

② 분류예측 레포트 (classification report)

from sklearn.metrics import classification_report

cfreport_train=classification_report(y_train, pred_train)
print("분류예측 레포트:\n", cfreport_train)

정밀도(precision) = 0.98, 재현율(recall) = 0.99

 

 

 

2-2. 테스트 데이터

pred_test=model.predict(X_scaled_test)
model.score(X_scaled_test, y_test)  # 0.9532163742690059

 

 

 

① 오차행렬 (confusion matrix)

confusion_test=confusion_matrix(y_test, pred_test)
print("테스트데이터 오차행렬:\n", confusion_test)

정상(0) 중 5명이 오분류, 환자(1) 중 3명이 오분류되었다.

 

 

 

② 분류예측 레포트 (classification report)

cfreport_test=classification_report(y_test, pred_test)
print("분류예측 레포트:\n", cfreport_test)

정밀도(precision) = 0.97, 재현율(recall) = 0.95

 

 

 

 

3. 하이퍼파라미터 튜닝

 

3-1. Grid Search

param_grid={'n_neighbors': [1, 3, 5, 7, 9, 11]}

n_neighbors 값을 6개로 설정하고 그리드 탐색을 진행한다.

 

 

 

from sklearn.model_selection import GridSearchCV

grid_search=GridSearchCV(KNeighborsClassifier(), param_grid, cv=5)
grid_search.fit(X_scaled_train, y_train)

 

 

 

print("Best Parameter: {}".format(grid_search.best_params_))
print("Best Score: {:.4f}".format(grid_search.best_score_))
print("TestSet Score: {:.4f}".format(grid_search.score(X_scaled_test, y_test)))

최적의 n_neighbors는 3으로, 이때 훈련 데이터의 정확도는 98.2%, 테스트 데이터의 정확도는 95.3% 이다.

 

 

 

3-2. Random Search

from scipy.stats import randint

param_distribs = {'n_neighbors': randint(low=1, high=20)}

랜덤 탐색을 위해 n_neighbors를 1~20 사이의 범위에서 20번(n_iter) 무작위 추출하는 방식을 적용한다.

 

 

 

from sklearn.model_selection import RandomizedSearchCV

random_search=RandomizedSearchCV(KNeighborsClassifier(), 
                                 param_distributions=param_distribs, n_iter=20, cv=5)
random_search.fit(X_scaled_train, y_train)

 

 

 

print("Best Parameter: {}".format(random_search.best_params_))
print("Best Score: {:.4f}".format(random_search.best_score_))
print("TestSet Score: {:.4f}".format(random_search.score(X_scaled_test, y_test)))

최적의 n_neighbors는 3으로, 이때 훈련 데이터의 정확도는 98.2%, 테스트 데이터의 정확도는 95.3% 이다.

 

 

 

 


 

 

Part 2. 회귀 (Regression)

 

1. 분석 데이터 준비

# 주택 가격 데이터
data2=pd.read_csv('house_price.csv', encoding='utf-8')

X=data2[data2.columns[1:5]]
y=data2[["house_value"]]

 

 

 

1-2. train-test 데이터셋 나누기

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test=train_test_split(X, y, random_state=42)

 

 

 

1-3. Min-Max 정규화

from sklearn.preprocessing import MinMaxScaler

scaler=MinMaxScaler()
scaler.fit(X_train)

X_scaled_train=scaler.transform(X_train)
X_scaled_test=scaler.transform(X_test)

 

 

 

 

2. 기본모델 적용

 

2-1. 훈련 데이터

from sklearn.neighbors import KNeighborsRegressor

model=KNeighborsRegressor()
model.fit(X_scaled_train, y_train)

pred_train=model.predict(X_scaled_train)
model.score(X_scaled_train, y_train)  # 0.6804607237174459

회귀에서 정확도는 R^2(설명력, 결정계수) 이다.

0과 1사이의 값을 가지며, 높을수록 실제 y 값과 모델의 예측 y 값이 일치하는 좋은 모델이다.

 

 

 

2-2. 테스트 데이터

pred_test=model.predict(X_scaled_test)
model.score(X_scaled_test, y_test)  # 0.5541889571372401

 

 

 

① RMSE (Root Mean Squared Error)

import numpy as np
from sklearn.metrics import mean_squared_error 

MSE_train = mean_squared_error(y_train, pred_train)
MSE_test = mean_squared_error(y_test, pred_test)

print("훈련   데이터 RMSE:", np.sqrt(MSE_train))
print("테스트 데이터 RMSE:", np.sqrt(MSE_test))

RMSE 오차가 작을수록 좋은 모델이다.

 

 

 

 

3. 하이퍼파라미터 튜닝

 

3-1. Grid Search

param_grid={'n_neighbors': [1, 3, 5, 7, 9, 11]}

n_neighbors 값을 6개로 설정하고 그리드 탐색을 진행한다.

 

 

 

from sklearn.model_selection import GridSearchCV

grid_search=GridSearchCV(KNeighborsRegressor(), param_grid, cv=5)
grid_search.fit(X_scaled_train, y_train)

 

 

 

print("Best Parameter: {}".format(grid_search.best_params_))
print("Best Score: {:.4f}".format(grid_search.best_score_))
print("TestSet Score: {:.4f}".format(grid_search.score(X_scaled_test, y_test)))

최적의 n_neighbors는 11로, 이때 훈련 데이터의 정확도는 56.4%, 테스트 데이터의 정확도는 58.8% 이다.

 

 

 

3-2. Random Search

from scipy.stats import randint

param_distribs = {'n_neighbors': randint(low=1, high=20)}

랜덤 탐색을 위해 n_neighbors를 1~20 사이의 범위에서 20번(n_iter) 무작위 추출하는 방식을 적용한다.

 

 

 

from sklearn.model_selection import RandomizedSearchCV

random_search=RandomizedSearchCV(KNeighborsRegressor(), 
                                 param_distributions=param_distribs, n_iter=50, cv=5)
random_search.fit(X_scaled_train, y_train)

 

 

 

print("Best Parameter: {}".format(random_search.best_params_))
print("Best Score: {:.4f}".format(random_search.best_score_))
print("TestSet Score: {:.4f}".format(random_search.score(X_scaled_test, y_test)))

최적의 n_neighbors는 19로, 이때 훈련 데이터의 정확도는 57.8%, 테스트 데이터의 정확도는 60.0% 이다.

728x90