K-평균 군집화: 원리, 구현 및 고려사항

K-평균 군집화는 데이터셋을 미리 정해진 K개의 군집으로 나누는 데 널리 사용되는 거리 기반 알고리즘입니다. 이 알고리즘의 목표는 각 데이터 포인트와 해당 군집 중심 간의 거리 제곱 합을 최소화하는 것입니다.

1. 핵심 원리

K-평균의 목표는 데이터를 K개의 군집으로 분할하여, 각 데이터 포인트가 가장 가까운 군집 중심에 속하도록 하는 것입니다. 군집 중심의 위치를 반복적으로 조정함으로써, K-평균은 군집 내부의 밀집도를 최적화하여 가능한 한 조밀하고 서로 분리된 군집을 형성합니다.

핵심 개념

  • 군집(Cluster): K-평균은 군집 내 거리의 제곱 합을 최소화하여 데이터 포인트들이 군집 내에 뭉치도록 합니다. 군집은 특정 기준에서 "서로 유사한" 데이터 포인트들의 집합입니다. 예를 들어, 쇼핑몰 고객을 "학생", "직장인", "은퇴자" 세 군집으로 나눌 수 있습니다.
  • 군집 중심(Centroid): 군집 중심은 해당 군집에 속한 모든 데이터 포인트의 평균값으로, 군집의 중심 위치를 나타냅니다.
  • 할당 및 업데이트: K-평균은 반복적인 과정을 통해 군집 할당을 조정하고, 데이터 포인트와 중심 간의 거리를 최소화하여 점진적으로 수렴합니다.

2. 알고리즘 작동 방식

2.1 기본 절차

K-평균은 "가장 가까운 중심에 할당"하는 방식을 사용합니다:

  1. K개의 군집 중심을 무작위로 선택합니다 (초기 중심점).
  2. 각 데이터 포인트를 가장 가까운 군집 중심으로 할당합니다.
  3. 각 군집의 새로운 중심을 재계산합니다.
  4. 중심점이 더 이상 변하지 않거나 지정된 반복 횟수에 도달할 때까지 2단계와 3단계를 반복합니다.

2.2 상세 단계 (예시 포함)

K-평균 군집화 과정은 크게 할당(Assignment) 단계와 업데이트(Update) 단계로 나뉩니다. 다음은 상세 단계입니다:

  1. K 값 결정: 군집의 수 K를 설정합니다.
  2. 군집 중심 초기화: 데이터셋에서 K개의 데이터 포인트를 무작위로 선택하여 초기 군집 중심(centroids)으로 사용합니다.
  3. 할당 단계: 데이터셋의 각 데이터 포인트에 대해, 가장 가까운 군집 중심으로 할당합니다. 여기서 "거리"는 주로 유클리드 거리(Euclidean distance)를 사용합니다.
  4. 업데이트 단계: 현재의 군집 할당에 따라, 각 군집의 중심을 다시 계산합니다. 즉, 해당 군집 내 모든 데이터 포인트의 평균값을 새로운 군집 중심으로 사용합니다.
  5. 반복: 군집 중심이 더 이상 변하지 않거나(수렴) 최대 반복 횟수에 도달할 때까지 3단계와 4단계를 반복합니다.

의사 코드

function KMeans(데이터셋 X, 군집 수 K):
    1. X에서 K개의 포인트를 무작위로 선택하여 초기 군집 중심 설정
    2. 다음을 반복:
        a. 각 포인트 P를 가장 가까운 군집 중심 C에 할당
        b. 각 군집 C의 중심을 해당 군집 내 모든 포인트의 평균으로 업데이트
    3. 군집 중심이 더 이상 변하지 않을 때까지 반복
    4. 최종 군집 할당 및 군집 중심 반환

3. K-평균의 장단점

  • 장점:
    • 간결하고 효율적: 대규모 데이터셋에 적합하며, 처리 속도가 빠릅니다.
    • 빠른 수렴: 적절한 초기 중심 선택 시 비교적 빠르게 수렴하는 경향이 있습니다.
  • 단점:
    • 초기 중심에 민감: 초기 군집 중심 선택에 따라 최종 결과가 달라질 수 있습니다.
    • 구형 군집 가정: K-평균은 각 군집이 구형이고 크기가 비슷하다고 가정합니다. 따라서 비구형(예: 초승달 모양) 군집이나 크기 차이가 큰 군집을 잘 발견하지 못합니다.
    • 이상치(Outlier)에 민감: 데이터의 이상치가 군집 중심 계산에 영향을 줄 수 있습니다.
    • 지역 최적해: 전역 최적해(global optimum)를 보장하지 않으며, 지역 최적해(local optimum)에 도달할 수 있습니다.
    • 데이터 유형 제한: 평균을 계산할 수 있는 데이터에만 적용 가능합니다.

4. 구현 예시

Scikit-learn 라이브러리 사용


from sklearn.cluster import KMeans
import numpy as np

# 예시 데이터 생성
X_sample = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])

# KMeans 모델 초기화 및 학습 (군집 2개)
# random_state는 재현성을 위해 설정
kmeans_model = KMeans(n_clusters=2, random_state=42, n_init=10)
kmeans_model.fit(X_sample)

# 각 데이터 포인트의 군집 레이블
cluster_labels = kmeans_model.labels_
# 계산된 군집 중심
cluster_centers = kmeans_model.cluster_centers_

print("군집 레이블:", cluster_labels)
print("군집 중심:", cluster_centers)

직접 구현


import numpy as np

def init_centers_randomly(data, num_clusters):
    # 데이터에서 무작위로 초기 중심점 선택
    indices = np.random.choice(len(data), num_clusters, replace=False)
    return data[indices]

def assign_to_closest_center(data, centers):
    # 각 데이터 포인트와 모든 중심점 간의 거리 계산
    # data shape: (n_samples, n_features), centers shape: (n_clusters, n_features)
    # X[:, np.newaxis] -> (n_samples, 1, n_features)
    # distances shape: (n_samples, n_clusters)
    distances = np.linalg.norm(data[:, np.newaxis] - centers, axis=2)
    # 각 데이터 포인트에 가장 가까운 중심점의 인덱스 반환
    return np.argmin(distances, axis=1)

def recalculate_centers(data, labels, num_clusters):
    new_centers = []
    for i in range(num_clusters):
        # 현재 군집에 속한 데이터 포인트들
        points_in_cluster = data[labels == i]
        if len(points_in_cluster) > 0:
            # 해당 군집의 평균 계산
            new_centers.append(points_in_cluster.mean(axis=0))
        else:
            # 군집에 포인트가 없으면 임의로 재설정 (이 예제에서는 단순화)
            new_centers.append(data[np.random.choice(len(data))]) 
    return np.array(new_centers)

def run_kmeans(data, num_clusters, max_iterations=100, tolerance=1e-4):
    # 초기 중심점 설정
    current_centers = init_centers_randomly(data, num_clusters)
    
    for _ in range(max_iterations):
        # 데이터 포인트를 가장 가까운 중심에 할당
        point_labels = assign_to_closest_center(data, current_centers)
        # 새로운 중심점 계산
        next_centers = recalculate_centers(data, point_labels, num_clusters)
        
        # 중심점 변화량 계산 및 수렴 여부 확인
        center_shift = np.sum(np.abs(next_centers - current_centers))
        if center_shift < tolerance:
            break # 수렴 조건 만족
        
        current_centers = next_centers # 중심점 업데이트
        
    return point_labels, current_centers

# 예시 데이터 (위와 동일)
data_points = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])

# K-means 실행
final_labels, final_centers = run_kmeans(data_points, num_clusters=2)
print("최종 군집 할당:", final_labels)
print("최종 군집 중심 위치:", final_centers)

태그: K-means 군집화 머신러닝 데이터 분석 비지도 학습

9월 29일 21:51에 게시됨