빅데이터 K 평균(K Means) 구현하기

1. 빅 데이터 K 평균(K Means) 구현하기

  • 클러스트 중심 또는 평균 기반 클러스터링 k-means
from sklearn.cluster import KMeans
import numpy as np  # 연산처리를 용이하게 하기 위해 사용함
import pandas as pd # 데이터 포인트를 만들기 위해 사용함
import seaborn as sb 
import matplotlib.pyplot as plt # 데이터 시각화를 위해 사용함
%matplotlib inline

데이터 설정하기

df = pd.DataFrame(columns={'x','y'})
df.loc[0] = [2,3]
df.loc[1] = [2,11]
df.loc[3] = [2,18]
df.loc[4] = [4,3]
df.loc[5] = [3,3]
df.loc[6] = [1,5]
df.loc[7] = [2,3]
df.loc[8] = [2,3]
df.loc[9] = [2,3]
df.loc[10] = [8,5]
df.loc[11] = [3,1]
df.loc[12] = [5,3]
df.loc[13] = [8,9]
df.loc[14] = [5,6]
df.loc[15] = [4,3]
df.loc[16] = [4,3]
df.loc[17] = [2,3]
df.loc[18] = [2,3]
df.loc[19] = [7,8]
df.loc[20] = [8,7]
df.loc[21] = [2,3]
df.loc[22] = [2,3]
df.loc[23] = [4,3]
df.loc[24] = [12,3]
df.loc[25] = [2,3]
df.loc[26] = [2,3]
df.loc[27] = [2,3]
df.loc[28] = [2,3]
df.loc[29] = [2,3]

df.head(30)
x y
0 2 3
1 2 11
3 2 18
4 4 3
5 3 3
6 1 5
7 2 3
8 2 3
9 2 3
10 8 5
11 3 1
12 5 3
13 8 9
14 5 6
15 4 3
16 4 3
17 2 3
18 2 3
19 7 8
20 8 7
21 2 3
22 2 3
23 4 3
24 12 3
25 2 3
26 2 3
27 2 3
28 2 3
29 2 3

데이터 시각화

# seaborn 라이브러리를 이용
sb.lmplot('x','y',data=df,fit_reg=False, scatter_kws={"s":100})
C:\Users\MyCom\anaconda3\envs\tfgpu\lib\site-packages\seaborn\_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning





<seaborn.axisgrid.FacetGrid at 0x28a0897c438>

output_9_2

2. k-means clustering

from sklearn.datasets import make_blobs
import pandas as pd
import numpy as np
import math
import scipy as sp
import seaborn as sns
import matplotlib.pyplot as plt

sns.set_palette("Set2")

Scikit-Learn은 머신러닝을 위한 파이썬 패키지이며, clustering을 할 수 있는 가상의 데이터셋을 만들어주는 함수들을 제공한다. 오늘은 그 중 하나인 make_blobs()를 사용해서 데이터셋을 만들어보자.

x, y = make_blobs(n_samples=100, centers=4, n_features=2, random_state=6)
points = pd.DataFrame(x, y).reset_index(drop=True)
points.columns = ["x", "y"]
points.head()
x y
0 0.276181 -2.217047
1 7.927368 -9.761527
2 8.491428 -2.549749
3 -11.537102 2.434883
4 4.292259 -8.992204

Step 1. k값 정하기

k-means clustering이란 이름에서 알 수 있듯이 주어진 데이터셋을 k개의 중심점을 기준으로 하여 그룹짓는 방법이다. 따라서, 중심점을 몇 개로 할 것인지를 미리 정해줘야 한다.

sns.scatterplot(x="x", y="y", data=points, palette="Set2");

output_15_0

위 그래프는 우리가 만든 데이터셋을 scatter plot으로 그려본 것이다. 데이터의 분포를 보니 k값이 4 정도면 적당한 cluster들을 얻을 수 있을 것 같다. 따라서, k=4로 해보자.

Step 2. 중심점(Centroid) 구하기

k값을 정했으니 이제 중심점을 구해야 한다. 중심점이란 말 그대로 각 cluster의 중심 좌표를 말한다. 2차원 데이터를 예로 들면 각 cluster의 중심점은 각 cluster의 x좌표의 평균과 y좌표의 평균이 된다. 단, clustering을 시작할 때는 아직 cluster가 생성되지 않았고 따라서 cluster의 중심점을 구할 수 없기 때문에 전체 데이터 중에서 랜덤한 k개의 데이터를 중심점으로 사용한다.

centroids = points.sample(4, random_state=1)
centroids
x y
80 -8.842286 1.786914
84 4.510561 -9.305970
33 5.883975 -8.372845
81 -8.831594 1.690414

위와 같이 전체 데이터 중에서 4개를 랜덤하게 골라 첫번째 중심점으로 삼았다.

Step3. 각 중심점으로부터의 거리를 구하여 가까운 중심점의 cluster로 할당하기

각 데이터에 대해서 4개의 중심점과의 거리를 계산한다. 그 후 값을 비교하여 가장 가까운 중심점의 cluster로 해당 데이터를 할당한다.

# 각 데이터에 대하여, 각 중심점과의 유클리드 거리 계산
distance = sp.spatial.distance.cdist(points, centroids, "euclidean")

# 가장 거리가 짧은 중심점의 cluster로 할당
cluster_num = np.argmin(distance, axis=1)

# 결과 확인
result = points.copy()
result["cluster"] = np.array(cluster_num)
result.head()
x y cluster
0 0.276181 -2.217047 1
1 7.927368 -9.761527 2
2 8.491428 -2.549749 2
3 -11.537102 2.434883 0
4 4.292259 -8.992204 1

위와 같이 각 데이터에 대하여 해당하는 cluster 번호를 구했다. 이를 cluster 별로 색을 다르게 해서 scatter plot으로 그려보면 아래와 같다.

sns.scatterplot(x="x", y="y", hue="cluster", data=result, palette="Set2");

output_23_0

Step 4. 변경된 cluster에 대해서 중심점 구하기

각 cluster에 대해서 중심점을 구해보자. 위에서 언급했듯이, 2차원 데이터셋일 때 cluster의 중심점은 x좌표의 평균과 y좌표의 평균이다.

# cluster별로 묶어서 평균 계산
centroids_2 = result.groupby("cluster").mean()
centroids_2
x y
cluster
0 -8.211603 2.420481
1 1.913263 -5.034035
2 6.180105 -5.007395
3 -5.728498 0.878158

Scikit-Learn을 이용해보자

Scikit-Learn은 k-means clustering을 보다 편하게 수행할 수 있도록 관련 함수를 제공한다.

from sklearn.cluster import KMeans 

# k-means clustering 실행
kmeans = KMeans(n_clusters=4)
kmeans.fit(points)

# 결과 확인
result_by_sklearn = points.copy()
result_by_sklearn["cluster"] = kmeans.labels_
result_by_sklearn.head()
x y cluster
0 0.276181 -2.217047 2
1 7.927368 -9.761527 0
2 8.491428 -2.549749 3
3 -11.537102 2.434883 1
4 4.292259 -8.992204 0
sns.scatterplot(x="x", y="y", hue="cluster", data=result_by_sklearn, palette="Set2");

output_28_0