AI/ML

[ML] 비지도학습 - 군집화모델 (K-means Clustering)

죵욜이 2024. 12. 29. 01:57

K-means clustering 이란?

K-means clustering은 데이터 포인트를 비슷한 특성을 가진 그룹(클러스터)으로 나누는 비지도 학습(Unsupervised Learning) 알고리즘입니다. 이 방법은 주어진 데이터셋을 사용자가 지정한 k개의 클러스터로 분할하는 것을 목표로 합니다.


작동 원리

  1. 초기화 (Initialization):
    • k개의 클러스터 중심(centroid)을 무작위로 선택합니다.
  2. 할당 단계 (Assignment Step):
    • 각 데이터 포인트를 가장 가까운 중심에 할당하여 클러스터를 형성합니다.
    • "가장 가까운"은 일반적으로 유클리드 거리(Euclidean Distance)를 기준으로 합니다.
  3. 갱신 단계 (Update Step):
    • 각 클러스터의 중심을 해당 클러스터에 속한 데이터 포인트의 평균값으로 갱신합니다.
  4. 반복 (Iterate):
    • 할당 단계와 갱신 단계를 반복하여 중심점이 더 이상 변하지 않을 때까지(또는 수렴 조건을 만족할 때까지) 수행합니다.

거리 측정 방법

  • 유클리드 거리
  • 맨해튼 거리
  • 코사인 유사도
  • 민코프스키 거리
  • 등 여러방식이 있지만 주로 유클리드 거리(Euclidean Distance)를 사용하여 데이터 포인트와 군집 중심 간의 거리를 계산한다.


그렇다면 초기 K 의 값은 어떻게 정할까?

K-means 의 중요한 하이퍼파라미터인 K(클러스터 개수) 를 선택하기 위해 엘보우 방법(Elbow Method)를 주로 사용합니다.

 

엘보우 포인트(Elbow Point)

  • 클러스터 개수를 선택할 때 클러스터 내 분산(SSE, Sum of Squared Errors)을 최소화하는 k 를 결정
  • SSE 는 각 데이터포인트와 해당 클러스터 중심 간 거리의 제곱합으로 계산된다.

- 과정

  1. 다양한 k 값에 대해 K-means 알고리즘을 실행
  2. 각 k 값에 대해 SSE를 계산
  3. SSE를 k값에 대해 플롯
  4. 그래프에서 SSE의 감소율이 급격히 줄어드는 지점(팔꿈치 모양)을 찾는다
    이 지점이 최적의 K로 간주된다.


알고리즘 종료 조건

  • 클러스터 중심이 더 이상 변화하지 않음.
  • 데이터 포인트의 클러스터 할당이 더 이상 변경되지 않음.
  • 지정된 최대 반복 횟수에 도달.

장점

  • 구현이 간단하고 계산이 빠릅니다.
  • 대규모 데이터셋에서도 비교적 효율적입니다.
  • 클러스터 개수가 명확히 정의된 경우 효과적입니다.

단점

  • 값(클러스터 수)을 사전에 지정해야 합니다.
  • 초기 중심값 선택에 민감하여 지역 최적해(Local Optima)에 빠질 수 있습니다.
  • 구형 클러스터(원형 구조)를 가정하기 때문에 복잡한 데이터 구조를 잘 처리하지 못합니다.
  • 이상치(Outlier)에 민감합니다.

실생활 응용

  • 고객 세분화: 고객의 구매 행동을 기반으로 그룹화하여 마케팅 전략 수립.
  • 이미지 압축: 색상 데이터를 그룹화하여 압축 이미지 생성.
  • 의학적 데이터 분석: 환자 데이터를 기반으로 질병 유형 분류.

K-means 변형 알고리즘

  • Mini-Batch K-means: 대규모 데이터셋을 처리하기 위해 작은 배치를 사용하여 속도 향상.
  • K-means++: 초기 중심값을 더 똑똑하게 선택하여 성능 향상.

예시

- 데이터 로드 및 전처리

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import seaborn as sns

# 데이터 로드
data = pd.read_csv('Mall_Customers.csv')

# 필요한 열 선택 및 결측값 처리
data = data[['Age', 'Annual Income (k$)', 'Spending Score (1-100)']]

# 데이터 스케일링
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)

 

- 모델 학습 및 군집화

# 최적의 k 찾기 (엘보우 방법)
inertia = []
K = range(1, 11)
for k in K:
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(data_scaled)
    inertia.append(kmeans.inertia_)

# 엘보우 그래프 그리기
plt.figure(figsize=(10, 8))
plt.plot(K, inertia, 'bx-')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Elbow Method For Optimal k')
plt.show()

# k=5로 모델 생성 및 학습
kmeans = KMeans(n_clusters=5, random_state=42)
kmeans.fit(data_scaled)

# 군집 결과 할당
data['Cluster'] = kmeans.labels_

 

- 군집 시각화

# 2차원으로 군집 시각화 (연령 vs 소득)
plt.figure(figsize=(10, 8))
sns.scatterplot(x=data['Age'], y=data['Annual Income (k$)'], hue=data['Cluster'], palette='viridis')
plt.title('Clusters of customers (Age vs Annual Income)')
plt.show()

# 2차원으로 군집 시각화 (소득 vs 지출 점수)
plt.figure(figsize=(10, 8))
sns.scatterplot(x=data['Annual Income (k$)'], y=data['Spending Score (1-100)'], hue=data['Cluster'], palette='viridis')
plt.title('Clusters of customers (Annual Income vs Spending Score)')
plt.show()