자기계발/Python

[빅데이터분석기사] 14 K-최근접이웃법(KNN)

호등 2022. 6. 21. 09:10
반응형

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

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

주로 유클리디안 거리 계산법 또는 민코브스키 방법을 사용한다. (민코브스키 방법이 디폴트)

 

최적의 K수는 일반적으로 3에서 10 범위 내에서 찾으며, K값이 작을수록 정교한 분류와 예측이 가능하다.

K값이 너무 작으면 과대적합 문제가 발생할 수 있으며, 너무 커도 과소적합 문제가 발생할 수 있기 때문에 적절한 K값을 찾는 것이 중요하다. (K값을 찾기 위해 그리드탐색 혹은 랜덤탐색을 적용한다)

 

KNN은 모델기반 알고리즘이 아닌 케이스기반 알고리즘이다. 입력되는 데이터에 따라 결과와 성능이 크게 달라지며, 새로운 데이터를 학습하는 시간이 오래 걸려 실시간 머신러닝이 필요한 분야에는 적합하지 않을 수 있다.

scikit-learn

sklearn.neighbors 안에 KNeighborsClassifier와 KNeighborsRegressor 두 가지가 있다.

Classifier은 레이블(y)이 범주일 경우 분류의 문제에 적용하는 알고리즘,

Regression은 레이블이 숫자일 경우 회귀 문제에 적용하는 알고리즘이다.

 

K에 해당하는 옵션은 'n_neighbors'는 디폴트 값이 'n_neighbors = 5'이다.

거리측정법은 'metric' 옵션인데 'minkowski'가 디폴트 값으로 설정되어 있다.

KNeighborsClassifier와 KNeighborsRegressor의 기본 설정은 모두 동일하다!

 

Part1. 분류(Classification)

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)

sklearn.neighbors에서 KNeighborsClassifier 라이브러리를 불러왔다.

 

기본 설정(n_neighbors=5)로 정확도를 계산해보았더니,

앞 포스팅의 로지스틱회귀모델보다 1.2% 더 좋은 결과를 보여주었따.

 

2) 혼동행렬과 분류예측 레포트

from sklearn.metrics import confusion_matrix

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

from sklearn.metrics import classification_report

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

혼동행렬은 sklearn.metircs에서 confusion_matrix 라이브러리를,

예측분류 레포트는 sklearn.metrics에서 classification_report 라이브러리를 불러왔다.

모델 적용 이후에 하는거니깐, confusion_matrix 안에 (y_train, pred_train)을 넣어준다.

 

이후 똑같이 test 데이터의 혼동행렬과 분류예측 레포트도 확인했다.

 

3) 그리드탐색

#Grid Search
param_grid = {'n_neighbors' : [1, 3, 5, 7, 9, 11]}
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 Scroe: {:.4f}".format(grid_search.best_score_))
print("TestSet Score: {:.4f}".format(grid_search.score(X_scaled_test, y_test)))

그리드탐색에서 하이퍼파라미터인 n_neighbors의 값을 조정하면서 더 좋은 예측 모델을 탐색해보자.

param_grid = {'n_neighbors' : [1, 3, 5, 7, 9 ,11]} 코드처럼 6개의 K값을 넣어주었다.

최적의 n_neighbors = 3, 이때의 정확도는 98.2%가 나왔다.

 

4) 랜덤탐색

#Random Search
from scipy.stats import randint
param_distribs = {'n_neighbors' : randint(low=1, high=20)}

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를 1~20 범위에서 20번(n_iter) 무작위 추출하는 옵션으로 적용해보았다.

분석 결과, 최적의 n_neighbors = 4, 정확도는 98.0%가 나왔다.

 

요 결과는 실행할때마다 조금씩 차이가 존재한다.


Part2. 회귀(Regression)

1) 분석데이터 준비

import pandas as pd 

data2 = pd.read_csv('house_price.csv', encoding='utf=8')
X=data2[data2.columns[1:5]]
y=data2[["house_value"]]

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42)

KNN을 회귀자(regressor) 알고리즘으로 활용하는 예시이다.

주택가격 자료 'house_price.csv' 파일로 실습 시작!

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) 기본모델 적용

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)

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

sklearn.neighbors에서 KNeighborsRegressor 라이브러리를 불러왔다.

회귀에서 정확도는 결정계수(R²)이고, 1에 가까울 수록 좋은 모델로 볼 수 있다.

 

훈련 정확도가 테스트 정확도보다 더 높게 나온 것을 보아서 과대적합 되었다고 판단할 수 있다.

 

#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를 구해보았다.

RMSE 훈련데이터 53,952, 테스트데이터는 63,831로 각각 계산되었고 작을수록 작은 모델이다.

역시나 훈련데이터가 더 좋게 나왔다.

 

이 후 Grid Search나 Random Search로 적당한 K 값을 탐색하는 과정이 있는데 

지금까지 해왔던거랑 똑같아서 생략함.

랜덤탐색 결과로, 그리드탐색으로 내가 지정했던 K값보다 더 큰 K값을 지정하는 것이 좋다는 걸 알 수 있었음  

 

반응형