클러스터링

클러스터링은 자율학습(Unsupervised learning)의 일종으로 아무런 지식이 없는 상태로 데이터들을 분류를 하며 object들을 유사도(similarity)에 근거하여 군집화한다. 아래 그림은 클러스터링이 어떤 것인지 보여주는 그림이다.

1. 클러스터.png

활용 분야

K-means는 다양한 분야에서 사용된다.

  • Image Segmentation
  • Clustering Gene Segementation Data
  • News Article Clustering
  • Clustering Languages
  • Species Clustering
  • Anomaly Detection

알고리즘

데이터는 n개가 있으며 클러스터는 k개가 있다고 가정한다.

k4XcapI.gif

    1. K개의 초기 Centroid(클러스터의 중심이 되는)를 임의로 선택한다.
    1. 각각 objects들을 자기자신과 centroid간 거리를 계산한 뒤 가장 근접한 군집에 할당한다.
    1. 할당된 포인트들의 평균을 계산하여 군집의 중심을 찾는다.
    1. 2번과정과 3번과정을 군집할당 결과가 더이상 없을 때 까지 반복한다.

파이썬 실습

바로 파이썬 실습으로 넘어가보겠다. 실습파일은 git 의 xclara.csv 파일을 사용했다.

1. 데이터 불러오기

from copy import deepcopy
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')

# Importing the dataset
data = pd.read_csv('xclara.csv')
print("Input Data and Shape")
print(data.shape)
data.head()
"Input Data and Shape"
V1    V2
0    2.072345    -3.241693
1    17.936710    15.784810
2    1.083576    7.319176
3    11.120670    14.406780
4    23.711550    2.557729
  • 실습을 위한 라이브러리모듈을 가져온다.
  • head 메서드를 통해 5개의 데이터를 출력하였다.
  • Input Data로는 x축, y축 값을 받아오는 것을 확인하였다.
# Getting the values and plotting it
f1 = data['V1'].values
f2 = data['V2'].values
plt.scatter(f1, f2, c='black', s=7)

3. scatter.png

  • matplot의 점 그래프기능을 이용하여 그래프를 출력하고 확인한다.

2. Centroid 선택하기

X = np.array(list(zip(f1, f2)))

# Number of clusters
k = 3
# X,Y coordinates of random centroids
C_x = np.random.randint(0, np.max(X)-20, size=k)
C_y = np.random.randint(0, np.max(X)-20, size=k)
C = np.array(list(zip(C_x, C_y)), dtype=np.float32)
print(C)
[[73. 83.]
 [ 1. 30.]
 [38. 32.]]
  • 군집의 갯수 k는 3으로 할당한다.
  • k개의 초기 Centroid의 좌표를 임의로 선택한다.
  • Centroid 좌표를 묶어 배열로 생성한다.
# Plotting along with the Centroids
plt.scatter(f1, f2, c='#050505', s=7)
plt.scatter(C_x, C_y, marker='*', s=200, c='r')

4.sc.png

  • Input Data와 임의로 선택했던 Centroid 좌표를 점 그래프를 통해 확인한다.
  • 빨간 별 표시가 임의로 선택한 centroid이다.

3. 데이터 군집화 하기

# Euclidean Distance Caculator
def dist(a, b, ax=1):
    return np.linalg.norm(a - b, axis=ax)
  • 각각의 포인트와 각각의 Centroid간의 유클리드 거리를 계산한다.
  • 이 거리에 대응하는 노름(벡터공간)을 계산하기 위해 numpy의 linalg 서브 패키지의 norm으로 벡터의 길이를 계산한다.
# 업데이트 될 때마다 centroid의 값을 저장하기 위해 배열 C와 동일한 공간에 모두 0으로 할당한다.
# C.shape = (3, 2)
C_old = np.zeros(C.shape)

# input data의 x좌표와 y좌표를 묶어 배열X로 생성한다.
# X와 동일한 크기를 가진 공간에 모두 0으로 할당한다.
X = np.array(list(zip(f1, f2)))
clusters = np.zeros(len(X))

# 새롭게 구한 centroid와 이전 centroid간의 오차를 생성한다.
error = dist(C, C_old, None)

# 오차의 변화가 없을 때 까지 반복한다.
while error != 0:
    # 각각 데이터들과 Centroid간의 거리를 구해서 가장 가까운 군집에 할당한다.
    for i in range(len(X)):
        distances = dist(X[i], C)
        cluster = np.argmin(distances)
        clusters[i] = cluster

    # 이전 Centroid값은 이전에 생성했떤 변수에 저장해놓는다.
    C_old = deepcopy(C)

    # 할당된 것들의 평균을 계산하여 새로운 centroid를 찾아낸다. 그리고 data들에게 label을 부여한다.
    # 다음 새로운 centroid와 이전 centroid의 오차를 계산한다.
    for i in range(k):
        points = [X[j] for j in range(len(X)) if clusters[j] == i]
        C[i] = np.mean(points, axis=0)
    error = dist(C, C_old, None)
  • 각각 데이터들의 군집화를 진행하는 과정이다.
  • 각각 데이터들과 임의의 3개의 Centroid간 가장 가까운 거리를 계산하고 각각 데이터에 라벨을 부여한다.
colors = ['r', 'g', 'b', 'y', 'c', 'm']
fig, ax = plt.subplots()
for i in range(k):
        points = np.array([X[j] for j in range(len(X)) if clusters[j] == i])
        ax.scatter(points[:, 0], points[:, 1], s=7, c=colors[i])
ax.scatter(C[:, 0], C[:, 1], marker='*', s=200, c='#050505')

5. 군집화 완료.png

  • 같은 라벨이 붙은 데이터끼리 군집화한 것을 시각화한것이다.

만약 군집의 갯수 k를 3이아닌 다른 값을 입력하면 어떻게 될까? k를 2,4,5,6 순으로 할당하고 그래프를 확인해 보았다.

6.2.png

6.4.png

6.5.png

6.6.png

잘못된 군집화가 이루어졌으며 매번 실행마다 군집의 크기가 달라졌다.

이제 scikit-learn을 이용한 K-Means Clustering을 진행해보자

scikit-learn clustering

from sklearn.cluster import KMeans

kmeans = KMeans(n_clusters=3)
kmeans = kmeans.fit(X)
labels = kmeans.predict(X)
centroids = kmeans.cluster_centers_
print(C)
print(centroids)
[[ 40.683628  59.715893]
 [  9.478045  10.686052]
 [ 69.92419  -10.119641]]
[[ 40.68362784  59.71589274]
 [ 69.92418447 -10.11964119]
 [  9.4780459   10.686052  ]]
  • sklearn cluster 라이브러리를 사용해서 얻은 centroid와 이전 여러 절차를 거쳐서 얻은 centroid는 동일함을 알 수있다.