Post

머신러닝 공부 - K-Means 클러스터링 쉽게 이해하기

군집화(Clustering)란 무엇인가

만약 우리가 다루는 데이터에 “레이블”이 붙어 있다면 지도학습, 즉 미리 가지고 있는 데이터와 레이블을 기반으로 예측이나 분류를 수행하는 모델을 만들 수 있다. 그러나 실제로는 레이블(분류)이 없는 경우가 더 많다. 물론 이렇게 별도의 레이블이 없는 데이터 안에서 패턴과 구조를 발견하는 비지도 학습도 머신러닝의 큰 축이고, 그 중 가장 대표적인 비지도 학습 기술이 바로 Clustering(군집화)이다.

참고로 지도학습 Classification(분류)과 엄연히 다른 거다. Classification은 미리 레이블이 붙어 있는 데이터들을 학습해서 그걸 바탕으로 새로운 데이터에 대해 분류를 수행하지만, Clustering은 레이블을 모르더라도 그냥 비슷한 속성을 가진 데이터들끼리 묶어주는 역할을 하기 때문이다.

아무튼 클러스터링, 군집화를 사용하는 예로는 아래와 같은 것들을 들 수 있다.

  • 추천 엔진 : 사용자 경험을 개인화하기 위해 비슷한 제품 묶어주기
  • 검색 엔진: 관련 주제나 검색 결과 묶어주기
  • 시장 세분화(segmentation): 지역, 인구 통계, 행동에 따라 비슷한 고객들 묶어주기

군집화의 목표

군집화의 목표는 서로 유사한 데이터들은 같은 그룹으로, 서로 유사하지 않은 데이터는 다른 그룹으로 분리하는 것이 된다.

그러면 자연스럽게 2개의 질문이 따라올 거다.

  • 몇 개의 그룹으로 묶을 것인가
  • 데이터의 “유사도”를 어떻게 정의할 것인가 (유사한 데이터란 무엇인가)

이 두 질문을 해결할 수 있는 가장 유명한 전략이 바로 K-Means 알고리즘이다.

K-Means 군집화의 원리

  • “K“는 데이터 세트에서 찾을 것으로 예상되는 클러스터(그룹) 수를 말한다.
  • “Means“는 각 데이터로부터 그 데이터가 속한 클러스터의 중심까지의 평균 거리를 의미한다. (이 값을 최소화하는 게 알고리즘의 목표가 된다.)

K-Means에서는 이걸 구현하기 위해 반복적인(iterative) 접근을 취한다.

  1. 일단 K개의 임의의 중심점(centroid)을 배치하고
  2. 각 데이터들을 가장 가까운 중심점으로 할당한다. (일종의 군집을 형성한다.)
  3. 군집으로 지정된 데이터들을 기반으로 해당 군집의 중심점을 업데이트한다.
  4. 2번, 3번 단계를 그래서 수렴이 될 때까지, 즉 더이상 중심점이 업데이트 되지 않을 때까지 반복한다.

그림으로 보면 아래와 같다.

K-means_convergence

여기서 일단 k 값은 3이다. 그래서 일단 중심점 3개를 아무 데나 찍고, 각 데이터들을 3개의 중 가까운 곳으로 할당한다. 그리고 그렇게 군집이 지정된 상태로 중심점을 업데이트 한다. 그리고 업데이트 된 중심점과 각 데이터들의 거리를 구해서 군집을 다시 할당하는 거다. 이 과정을 계속 반복하는 것.

아무튼 이렇게 군집화를 해놓으면 새로운 데이터가 들어와도 그게 어떤 군집에 속할지 할당해줄 수 있게 되는 셈이다.

scikit-learn 사용법

파이썬 라이브러리 scikit-learn를 사용하면 K-means를 매우 쉽게 적용해볼 수 있다.

1
2
3
4
5
6
from sklearn.cluster import KMeans

model = KMeans(n_clusters=k)
model.fit(data)

model.predict(samples)

K값(군집의 개수) 정하기

군집화를 하기 위해서는 몇 개의 군집이 적절할지 결정해야 하는데, 그러려면 일단 “좋은 군집”이란 무엇인지 정의할 수 있어야 한다.

만약 군집화가 잘 되었면 각 군집의 샘플이 가까운 거리에서 오밀조밀하게 묶일 거다. 군집 내의 데이터들이이 얼마나 퍼져 있는지 (혹은 얼마나 뭉쳐있는지) 응집도는 inertia 값으로 확인한다. inertia는 각 데이터로부터 자신이 속한 군집의 중심까지의 거리를 의미하기 때문에 inertia 값이 낮을수록 군집화가 더 잘 됐다고 볼 수 있는 거다.

sciklit-learn으로 모델을 만들었다면 이렇게 찍어보면 끝이다.

1
print (model.inertia_)

그래서 군집의 개수, 즉 k 값을 바꿔가면서 inertia를 그래프로 확인해볼 수 있는데,

1
2
3
4
5
6
7
8
9
10
11
12
num_clusters = list(range(1, 9))	# K는 1 ~ 8사이의 정수입니다
inertias = []

for i in num_clusters:
    model = KMeans(n_clusters=i)
    model.fit(samples)
    inertias.append(model.inertia_)

plt.plot(num_clusters, inertias, '-o')
plt.xlabel('Number of Clusters (k)')
plt.ylabel('Inertia')
plt.show()

number-of-clusters

k값이 증가하면 intertia 값은 감소하다가 어느정도 수준이 되면 거의 변화를 안 보이게 된다. 그래서 너무 많지 않은 군집의 개수로 분류하면서도 intertia 값이 작은 상태, 그 최적의 값을 찾으면 된다. (이러한 방법을 “elbow” 메소드라고 부른다. 팔꿈치처럼 그래프가 꺾이는 관절 부분을 찾아낸다는 뜻. )

위의 그래프를 예로 들면 최적의 클러스터 수는 3으로 보인다.

K-Means 군집화의 단점

K-Means 클러스터링 알고리즘은 소개된지 거의 반세기가 지났지만, 여전히 머신 러닝에 가장 널리 사용되는 클러스터링 알고리즘 중 하나다.

그러나 K-Means 알고리즘의 가장 큰 단점은 처음에 지정하는 중심점(centroid)의 위치를 무작위로 결정하기 때문에 최적의 클러스터로 묶어주는 데에는 한계가 있다는 거다.

그래서 이 K-Means의 새로운 버전이라고 할 수 있는 K-Means++ 알고리즘에 대해서도 알고 갈 필요가 있다. K-Means++는 전통적인 K-Means의 문제, 즉 중심점 무작위 선정의 문제를 해결하기 위해 생겨난 거라고 보면 된다.

K-Means++ 군집화

전통적인 K-Means는 아래와 같은 원리로 진행된다.

  1. 일단 K개의 임의의 중심점(centroid)을 배치하고
  2. 각 데이터들을 가장 가까운 중심점으로 할당한다. (일종의 군집을 형성한다.)
  3. 군집으로 지정된 데이터들을 기반으로 해당 군집의 중심점을 업데이트한다.
  4. 2번, 3번 단계를 그래서 수렴이 될 때까지, 즉 더이상 중심점이 업데이트 되지 않을 때까지 반복한다.

그러나 K-Means++는 좀 다르다. K-Means에서 가장 첫번째 단계, 즉 중심점을 배치하는 걸 그냥 임의로 하는 대신 좀 더 신중하게(?) 하는 거다.

  1. (일단 아무 공간에나 중심점을 k개 찍고 시작하는 게 아니라) 가지고 있는 데이터 포인트 중에서 무작위로 1개를 선택하여 그 녀석을 첫번째 중심점으로 지정한다.
  2. 나머지 데이터 포인트들에 대해 그 첫번째 중심점까지의 거리를 계산한다.
  3. 두번째 중심점은 각 점들로부터 거리비례 확률에 따라 선택한다. (뭔 소리야?) 즉, 이미 지정된 중심점으로부터 최대한 먼 곳에 배치된 데이터포인트를 그 다음 중심점으로 지정한다는 뜻이다.
  4. 중심점이 k개가 될 때까지 2, 3번을 반복한다.

그리고 scikit-learn에서 K-Means++를 사용하고 싶다면, 모델을 불러올 때 init='k-means++'만 넣어주면 된다.

1
2
3
from sklearn.cluster import KMeans

model = KMeans(n_clusters=k,  init='k-means++')

사실 기본값이 k-means++라 따로 지정 안 해주면 알아서 ++로 돌린다. 오히려 전통적인 k-means로 중심점을 랜덤하게 지정하고 싶으면 init='random'을 써줘야 한다.

아무튼 K-means++는 전통적인 K-Means에 비해 이런 장점이 있다고 요약해볼 수 있겠다.

  • 초기 중심점을 더욱 전략적으로 배치하기 때문에 전통적인 K-Means보다 더 최적의 군집화를 할 수 있다.
  • K-Means보다 알고리즘이 수렴하는 속도가 빠르다. 전통적인 K-Means를 사용하면 초기 중심점이 (재수 없게) 잘못 지정되는 경우 알고리즘이 수렴하는 데 시간이 오래 걸릴 수 있기 때문이다.
This post is licensed under CC BY 4.0 by the author.