k-means Clustering
데이터를 k개의 그룹(cluster)으로 나누는 알고리즘
데이터를 k개의 그룹으로 나눠 각 군집의 중심(centroid)을 설정, 데이터를 가장 가까운 중심에 할당하는 방식으로 작동
반복적으로 군집 중심을 업데이트하며 최적의 클러스터를 찾아감
알고리즘의 단계
- 초기화 : k개의 군집 중심(centroid)을 무작위로 설정
- 할당 단계 : 각 데이터를 가장 가까운 군집 중심에 할당
- 업데이트 단계 : 군집 중심을 해당 군집에 속한 데이터 포인트들의 평균으로 업데이트
- 반복 : 군집 중심이 변하지 않을 때까지 2~3단계를 반복
거리 측정 방법
유클리드 거리(Euclidean Distance)
p, q은 각각 데이터 포인트
n은 특징(feature) 차원 수
- 두 점 사이의 직선 거리를 측정 (좌표공간에서의 실제 거리와 직관적으로 일치)
- 차원이 증가하면 거리 계산의 신뢰도가 낮아지는 차원의 저주(Curse of Dimensionality) 문제가 발생할 수 있음
맨해튼 거리(Manhattan Distance, L1 Norm)
x, y 좌표의 차이를 각각 더하는 방식으로 거리를 측정
바둑판 위에서 경로를 따져 이동할 때처럼 계산된다고 해서 택시 거리(Taxicab Distance)라고도 부름
- 축을 따라 이동하는 방식이므로, 고차원 데이터에도 비교적 안정적
- 유클리드 거리보다 덜 민감하게 동작할 수 있음
- 정사각형 형태의 군집이 만들어지는 경향이 있음
→ 텍스트 데이터에서 단어 벡터 간 거리 측정 (예 : NLP)
→ 도시 거리 계산 (도시 내 길을 따라 이동하는 거리와 유사)
민코프스키 거리(Minkowski Distance)
유클리드 거리와 맨해튼 거리를 일반화한 거리 척도
p = 1이면 맨해튼 거리
p = 2이면 유클리드 거리
p < 2일 경우, 더 높은 차원의 거리 측정 가능
- p값을 조정하면 유클리드 거리와 맨해튼 거리 사이에서 유연하게 적용 가능
- 고차원 공간에서도 적용 가능하지만, 최적의 p값을 찾는 것이 중요
코사인 유사도 (Cosine Similarity)
k-means는 원래 거리 기반 알고리즘이지만, 각도 기반으로 군집화해야 할 경우 유사도를 활용할 수 있음
두 벡터가 이루는 각도의 코사인 값을 이용해 코사인 유사도를 측정하는 방식
코사인 거리(Cosine Distance) 변환
- 크기(벡터의 길이)가 아니라 방향(패턴)에 집중
→ 데이터 크기(scale)에 민감하지 않음 - 유사도 값이 -1(완전 반대), 0(무관), 1(완전 동일) 형태로 나옴
→ 텍스트 데이터 분석(예 : 문서 클러스터링)
→ 추천 시스템(예 : 사용자 행동 패턴 기반 클러스터링)
*원래 k-means는 거리 기반 알고리즘이라 코사인 유사도를 직접 사용할 수 없음
코사인 거리(Cosine Distance) = 1 - Cosine Similarity로 변환해 사용 가능
마할라노비스 거리(Mahalanobis Distance)
각 변수의 분산과 공분산을 고려하여 거리 측정
데이터가 서로 다른 단위를 가질 때 유용
여기서 S는 공분산 행렬(convariance matrix)
- 데이터의 상관관계를 반영하여 거리 측정 가능
- 단순한 유클리드 거리보다 더 정교한 측정 가능
→ 이상치 탐지(Outlier Detection)
→ 차원이 높은 데이터에서 변수 간 상관관계를 고려한 클러스터링
하이퍼볼릭 거리(Hyperbolic Distance)
고차원 공간에서, 특히 네트워크 그래프나 트리 구조에서 자주 사용
→ 소셜 네트워크 분석
→ 지식 그래프(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()

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()


→ 고객들의 연령, 연소득, 지출 점수 등을 바탕으로 소비 패턴 분석 가능
활용 예
• 고객 유형(예: 고소득-고소비층, 저소득-고소비층 등) 분석
• 타겟 마케팅 전략 수립 (특정 군집을 대상으로 한 맞춤형 광고)
• 추천 시스템(비슷한 소비 패턴을 가진 고객에게 맞춤형 상품 추천)
'⊢MachineLearning' 카테고리의 다른 글
비지도학습 : 군집화 모델 - DBSCAN (0) | 2025.03.17 |
---|---|
비지도학습 : 군집화 모델 - 계층적 군집화 (2) | 2025.03.17 |
지도학습 : 분류모델 - 의사결정나무 (0) | 2025.03.16 |
지도학습 : 분류모델 - 나이브베이즈 (0) | 2025.03.14 |
지도학습 : 분류모델 - KNN (0) | 2025.03.14 |