⊢MachineLearning

비지도학습 : 군집화 모델 - k-means Clustering

최 수빈 2025. 3. 16. 22:50

 

k-means Clustering

 

데이터를 k개의 그룹(cluster)으로 나누는 알고리즘

 

데이터를 k개의 그룹으로 나눠 각 군집의 중심(centroid)을 설정, 데이터를 가장 가까운 중심에 할당하는 방식으로 작동

반복적으로 군집 중심을 업데이트하며 최적의 클러스터를 찾아감

 

 

알고리즘의 단계

  1. 초기화 : k개의 군집 중심(centroid)을 무작위로 설정
  2. 할당 단계 : 각 데이터를 가장 가까운 군집 중심에 할당
  3. 업데이트 단계 : 군집 중심을 해당 군집에 속한 데이터 포인트들의 평균으로 업데이트
  4. 반복 : 군집 중심이 변하지 않을 때까지 2~3단계를 반복

 

 

거리 측정 방법

 

유클리드 거리(Euclidean Distance)

 

d(p, q) = √∑i=1n (pi - qi)2

 

p, q은 각각 데이터 포인트

n은 특징(feature) 차원 수

 

  • 두 점 사이의 직선 거리를 측정 (좌표공간에서의 실제 거리와 직관적으로 일치)
  • 차원이 증가하면 거리 계산의 신뢰도가 낮아지는 차원의 저주(Curse of Dimensionality) 문제가 발생할 수 있음

 

맨해튼 거리(Manhattan Distance, L1 Norm)

 

x, y 좌표의 차이를 각각 더하는 방식으로 거리를 측정

바둑판 위에서 경로를 따져 이동할 때처럼 계산된다고 해서 택시 거리(Taxicab Distance)라고도 부름

 

d(p, q) = ∑i=1n |pi - qi|

 

  • 축을 따라 이동하는 방식이므로, 고차원 데이터에도 비교적 안정적
  • 유클리드 거리보다 덜 민감하게 동작할 수 있음
  • 정사각형 형태의 군집이 만들어지는 경향이 있음

→ 텍스트 데이터에서 단어 벡터 간 거리 측정 (예 : NLP)

→ 도시 거리 계산 (도시 내 길을 따라 이동하는 거리와 유사)

 

 

민코프스키 거리(Minkowski Distance)

 

유클리드 거리와 맨해튼 거리를 일반화한 거리 척도

 

d(p, q) = ( ∑i=1n |pi - qi|p )1/p

 

p = 1이면 맨해튼 거리

p = 2이면 유클리드 거리

p < 2일 경우, 더 높은 차원의 거리 측정 가능

 

  • p값을 조정하면 유클리드 거리와 맨해튼 거리 사이에서 유연하게 적용 가능
  • 고차원 공간에서도 적용 가능하지만, 최적의 p값을 찾는 것이 중요

 

코사인 유사도 (Cosine Similarity)

 

k-means는 원래 거리 기반 알고리즘이지만, 각도 기반으로 군집화해야 할 경우 유사도를 활용할 수 있음

두 벡터가 이루는 각도의 코사인 값을 이용해 코사인 유사도를 측정하는 방식

 

cos(θ) = ( p ⋅ q ) / ( ||p|| ⋅ ||q|| )

 

 

코사인 거리(Cosine Distance) 변환

 

d(p, q) = 1 - cos(θ)
  • 크기(벡터의 길이)가 아니라 방향(패턴)에 집중
    → 데이터 크기(scale)에 민감하지 않음
  • 유사도 값이 -1(완전 반대), 0(무관), 1(완전 동일) 형태로 나옴

→ 텍스트 데이터 분석(예 : 문서 클러스터링)

→ 추천 시스템(예 : 사용자 행동 패턴 기반 클러스터링)

 

*원래 k-means는 거리 기반 알고리즘이라 코사인 유사도를 직접 사용할 수 없음

코사인 거리(Cosine Distance) = 1 - Cosine Similarity로 변환해 사용 가능

 

 

 

마할라노비스 거리(Mahalanobis Distance)

 

각 변수의 분산과 공분산을 고려하여 거리 측정

데이터가 서로 다른 단위를 가질 때 유용

 

d(p, q) = √( ( p - q )T S-1 ( p - q ) )

 

여기서 S는 공분산 행렬(convariance matrix)

 

  • 데이터의 상관관계를 반영하여 거리 측정 가능
  • 단순한 유클리드 거리보다 더 정교한 측정 가능

→ 이상치 탐지(Outlier Detection)

→ 차원이 높은 데이터에서 변수 간 상관관계를 고려한 클러스터링 

 

 

하이퍼볼릭 거리(Hyperbolic Distance)

 

고차원 공간에서, 특히 네트워크 그래프나 트리 구조에서 자주 사용

d(p, q) = arcosh( 1 + 2 ⋅ ||p - q||2 / ( (1 - ||p||2) ⋅ (1 - ||q||2) ) )

 

→ 소셜 네트워크 분석

→ 지식 그래프(Knowledge Graph) 클러스터링

 

 

  • 연속형 데이터 → 유클리드 거리, 맨해튼 거리
  • 고차원 데이터 → 민코프스키 거리, 마할라노비스 거리
  • 텍스트/문서 데이터 → 코사인 유사도
  • 상관관계를 고려해야 하는 경우 → 마할라노비스 거리
  • 네트워크/트리 구조 데이터 → 하이퍼볼릭 거리

 

기본적으로 k-means에서 가장 많이 사용되는 거리 측정 방법은 유클리드 거리를 사용한 거리 측정 방법

 

 

최적의 k값 찾기 : 엘보우 방법(Elbow Method)

 

클러스터 수 k를 결정하는 대표적인 방법

→ k-means에서 클러스터 수 k를 미리 정하기 위함

 

  • 여러 개의 k값에 대해 군집의 응집도(Inertia)를 계산하여 그래프로 표현
    Inertia(관성) : 각 데이터가 군집 중심과 얼마나 가까운지를 나타내는 값
  • k가 증가할수록 Inertia는 감소하지만, 어느 순간 감소율이 급격히 줄어드는 지점이 존재
    → 최적의 k

그래프에서 급격한 기울기 변화가 있는 지점 : 엘보우 포인트, 최적의 k값이 됨

 

 

 

k-means Clustering 실습

 

Kaggle의 쇼핑몰 고객 데이터(Mall_Customers.csv)를 활용하여 k-means clustering을 적용

 

 

데이터 로드 및 전처리

pip install kagglehub

import kagglehub
import os
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans # k-means 군집화 모델 생성
import matplotlib.pyplot as plt
import seaborn as sns

# Download latest version
path = kagglehub.dataset_download("vjchoudhary7/customer-segmentation-tutorial-in-python")

# 데이터 파일 경로 생성
csv_path = os.path.join(path, "Mall_Customers.csv")

# 데이터 로드
data = pd.read_csv(csv_path)

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

# 데이터 스케일링 - 데이터를 표준화(평균 0, 분산 1)하여 스케일 차이를 제거
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)

 

최적의 k 찾기 (엘보우 방법)

# 여러 k 값에 대해 inertia 계산
inertia = []
K = range(1, 11)

for k in K:
    kmeans = KMeans(n_clusters=k, random_state=42) # n_cluster = k : 군집 수 설정, random_state=42
    kmeans.fit(data_scaled) # fit(data_scaled) : 데이터를 학습하여 군집 형성
    inertia.append(kmeans.inertia_) # 각 k에 대한 관성(Inertia) 값 저장

# 엘보우 그래프 그리기
plt.figure(figsize=(10, 6))
plt.plot(K, inertia, 'bx-') # x축, y축 데이터와 그래프 스타일 설정 - Inertia 값을 시각화하여 엘보우 포인트 찾기
plt.xlabel('Number of clusters (k)')
plt.ylabel('Inertia')
plt.title('Elbow Method For Optimal k')
plt.show()

 

Elbow Method For Optimal k

 

k-means 모델 학습 및 군집화

# 최적의 k 값 선택 후 모델 학습
kmeans = KMeans(n_clusters=5, random_state=42) # k-means 모델 생성 (k=5)
kmeans.fit(data_scaled) # 데이터를 학습하여 클러스터 형성

# 군집 결과 할당
data['Cluster'] = kmeans.labels_ # 각 데이터가 속한 클러스터 할당

 

군집 시각화

# 연령 vs 연소득 군집 시각화
plt.figure(figsize=(10, 6))
# 산점도 그래프, X=data['Age'] : x축 데이터, y=data['Annual Income (k$)'] : y축 데이터, hue=data['Cluster'] : 색상에 따라 군집 구분, palette='viridis' : 색상 팔레트 설정
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()

# 연소득 vs 지출 점수 군집 시각화
plt.figure(figsize=(10, 6))
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()

 

 
Clusters of customers (Age vs. Annual Income)
Clusters of customers (Annual Income vs. Spending Score)

 

→ 고객들의 연령, 연소득, 지출 점수 등을 바탕으로 소비 패턴 분석 가능

 

 

활용 예

 고객 유형(예: 고소득-고소비층, 저소득-고소비층 등) 분석

 타겟 마케팅 전략 수립 (특정 군집을 대상으로 한 맞춤형 광고)

 추천 시스템(비슷한 소비 패턴을 가진 고객에게 맞춤형 상품 추천)