본문 바로가기
데이터 분석/Machine Learning

클러스터링 분석 - (5) 적정 군집수(k) 찾기

by 친절한 휘저씨 2021. 12. 22.

대표적인 클러스터링 방법, k-평균(k-means) 군집화 알고리즘을 사용할 때 고민이 필요한 부분 중 한 가지는 군집수(k) 결정입니다. 군집분석은 비지도 학습(unsupervised learning) 방법 중 하나이고, 비지도 학습에서는 보통 타겟값 혹은 목표값이 없는 데이터를 사용하기 때문에 군집화가 잘 되었는지, 혹은 적정 클러스터(군집)의 수는 몇 개인지 판단하는 것은 매우 어렵습니다. 하지만, 분석가의 판단을 돕고, 최선의 결과를 도출하기 위한 방법으로 몇 가지를 생각해 볼 수 있는데요, 하나씩 살펴보도록 하겠습니다.

 

 

Inertia value를 활용한 군집 응집도 탐색

Inertia value에 대하여 설명하기 전에 k-means 알고리즘의 동작 원리를 간단히 알아보는 것이 좋을 것 같습니다.

  1. k개의 클러스터 중심(centroid)을 무작위로 지정
  2. 데이터 포인트를 가장 가까운 클러스터 중심에 할당
  3. 각각의 클러스터에 할당된 데이터 포인트의 평균으로 클러스터 중심을 다시 지정
  4. 위의 2~3의 반복
  5. 각각의 클러스터에 할당되는 데이터 포인트에 변화가 없을 때 알고리즘 종료

k-means 알고리즘을 통해 만들어진 각각의 군집은 하나의 중심(centroid)을 가지고 있고, 각 개체는 가장 가까운 중심에 할당됩니다. 이렇게 할당된 개체들이 모여 하나의 군집을 형성하는 방식으로 군집화가 진행됩니다. Inertia value는 각 클러스터의 중심에서 클러스터에 할당된 데이터 포인트간의 거리를 합산한 것을 의미하며, 군집이 얼마나 잘 응집되었는지 보여주는 지표입니다. 이 값이 작을수록 응집도가 높게 군집화가 잘 되었다고 평가할 수 있습니다.

따라서 데이터 전처리와 스케일링을 완료한 데이터셋을 이용하여 군집수(k)를 다양하게 적용하여 모델 학습 과정을 거친 후, Inertia value를 출력하여 군집수의 변화에 따라 응집도가 어떻게 달라지는지 확인할 수 있습니다. 아래는 Jupyter Notebook에서 Python으로 작성한 code이고, 실제로 분석에 활용했던 내용입니다. 굉장히 많은 변수와 개체로 구성된 dataset이었기 때문에 k의 수는 넉넉히 19개까지 설정하여 응집도 변화를 살펴보고자 했습니다.

 

# Import Module
from sklearn.cluster import KMeans    # k-means 모듈 불러오기
import matplotlib.pyplot as plt    # 시각화를 위한 matplotlib.pyplot 모듈 불러오기
%matplotlib inline    # 시각화 결과를 Jupyter Notebook에 바로 표시하기 위한 명령어

# k-means clustering & inertia simulation
ks = range(1,20)   # 1~19개의 k로 클러스터링하기 위함
inertias = []    # 응집도 결과 저장을 위한 빈 리스트 만들어 놓기
for k in ks :
    model = KMeans(n_clusters = k, n_init = 5)  # n_init 숫자 클수록 계산량 증가하니까 grid search 단계에서는 작게 설정
    %time model.fit(df)    # 'df'라는 이름의 dataset을 사용하여 모델 학습 & 학습에 소요되는 시간 측정  
    inertias.append(model.inertia_)    # 응집도 결과를 inertias 리스트에 계속 저장(추가)
    print('n_cluster : {}, inertia : {}'.format(k, model.inertia_))    # k 설정에 따른 결과 출력
    
# Visualization
plt.figure(figsize = (15, 6))   
plt.plot(ks, inertias, '-o')    
plt.xlabel('number of clusters, k')    
plt.ylabel('inertia')    
plt.xticks(ks)    
plt.show()

 

위의 결과를 보시면 k의 결과가 6개를 넘어가면서부터 k 개수 증가에 따른 응집도 감소 효과가 점차 작아지는 모습을 볼 수 있습니다. 또한 k=10 을 전후하여 응집도 변화가 다시 일시적으로 커지는 것처럼 보이기 때문에 실제로 분석을 진행할 때에는 k를 6~11로 다양하게 설정하여 클러스터링 작업을 진행하고 군집화 결과를 검토하는 데 사용했습니다.



실루엣(silhouette) 계수


실루엣 계수
는 inertiua value와 마찬가지로 군집화의 정답(타겟값)을 모를 때 군집 응집도를 평가하는 방법 중 한 가지입니다.

우선 모든 데이터 쌍 (i, j)에 대해 거리 혹은 비유사도(dissimilarity)를 구하고, 이 결과를 이용하여 모든 데이터 i에 대해 다음 값을 구합니다.

  • a(i) : i와 같은 군집에 속한 원소들의 평균 거리
  • b(i) : i와 다른 군집 중 가장 가까운 군집까지의 평균 거리
  • 이 때 데이터 i에 대한 실루엣 계수는 아래와 같이 정의합니다. 전체 데이터의 실루엣 계수를 평균된 값을 평균 실루엣 계수라고 합니다.

만약 데이터 i 에 대하여 같은 군집의 데이터가 다른 군집의 데이터보다 더 가깝다면 그 데이터의 실수엣 계수는 양수(최대 점수 1)가 됩니다. 반대로 다른 군집의 데이터가 같은 군집의 데이터보다 더 가깝다면 군집화가 잘못된 경우라고 볼 수 있는데요, 이 때는 그 데이터의 실루엣 계수가 음수가 됩니다(-1: 잘못된 군집). 잘못된 군집화에서는 실루엣 계수가 음수인 데이터가 많아지므로 평균 실루엣 계수가 작아집니다. 따라서 실루엣 계수가 클수록 좋은 군집화라고 할 수 있습니다.


하지만, 결론부터 말씀드리면 클러스터링 작업을 진행할 때는 실루엣 계수를 활용하지는 않았는데요, 그 이유는..

  • 클러스터 모양이 밀집되었을 때(원형일 때)는 성능이 좋지만, 모양이 복잡할 때는 밀집도를 활용한 평가가 잘 들어맞지 않는 문제가 있고, (사실 이건 inertia value를 구할 때도 같은 문제가 발생하긴 합니다 )
  • inertia value를 구할 때보다 계산량이 많아서 대용량 데이터셋으로 k 갯수별로 계수를 구하는 것에 시간이 너무 오래 걸리는 이슈도 있었습니다.
  • 또한, 밀집도 확인을 위해 굳이 2가지 군집 타당성 지표를 활용하는 것은 그리 효율적이지 못하다고 판단했기 때문입니다. 실루엣 점수가 높은 k를 찾더라도 군집에 어떤 유의미한 발견이나 흥미로운 내용이 있는지 여전히 알 수 없는 문제가 있기 때문에 응집도 지표는 inertia value로 충분할 것으로 판단했습니다.

아래는 실루엣 계수를 구하기 위한 모듈과 간단한 명령어 예시입니다. 참고로 보시면 될 것 같습니다.

 

from sklearn.metrics.cluster import silhouette_score    # 모듈 불러오기

model = KMeans(n_clusters = k)  # 모델 생성. k에는 적정한 군집수 넣기
k_model = model.fit(df)    # 'df'라는 이름의 dataset으로 모델 학습 
cluster = k_model.labels_    # 클러스터링 결과를 cluster라는 변수에 저장

print("Silhouette Score:", silhouette_score(df, cluster))    # dataset과 결과변수를 함수에 넣어 계수 출력

좀 더 자세한 내용과 활용 방법은 아래 링크를 참고하시면 좋을 것 같습니다.
Selecting the number of clusters with silhouette analysis on KMeans clustering

 

 

군집 응집도, 비지도 학습의 한계

앞서 k-means 알고리즘을 사용할 때 활용 가능한 2가지 군집 응집도 계산 방법을 살펴보았는데요, 그 어느 것도 적정 군집수를 마법처럼 콕 집어 알려주지는 않습니다. 다만, 아주 잘못된 결과를 처음부터 만드는 우를 범하지 않도록 시행착오를 줄여주는 데에 유용하게 사용할 수 있을 것으로 보여집니다. 또한, 앞서 말씀드렸던 것처럼 비지도 학습은 정답이 없기 때문에 군집화 결과물을 평가하기 위해서는 결국 사람이 직접 확인하는 과정을 거칠 수밖에 없기도 합니다.

실제로 저희 팀에서 최근에 진행한 고객세분화 프로젝트에서는 데이터 준비 작업과 군집화보다 1)군집화 결과물을 이해하기 쉽게 시각화하고, 2)현업(마케터, PO 등) 담당자들과 군집화가 잘 되었는지 검토하는 과정에 훨씬 많은 시간을 쏟았던 것으로 기억합니다. 물론 이 과정에서 군집의 수와 데이터 추출 조건을 달리하여 수차례 군집화 작업을 다시 진행한 것은 당연한 일이겠지요. 프로파일링(군집별로 특성을 요약&시각화) 작업만 10번 가까이 반복했던 것으로 기억합니다. 그 과정에서 일부 클러스터(군집)는 활용 목적에 맞게 임의로 통합하는 작업을 병행하기도 했습니다.

결국 클러스터링 분석 작업에서 납득할 만한, 그리고 현업에서 활용 가능한 결과물을 만들어내기 위해서는 온전히 기계에만 의존하는 것은 한계가 있습니다. 이것은 비단 k-means를 활용하는 작업뿐만 아니라 다른 알고리즘을 사용한 군집화 작업에서도 마찬가지입니다. 이렇게 보면 클러스터링 분석 결과물의 퀄리티는 ‘공들인 시간’과 상관관계가 높을 수도 있을 것 같네요.


오늘 이야기는 여기서 마치겠습니다. 긴 글 읽어주셔서 감사합니다. 😀

 


클러스터링 작업뿐만 아니라 여러 학습 과정에서 아래 블로그의 도움을 많이 받았습니다. 감사합니다.
매우 유명한 블로그들이고 제가 다루는 것보다 훨씬 깊이 있는 내용을 자세히 배울 수 있습니다.

조대협의 블로그
ratsgo’s blog
TOTAL DATA SCIENCE

 

 

 

반응형

댓글