K-최근접 이웃 (K-Nearest Neighbors, K-NN)
- 분류(Classification)와 회귀(Regression) 를 모두 지원한다.
- 예측하려는 데이터와 input 데이터들 간의 거리를 측정해 가장 가까운 K개의 데이터셋의 레이블을 참조해 분류/예측한다.
- 학습시 단순히 input 데이터들을 저장만 하며 예측 시점에 거리를 계산한다.
- 학습은 빠르지만 예측시 시간이 많이 걸린다.
- K-NN에서 K는 새로운 데이터포인트를 분류할때 확인할 데이터 포인트의 개수를 지정하는 하이퍼파라미터
- K를 1로 하면 파란색, K를 3으로 하면 주황색 으로 분류한다.
- K가 너무 작으면 과적합(Overfitting)이 일어나고 K가 너무 크면 성능이 나빠진다. (Underfitting).
주요 하이퍼 파라미터
- 이웃 수
- n_neighbors = K
- K가 작을 수록 모델이 복잡해져 과적합이 일어나고 너무 크면 단순해져 성능이 나빠진다.
- n_neighbors는 Feature수의 제곱근 정도를 지정할 때 성능이 좋은 것으로 알려져 있다.
- 거리 재는 방법
- p=2: 유클리디안 거리(Euclidean distance - 기본값)
- p=1: 맨하탄 거리(Manhattan distance)
유클리디안 거리(Euclidean_distance)
맨하탄 거리 (Manhattan distance)
요약
- K-NN은 이해하기 쉬운 모델이며 튜닝할 하이퍼파라미터의 수가 적어 빠르게 만들 수있다.
- K-NN은 서비스할 모델을 구현할때 보다는 복잡한 알고리즘을 적용해 보기 전에 확인용 또는 base line을 잡기 위한 모델로 사용한다.
- 훈련세트가 너무 큰 경우(Feature나 관측치의 개수가 많은 경우) 거리를 계산하는 양이 늘어나 예측이 느려진다.
- Feature간의 값의 단위가 다르면 작은 단위의 Feature에 영향을 많이 받게 되므로 전처리로 Scaling작업이 필요하다.
- Feature가 너무 많은 경우와 대부분의 값이 0으로 구성된(희소-sparse) 데이터셋에서 성능이 아주 나쁘다
위스콘신 유방암 데이터를 이용한 암환자분류
K값 변화에 따른 성능 평가
- malignant: 악성
- benign : 양성
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data,
cancer.target,
stratify=cancer.target)
# feature scaling (각 feature(컬럼)간의 단위(범위)를 맞춰준다.)
# Train set으로 fit, 새로운데이터(X_test, new data)의 scaling을 train set에 맞춰서 한다.
from sklearn.preprocessing import StandardScaler#, MinMaxScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) #fit(X_train), tranform(X_train)
X_test_scaled = scaler.transform(X_test)
#KNN
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
k_param = range(1,11) #k값을 1 ~ 10 변경하면서 성능을 체크
train_acc_list = []
test_acc_list = []
for k in k_param:
knn = KNeighborsClassifier(n_neighbors=k)
# 모델 학습
knn.fit(X_train_scaled, y_train)
# 예측 및 검증
pred_train = knn.predict(X_train_scaled)
pred_test = knn.predict(X_test_scaled)
# 성능점수를 list에 추가
train_acc_list.append(accuracy_score(y_train, pred_train))
test_acc_list.append(accuracy_score(y_test, pred_test))
dic = {
'k':k_param,
'Train 정확도':train_acc_list,
'Test 정확도':test_acc_list
}
acc_df = pd.DataFrame(dic)
acc_df
import matplotlib.pyplot as plt
acc_df2 = acc_df.set_index('k')
acc_df2 = acc_df2.sort_index(ascending=False)
acc_df2.plot(figsize=(7,7))
# plt.plot(acc_df2.index, acc_df2['Train 정확도'])
# plt.plot(acc_df2.index, acc_df2['Test 정확도'])
plt.xlabel('K값-모델의 복잡도')
plt.show()
knn_clf = KNeighborsClassifier(n_neighbors=7)
knn_clf.fit(X_train_scaled, y_train)
p_train = knn_clf.predict(X_train_scaled)
p_test = knn_clf.predict(X_test_scaled)
accuracy_score(p_train, y_train), accuracy_score(p_test, y_test)
(0.9765258215962441, 0.9790209790209791)
파이프라인(scaling, knn), gridsearchcv (가장 성능좋은 k수 찾기.)
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
('scaler', StandardScaler()),
('knn', KNeighborsClassifier())
])
param_grid = {
"knn__n_neighbors":range(1,11),
"knn__p":[1,2]
}
gs = GridSearchCV(pipeline,
param_grid=param_grid,
cv=5)
# KNeighborsClassifier(n_neighbors=5, p=2)
#베스트 모델 조회
best_model = gs.best_estimator_
#학습
best_model.fit(X_train_scaled, y_train)
#예측 검증
pred_train = best_model.predict(X_train_scaled)
pred_test = best_model.predict(X_test_scaled)
accuracy_score(pred_train, y_train), accuracy_score(pred_test, y_test)
(0.9788732394366197, 0.972027972027972)
accuracy_score(y_train, gs.predict(X_train_scaled))
0.9788732394366197
728x90
반응형
'Data Analysis & ML > Machine Learning' 카테고리의 다른 글
[Machine Learning][머신러닝] Decision Tree(결정트리)와 RandomForest(랜덤포레스트) (0) | 2020.09.02 |
---|---|
[Machine Learning][머신러닝][지도학습] SVM(Support Vector Machine) (0) | 2020.09.01 |
[Machine Learning][머신러닝] 과적합과 해결방법(그리드서치/파이프라인) (0) | 2020.08.31 |
[Machine Learning][머신러닝] Classification(분류) 평가지표 (0) | 2020.08.28 |
[Machine Learning][머신러닝] 데이터 전처리(범주형/연속형) (5) | 2020.08.27 |