본문 바로가기

카테고리 없음

K-means clustering에 대해 알아봅시다 :)

k-means 알고리즘은 예전 글에서 설명했던 지도학습(Supervised Learning)과 비지도학습(Unsupervised Learning) 중 비지도학습에 속합니다. 그리고 클러스터링, 군집분석의 대표격이라고 할 수 있습니다. 주어진 k개의 데이터를 k개의 군집으로 묶는 알고리즘으로 데이터들과 각 군집간의 거리 차리의 분산을 최소화합니다. 파이썬에서는 sklearn 패키지에서 함수를 제공합니다.

 

비지도학습(Unsupervised Learning)

훈련 데이터로부터 하나의 함수를 추론하는 방법 중 하나로, 지도학습과 달리 데이터에서 추출하고자 하는 라벨(label)이 없는 데이터를 이용해 함수를 추론하는 것으로 일반적으로 클러스터링(군집)을 위해 사용된다.

 

클러스터링(군집)

라벨(label) 데이터 없이 데이터 각각의 특성을 고려해 주어진 데이터를 가장 잘 설명하는 집단을 찾아 속하게 하는 것(나누는 것)

 

k-means 알고리즘의 원리는 군집 내의 응집도를 최소화하고, 분리도는 최대화하여 군집을 나눕니다. 응집도를 최소화하는 것은 클러스터 데이터와 클러스터 중심 값과의 거리 합인데요, 이것을 최소화합니다. 분리도는 클러스터의 중심값과 다른 클러스터의 중심값과의 거리이고 이것을 최대화해야 합니다.

 

그렇다면 거리는 어떻게 구하냐하면, k-means 알고리즘은 유클리드 거리 측정법이라는 거리공식을 사용합니다. 그래서 중심에서 멀리 떨어져 있어도 반복적으로 중심을 수정해나갈 수가 있습니다. 또한 벡터 사이의 거리가 짧으면 유사성이 더 높다는 것을 의미하죠. 유클리드 거리 측정법은 다음과 같은 공식을 이용합니다.

이 유클리드 거리가 큰 값을 가지면 사용자 간의 거리가 멀다는 의미이기 때문에 사용자 간 유사성이 떨어짐을 의미합니다.

 

k-means 알고리즘의 수행단계는 다음과 같습니다.

(0) 전체 클러스터의 개수 K값을 설정한다.

(1) (초기 중심값 선택)K개의 그룹으로 군집한 n개의 점을 가지고 있고 여기서 임의로 k개의 점을 선택하여 k개의 클 러스터의 초기 중심값(centroid)을 정한다.

(2) (클러스터할당) k개의 클러스터의 중심값과 각 개별점(데이터)간의 거리를 측정하여 가장 가까운 클러스터에 해당 데이터를 할당한다. 여기서 거리 측정은 유클리드 거리 측정법을 사용한다.

Note! 이때, 데이터는 다른 클러스터 중심값들보다 할당된 클러스터의 중심값과 가장 가깝다. \

(3) (새로운 중심값 선택) 각 클러스터마다 그 안에 배정된 모든 점들 간의 거리평균값을 구하여 새로운 중심값으로 정 한다.

(4) 만약, 새로운 중심값들이 이전의 중심값들과 동일하다면 알고리즘을 끝내고 그렇지 않으면 (2)~(4) 단계를 계속 반 복 한다.

 

이제 실습을 진행해보겠습니다.

 

 

kmean군집분석정리
In [1]:
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline

먼저 필요한 도구 들을 불러와 줍니다. 당연하게 kmeans도 불러오고, 가우시안 값들로 이루어진 샘플데이터셋도 생성해 줍니다.

In [2]:
np.random.seed(0)

centers = [[1, 1], [0, 0], [2, -1]]

data, labels_true = make_blobs(n_samples = 2000, centers = centers, 
                               cluster_std = 0.7)

임의의 난수 값들을 생성하고, 불러온 데이터의 중심점들, 2000개의 배열 형태로 이루어진 클러스터 대상 데이터, 데이터의 실제 라벨을 설정해줍니다. 시드 값이란 난수를 생성할 때 사용되는 초기값입니다. 그래서 같은 시드값을 설정하면 같은 난수 값들을 생성합니다.

In [3]:
data.shape
Out[3]:
(2000, 2)
In [4]:
print(data)
print()
print(labels_true)
print(np.unique(labels_true))
[[ 2.88735684  0.94825273]
 [ 0.00712986  1.53880744]
 [ 0.3264657  -0.06607475]
 ...
 [ 0.53901292  0.64003622]
 [ 1.65065358  1.40755721]
 [ 0.74131908 -0.71579507]]

[0 1 1 ... 0 0 1]
[0 1 2]

배열 값 중 중복을 제거하고 다른 값들을 추출해 줍니다.

In [5]:
plt.figure(figsize=(15,10))
plt.scatter(data[:,0], data[:,1])
Out[5]:
<matplotlib.collections.PathCollection at 0x1996bb790b8>

이제 데이터들을 삼점도로 확인해봅니다.

In [6]:
# compute clustering with KMeans
estimator = KMeans(init = 'k-means++', n_clusters = 3, n_init = 10)
estimator.fit(data)
Out[6]:
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
       n_clusters=3, n_init=10, n_jobs=None, precompute_distances='auto',
       random_state=None, tol=0.0001, verbose=0)

이제 모델을 학습시킬 차례입니다. kmeans를 수행하는 함수를 이용해서 훈련을 시켜줍니다. 초기 중심값을 3개로 정했으니 3개의 군집으로 나눠보겠습니다.

In [8]:
labels_predict = estimator.labels_
np.unique(labels_predict)
Out[8]:
array([0, 1, 2])
각 데이터의 라벨을 학습한 모델로 예측한 라벨데이터로 만들어 줍니다.
In [9]:
cm = plt.cm.get_cmap('jet')
scaled_labels = (labels_predict - np.min(labels_predict)) 
scaled_labels = scaled_labels /(np.max(labels_predict) - np.min(labels_predict))
np.unique(scaled_labels)
Out[9]:
array([0. , 0.5, 1. ])

jet는 칼라맵의 변수이고, 예측한 라벨데이터를 정규화해줍니다.

In [10]:
plt.figure(figsize=(15,10))
plt.scatter(data[:,0], data[:,1], c = cm(scaled_labels))
Out[10]:
<matplotlib.collections.PathCollection at 0x1996bba2e48>

결과를 확인해보면 중심값들을 기준으로 군집들이 형성된 것을 확인할 수 있습니다. 군집분석은 아주 유용한 분석도구 중의 하나이기 때문에 조금 더 심화된 내용들을 꾸준히 업로드 할 것입니다. 참고해주세요 :)