일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 샤딩
- 쿼리 실행계획
- k-Nearest Neighbors
- 머신러닝
- R Studio
- 오버라이딩
- partitioning
- 파티셔닝
- LRU
- axios
- 글또
- 상자그림
- 레디스
- 복합인덱스
- f45
- Retry
- System Design
- axis interceptor
- 데이터베이스
- 인덱스 추가
- Sharding
- 데이터베이스 파티셔닝
- 데이터베이스 인덱스
- redis
- 다섯수치요약
- DB 파티셔닝
- 가상면접 사례로 배우는 대규모 시스템 설계
- knn분류기
- 인덱스 순서
- 통계학개론
- Today
- Total
haileyjpark
[머신러닝] KNN(K-Nearest Neighbors) 분류기 본문
머신러닝 수업을 듣고 KNN 분류기에 대해 학습한 내용을 바탕으로 KNN 분류기를 구현하고, K값에 따른 성능과 거리측정방식에 따른 성능을 비교해보았습니다.
KNN(K-Nearest Neighbors) 분류기란?
KNN(K-Nearest Neighbors) 분류기는 머신러닝의 지도 학습 기법 중 하나로, 가장 간단하고 직관적인 분류 알고리즘으로 알려져 있습니다. KNN 분류기의 주요 개념은 새로운 데이터를 분류할 때, 그 데이터와 가장 가까운 K개의 이웃 데이터의 클래스(라벨)를 참고하여 결정하는 방식입니다.
KNN의 원리
KNN의 핵심 원리는 유사한 데이터가 가깝게 위치한다는 가정에 기반하고 있습니다. 즉, 새로운 데이터가 주어졌을 때, 그 데이터와 기존 데이터 간의 거리를 계산하여 가장 가까운 K개의 이웃 데이터를 찾아 이웃 데이터의 클래스 중에서 다수결로 새로운 데이터의 클래스를 결정합니다.
이때 중요한 요소는 K 값과 거리 측정 방법입니다.
- K 값: K는 이웃의 개수를 의미하며, K의 값에 따라 분류기의 성능이 달라질 수 있습니다. 너무 작은 K를 선택하면 노이즈에 민감해질 수 있고, 너무 큰 K를 선택하면 모델이 데이터에 덜 민감해져 구분 능력이 떨어질 수 있습니다. 일반적으로 여러 K 값을 테스트해보며 최적의 K 값을 찾습니다.
- 거리 측정 방법: KNN에서는 데이터 포인트 간 거리를 측정하여 가장 가까운 이웃을 찾습니다. 일반적으로 유클리드 거리(Euclidean Distance)가 많이 사용되지만, 문제에 따라 맨해튼 거리(Manhattan Distance), 코사인 유사도(Cosine Similarity) 등 다양한 거리 측정 방법을 사용할 수 있습니다. 거리 측정 방법에 따라 분류 결과가 달라질 수 있기 때문에, 적절한 거리를 선택하는 것도 중요한 요소입니다.
KNN 알고리즘의 작동 방식
1. 데이터 준비: 학습 데이터와 테스트 데이터를 준비합니다. 학습 데이터는 이미 클래스 라벨이 부여된 데이터이며, 테스트 데이터는 분류하고자 하는 새로운 데이터입니다.
2. 거리 계산: 테스트 데이터와 학습 데이터의 각 포인트 간의 거리를 계산합니다.
3. 가장 가까운 이웃 찾기: 계산한 거리 값 중에서 가장 가까운 K개의 이웃을 선택합니다.
4. 다수결 투표: K개의 이웃 데이터의 라벨을 확인하고, 그 중 가장 빈도가 높은 라벨을 테스트 데이터의 예측 라벨로 결정합니다.
5. 결과 출력: 테스트 데이터에 대해 예측된 라벨을 출력하여 분류 결과를 확인합니다.
KNN의 장점과 단점
장점
- 직관적이고 간단함: 이해하고 구현하기 쉽습니다. 데이터의 분포나 특성을 크게 가정하지 않기 때문에 유연하게 사용할 수 있습니다.
- 모델 학습 시간이 없음: KNN은 학습 단계에서 모델을 생성하지 않고, 테스트 단계에서 거리 계산과 다수결 투표만 수행하기 때문에 Lazy Learning(게으른 학습)이라고도 불립니다. 학습 시간이 거의 들지 않는다는 장점이 있습니다.
단점
- 계산 비용이 큼: 모든 데이터와 거리를 계산해야 하므로, 데이터가 많아질수록 계산 비용이 커집니다. 특히, 실시간으로 예측해야 하는 환경에서는 비효율적일 수 있습니다.
- 저장공간이 많이 필요함: KNN은 모든 학습 데이터를 저장하고 있어야 하므로, 메모리 사용량이 많아질 수 있습니다.
- 데이터의 특성에 따라 성능이 영향을 받음: 데이터의 특성에 따라 K 값이나 거리 측정 방법을 잘 선택하지 않으면 성능이 떨어질 수 있으며, 특히 고차원 데이터에서는 거리 기반 측정이 잘 작동하지 않는 차원의 저주(Curse of Dimensionality) 문제가 발생할 수 있습니다.
KNN의 활용 사례
KNN은 그 직관성 덕분에 간단한 분류 문제나 회귀 문제에 자주 사용됩니다. 예를 들어, 이미지 분류, 텍스트 분류, 추천 시스템, 패턴 인식 등에서 활용됩니다. 특히, 소규모 데이터셋을 다룰 때 성능이 우수하며, 데이터 분포를 파악하거나 다른 복잡한 모델의 성능과 비교할 때 기준으로 사용하기도 합니다.
K값에 따른 성능 분석 구현
KNN 알고리즘에서 K 값은 예측의 정확도에 중요한 역할을 합니다. K 값이 너무 작으면 모델이 데이터의 노이즈에 민감해져 과적합될 가능성이 있으며, K 값이 너무 클 경우 주어진 데이터 영역이 아닌 전체 데이터 영역에서 각 클래스가 차지하는 비율(선험확률)에 의존하게 됩니다.
K 값을 3, 5, 7, 15, 20, 100으로 설정하고 각 K 값에 대해 5번씩 무작위로 데이터를 분할하여 정확도를 측정한 후, 평균 정확도를 계산하여 각각의 성능 비교를 구현해 보았습니다.
import numpy as np
import pandas as pd
from collections import Counter
from sklearn.model_selection import train_test_split
# CSV 파일 불러오기
data = pd.read_csv('./knn_assignment_data.csv')
X = data[['Feature1', 'Feature2']].values
y = data['Label'].values
# 거리 계산 함수 (유클리드 거리)
def euclidean_distance(point1, point2):
return np.sqrt(np.sum((point1 - point2) ** 2))
# KNN 분류기 클래스 정의
class KNNClassifier:
def __init__(self, k=3, distance_metric='euclidean'):
self.k = k
self.distance_metric = distance_metric
def fit(self, X_train, y_train):
self.X_train = X_train
self.y_train = y_train
def _calculate_distance(self, x1, x2):
if self.distance_metric == 'euclidean':
return euclidean_distance(x1, x2)
def predict(self, X_test):
predictions = [self._predict(x) for x in X_test]
return np.array(predictions)
def _predict(self, x):
distances = [self._calculate_distance(x, x_train) for x_train in self.X_train]
k_indices = np.argsort(distances)[:self.k]
k_nearest_labels = [self.y_train[i] for i in k_indices]
most_common = Counter(k_nearest_labels).most_common(1)
return most_common[0][0]
# K 값에 따른 성능 비교 (유클리드 거리 고정)
k_values = [3, 5, 7, 15, 20, 100]
n_repeats = 5
results = {}
for k in k_values:
accuracies = []
for _ in range(n_repeats):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
knn = KNNClassifier(k=k, distance_metric='euclidean')
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
accuracy = np.sum(y_pred == y_test) / len(y_test)
accuracies.append(accuracy)
avg_accuracy = np.mean(accuracies)
results[k] = avg_accuracy
print(f"K={k}, Average Accuracy={avg_accuracy:.2f}")
# 최적 K 값 출력
best_k = max(results, key=results.get)
print(f"\n최적 K 값: {best_k}, 평균 정확도: {results[best_k]:.2f}")
K 값 선택 근거
처음에 K의 값을 3, 5, 7로 비교해보았으나, 성능에 큰 차이가 보이지 않아서 점점 더 큰 값으로 비교해보려고 15, 20, 100을 추가하여 다시 비교해보았습니다.
결과 분석
- K=3: 모델이 세부사항에 민감하게 반응하여 각 클래스의 경계를 잘 구분할 것으로 예상했지만, 정확도가 0.77로 나타나 작은 K 값에서 다소 불안정한 성능을 보였습니다.
- K=5, K=7: 이 값들에서는 정확도가 0.79로 약간 개선되었으며, 모델이 과도한 세부 사항을 반영하지 않으면서도, 데이터의 전반적인 경향을 잘 반영하는 균형을 이룹니다.
- K=15: 정확도가 가장 높은 0.80을 기록했습니다. 이 구간에서 모델이 데이터의 노이즈에 덜 민감해지며, 과적합되지 않으면서도 일반화 성능이 향상된 것으로 보입니다.
- K=20, K=100: K=20, K=100에서 정확도가 0.79로 약간 낮아졌습니다. 이는 큰 K 값에서는 모델이 각 클래스의 전반적인 분포를 반영하여, 안정적이지만 세부사항을 잘 반영하지 못하는 경향이 있음을 시사합니다.
최적 K값과 결론
최적의 K 값은 K=15로 나타났으며, 이때 평균 정확도가 0.80으로 가장 높았습니다.
이는 K=15일 때 모델이 각 클래스의 전반적인 분포와 개별 데이터 포인트 간의 관계를 적절하게 반영할 수 있었음을 의미합니다.
K 값에 따라 성능 차이가 크게 나타나지 않은 이유는 다음과 같이 분석할 수 있습니다.
- 데이터의 균등한 분포: 각 클래스가 균일하게 분포되어 있어, K 값이 작아도 과적합 문제가 심각하지 않았습니다.
- 명확한 클래스 경계: 클래스 간 경계가 명확하여 작은 K 값이나 큰 K 값 모두 안정적인 성능을 보였습니다.
- K 값이 큰 경우: 큰 K 값에서는 모델이 모든 클래스의 평균적인 분포를 반영하며 안정성을 유지하지만, 개별 데이터의 세부 사항 반영이 부족해 정확도가 약간 감소했습니다.
'소프트웨어 공학' 카테고리의 다른 글
CPU 쓰로틀링이 높다란 무엇일까? (0) | 2025.02.02 |
---|---|
알고리즘 개념 정리 - 정렬 (1) | 2024.10.27 |
Yarn workspace로 모노레포 관리시 발생할 수 있는 문제 (2) | 2024.02.04 |
Yarn workspace로 모노레포 관리하기 (0) | 2024.01.21 |
[컴퓨터 구조] 컴퓨터 아키텍처의 주소 지정 방식과 마이크로 연산 (0) | 2023.12.24 |