Search
🗃️

K-NN

생성일
2025/04/08 10:05
태그
데이터마이닝
작성자

K-NN 분류기(범주형 결과)

학습
Lazy learning
모델을 학습하는 단계가 존재하지 않음
비모수적 방법
예측
분류하고자 하는 새로운 관측치와 유사한 k개의 관측치를 식별하여, 해당 관측치들의 다수가 속한 Class로 분류
유사도 측정 방식
Euclidean Distance
i=1n(xiyi)2\sqrt{ \sum_{i=1}^{n} (x_i - y_i)^2 }
계산 비용이 낮다
대부분의 경우 독립 변수의 척도를 균등하게 하기 위해, 독립 변수 표준화 과정을 거친다.
각 특성(feature)의 단위에 민감
표준화를 거치지 않으면, 의미 없는 기준으로 최근접 이웃이 결정될 위험이 있다.
Manhattan Distance
i=1nxiyi\sum_{i=1}^{n} |x_i - y_i|
각 특성(feature)의 단위에 민감
Cosine Similarity
i=1nxiyii=1nxi2i=1nyi2\frac{ \sum_{i=1}^{n} x_i y_i }{ \sqrt{ \sum_{i=1}^{n} x_i^2 } \cdot \sqrt{ \sum_{i=1}^{n} y_i^2 } }
각 특성(feature)의 단위에 민감하지 않음
벡터의 방향만 고려하게 됨
분류 규칙
k=1k=1
최근접 이웃을 하나 찾아, 새로운 관측치를 해당 Class로 분류
k>1k>1
다수결 결정 규칙 사용
kk가 커질수록 학습 데이터에 존재하는 노이즈로 인해 발생하는 과적합의 위험을 줄일 수 있으나 지역적 구조 파악에 어려울 수 있다.
kk가 작으면 데이터의 노이즈를 적합할 위험이 있다.
k=nk=n → 학습 데이터의 다수를 차지하는 Class로 분류 → 나이브 규칙과 일치
범주형 변수에서 이진 가변수로 변환
회귀모델에서는 m개의 가변수 중 하나는 나머지 합으로 표현 가능 → 다중공선성 문제가 생김
K-nn 모델에서는 m개의 가변수를 모두 사용하여야 함
m-1개만 사용하는 경우 서로 다른 범주를 같은 거리로 판정할 위험이 있다.

K-NN 예측기(수치형 결과)

분류 규칙
거리를 계산해 이웃 결정
최근접 이웃들의 평균 결과 값을 사용하여 수치 결정
가중 평균 사용 → 예측하고자하는 관측치로부터 먼 거리의 관측치는 영향을 줄임

K-NN 알고리즘의 장단점

장점
모수에 대한 가정이 거의 존재하지 않음
학습 데이터가 충분히 많고, 각 Class의 특성이 독립 변수 값들의 조합으로 결정될 때 성능 우수
단점
추론(활용) 단계에서 근접 이웃을 찾는데 소요되는 시간 多
차원 축소 → 거리 계산 시간 줄이기
데이터의 차원이 크면, 학습 데이터의 양이 굉장히 많이 필요함

코드

import pandas as pd from sklearn import preprocessing from sklearn.model_selection import train_test_split from sklearn.neighbors import NearestNeighbors, KNeighborsClassifier df = pd.read_csv('dmba/RidingMowers.csv') df['Number'] = df.index+1 trn, val = train_test_split(df, test_size=0.4, random_state=26) predictors = ['Income','Number'] # 정규화 scaler = preprocessing.StandardScaler() scaler.fit(trn[['Income','Lot_Size']]) df_Norm = pd.concat([pd.DataFrame(scaler.transform(df[['Income','Lot_Size']]), columns=['zIncome','zLot_size']), df[['Ownership','Number']]], axis=1) trn_ = df_Norm.iloc[trn.index] val_ = df_Norm.iloc[val.index] new = pd.DataFrame([{'Income': 60, 'Lot_Size': 20}]) new_ = pd.DataFrame(scaler.transform(new), columns = ['zIncome','zLot_size']) # 단순히 가장 가까운 데이터 포인트들의 거리와 인덱스를 반환 knn = NearestNeighbors(n_neighbors=3) knn.fit(trn_.iloc[:, 0:2]) dist , idx = knn.kneighbors(new_) trn_.iloc[idx[0],:] # 새로운 데이터가 주어졌을 때, 가까운 이웃을 보고 어떤 클래스인지 예측 X = trn_[['zIncome','zLot_size']] Y = trn['Ownership'] knn = KNeighborsClassifier(n_neighbors=4).fit(X,Y) y = knn.predict(new_) print(y)
Python
복사