without haste but without rest
08. Clustering - K-means, Hierarchical 본문
0. 개요
- 앞으로 다룰 4가지 학습은 비지도 학습이다. - k-mean, hierarchical, dbscan, spectral
(1) k-means
- 유저가 hyperparameter value인 k를 인위적으로 정하고 군집을 k개 만큼 만든다.
(2) hierarchical clustering (계층적 군집화)
- 두 점의 거리를 기준으로 군집화 해 나가는 방법
- 단 이때 정해준 리미트 거리(y 값)에 따라서 군집의 개수가 달라진다.
- 계산량이 많다.
- 거리에 따른 군집 개수는 dendrogram으로 확인 할 수 있다.
(3) 실루엣 스코어
- 클러스터링 모델을 평가하는 스코어
1. 샘플 데이터 생성
import pandas as pd
import seaborn as sns
sns.set_context("paper", font_scale = 1.5)
sns.set_style("white")
## 클러스터링 알고리즘 학습을 위한 가상 자료 생성 ##
###########################################################################
from sklearn import datasets
def make_blobs():
# build blobs for demonstration
n_samples = 1500
blobs = datasets.make_blobs(n_samples = n_samples,
centers = 5,
cluster_std = [3.0, 0.9, 1.9, 1.9, 1.3],
random_state = 51)
# create a Pandas dataframe for the data
df = pd.DataFrame(blobs[0], columns=['Feature_1', 'Feature_2'])
df.index.name = 'record'
return df
df = make_blobs()
print(df.head(10))
# plot scatter of blob set
sns.lmplot(x = 'Feature_2', y = 'Feature_1',
data = df, fit_reg=False)
2. k-means
(1) 2~6개 군집으로 군집화 해보기
## k-means 클러스터링 ##
###########################################################################
from sklearn.cluster import KMeans
## k = 2
clus = KMeans(n_clusters = 2, tol = 0.004, max_iter = 300)
# fit to input data
clus.fit(df)
# get cluster assignments of input data and print first five labels
df['K-means Cluster Labels'] = clus.labels_
print(df['K-means Cluster Labels'][:5].tolist())
df.head()
## 클러스터링 결과 시각화 ##
sns.lmplot(x = 'Feature_2', y = 'Feature_1',
hue = "K-means Cluster Labels", data = df, fit_reg = False)
## k = 3
clus = KMeans(n_clusters = 3, tol = 0.004, max_iter = 300)
# fit to input data
clus.fit(df)
# get cluster assignments of input data and print first five labels
df['K-means Cluster Labels'] = clus.labels_
print(df['K-means Cluster Labels'][:5].tolist())
## 클러스터링 결과 시각화 ##
sns.lmplot(x = 'Feature_2', y = 'Feature_1',
hue = "K-means Cluster Labels", data = df, fit_reg = False)
## k = 4
clus = KMeans(n_clusters = 4, tol = 0.004, max_iter = 300)
# fit to input data
clus.fit(df)
# get cluster assignments of input data and print first five labels
df['K-means Cluster Labels'] = clus.labels_
print(df['K-means Cluster Labels'][:5].tolist())
## 클러스터링 결과 시각화 ##
sns.lmplot(x = 'Feature_2', y = 'Feature_1',
hue = "K-means Cluster Labels", data = df, fit_reg = False)
## k = 5
clus = KMeans(n_clusters = 5, tol = 0.004, max_iter = 300)
# fit to input data
clus.fit(df)
# get cluster assignments of input data and print first five labels
df['K-means Cluster Labels'] = clus.labels_
print(df['K-means Cluster Labels'][:5].tolist())
## 클러스터링 결과 시각화 ##
sns.lmplot(x = 'Feature_2', y = 'Feature_1',
hue = "K-means Cluster Labels", data = df, fit_reg = False)
## k = 6
clus = KMeans(n_clusters = 6, tol = 0.004, max_iter = 300)
# fit to input data
clus.fit(df)
# get cluster assignments of input data and print first five labels
df['K-means Cluster Labels'] = clus.labels_
print(df['K-means Cluster Labels'][:5].tolist())
## 클러스터링 결과 시각화 ##
sns.lmplot(x = 'Feature_2', y = 'Feature_1',
hue = "K-means Cluster Labels", data = df, fit_reg = False)
군집 개수를 2개부터 6개까지 설정해서 군집화를 진행했다. 그런데 사람의 눈으로는 어떤 군집이 최적인지 판단하기가 어렵다. 따라서 루소가 제안한 실루엣 스코어를 기준으로 군집의 개수를 선택한다.
실루엣 스코어는 -1~1 사이의 값을 가지며 1에 가까울 수록 최적화가 되었다는 뜻이며, -1에 가까울수록 이질적이라는 의미이다.
(2) 실루엣 스코어로 군집 개수 결정하기
## 클러스터 수 결정 ##
from sklearn import metrics
# create list of k values to test and then use for loop
n_clusters = [2, 3, 4, 5, 6, 7, 8]
for k in n_clusters:
kmeans = KMeans(n_clusters = k, random_state = 42).fit(df)
cluster_labels = kmeans.predict(df)
S = metrics.silhouette_score(df, cluster_labels)
print("n_clusters = {:d}, silhouette score {:1f}".format(k, S))
군집이 6개일 때 0.56으로 가장 높은 스코어를 기록했다. 하지만 군집이 5개일 때와 큰 차이가 아니므로 군집이 5개인 모델을 선택하는 것도 고려해볼 수 있다.
3. hierarchical clustering
(1) 샘플 데이터 생성
## 계층적 클러스터링 알고리즘 ##
## 순차적으로 가까운 점들끼리 군집을 만들어 나가는 군집화 방법
## 자료 수가 많아지면 계산량이 기하급수적으로 많아진다.
## Agglomerative clustering == hierarchical clustering
###########################################################################
## 알고리즘 스케치
data = {'x': [1, 2, 2, 4, 5], 'y': [1, 1, 4, 3, 4]}
data = pd.DataFrame(data)
print(data)
# plot scatter of blob set
sns.lmplot(x = 'x', y = 'y',
data = data, fit_reg=False)
(2) 과정 - 각 점들의 거리를 확인하며 군집화
from scipy.spatial.distance import pdist, squareform
distances = pdist(data.values, metric = 'euclidean') ** 2
print(distances)
dist_matrix = squareform(distances)
print(dist_matrix)
scipy의 pdist, squareform 라이브러리로 생성한 각 점들의 거리다. (0, 1) 좌표는 첫번째 점과 두 번째 점과의 거리다 두 점의 거리가 1로 제일 가까우므로 첫 번째 군집화 대상이 될 것이다.
data['cluster'] = [0, 0, 1, 2, 3]
data_0 = data.groupby('cluster').mean()
print(data_0.values)
1, 2번째 데이터를 인위적으로 0번 그룹으로 묶어주고 평균을 계산한다. (1, 1) 과 (2, 1) 좌표 간의 거리의 평균인 (1.5, 1)이 새로운 좌표가 된다. 1, 2번 데이터의 중간 위치다.
distances = pdist(data_0.values, metric = 'euclidean') ** 2
dist_matrix = squareform(distances)
print(dist_matrix)
군집화한 데이터를 다시 유클리디안 거리를 기준으로 거리를 계산한다. 이번에는 2, 3 번째 컬럼에 있는 값들 끼리의 거리 차이가 가장 작으므로 두 점을 군집화할 것이다.
data['cluster'] = [0, 0, 1, 2, 2]
data_0 = data.groupby('cluster').mean()
print(data_0.values)
군집화한 새로운 점(데이터)들의 값이다. 군집화를 하면 두 점의 평균 거리로 새롭게 이동한다. (4, 3) (5, 4) 였으므로 평균 값인 (4.5, 3.5) 좌표가 군집의 중앙이 되는 것이다.
distances = pdist(data_0.values, metric = 'euclidean') ** 2
dist_matrix = squareform(distances)
print(dist_matrix)
군집화한 새로운 좌표들 간의 거리다. 1, 2번 그룹들 간의 거리가 6.5로 가장 작으므로 다시 군집화할 수 있다.
distances = pdist(data_0.values, metric = 'euclidean') ** 2
dist_matrix = squareform(distances)
print(dist_matrix)
0, 1번 데이터와 2, 3, 4 데이터가 두 군집으로 구분되는 상태며 위 좌표는 두 군집의 중심 좌표이다.
distances = pdist(data_0.values, metric = 'euclidean') ** 2
dist_matrix = squareform(distances)
print(dist_matrix)
두 군집의 거리는 11.8이다.
(3) dendrogram
# ward distance
from scipy.cluster.hierarchy import linkage, dendrogram
z = linkage(data.values[:, :2], 'single')
dendrogram(z)
"""
덴드로그램은 y축 크기를 기준으로 클러스터를 어떻게 묶을 수 있는지
겹쳐진 바 차트로 직관적으로 보여줌
ward -> linkage, 연결에 필요한 거리 기준
"""
덴드로그램은 거리 (y 값)을 기준으로 어떤 데이터들끼리 군집이 될 수 있는지 보여준다. 따라서 순서까지도 파악할 수 있다. 제일 첫 번째로 1.0 부근에서 0, 1번 째 데이터들끼리 군집이 되고 1.5 조금 아래에서 3, 4번 째 데이터들이 군집화가 된다. ...
(4) ward distance
새로운 데이터가 군집에 들어왔을 때의 거리를 계산하는 방법으로 ward가 제안한 방법이다. (깊게 들어가면 통계적이므로 일단은 linkage 옵션에 ward 를 지정해준다는 거 정도로만 알아둔다.)
(5) evalueate
## 가상자료 계층적 클러스터링
from IPython.display import Image
Image("./hca_dendrogram.jpg")
*데이터는 제일 위에서 만든 데이터 프레임
from sklearn.cluster import AgglomerativeClustering
clus = AgglomerativeClustering(n_clusters = 5,
affinity = 'euclidean', linkage = 'ward')
# fit to input data
clus.fit(df)
# get cluster assignments
df['HCA Cluster Labels'] = clus.labels_
sns.lmplot(x = 'Feature_2', y = 'Feature_1',
hue = "HCA Cluster Labels", data = df, fit_reg = False)
n_clusters = [2, 3, 4, 5, 6, 7, 8]
for num in n_clusters:
HCA = AgglomerativeClustering(n_clusters = num,
affinity = 'euclidean', linkage = 'ward',
memory = './model_storage/dendrogram',
compute_full_tree = True)
cluster_labels= HCA.fit_predict(df)
S = metrics.silhouette_score(df, cluster_labels)
print("n_clusters = {:d}, silhouette score {:1f}".format(num, S))
계층적 군집화는 군집이 5개일 때 실루엣 스코어가 가장 높은 결과를 보인다.
4. 클러스터링 모델 성능 비교
1번 테스트에서는 density가 좋은 결과를 낸것이라고 할 수 있다.
2번 테스트에서는 k-means가 좋지 않은 결과를 보인다.
3번 테스트에서도 k-means가 좋지 않은 결과다.
4번 테스트는 데이터들이 비교적 멀리 떨어져 있어서 모든 모델이 좋은 성능을 보인다.
5번 테스트에서는 k-means가 좋지 않아 보이고 hierarchical, spectral 이 좋은 결과를 냈다.
6번 테스트에서는 k-means가 가장 좋지 않고 density가 가장 좋은 결과를 보인다.
보통 통계학자들은 k-means를 가장 선호한다고 한다.
density, spectral은 조금 더 요구조건이 있다고 한다. (다음 주차 수업때 다룬다.)
'Homework > DataMining' 카테고리의 다른 글
10. OLS, SGD (0) | 2020.05.26 |
---|---|
09. Clustering - dbscan, spectal (0) | 2020.05.19 |
07. PCA(Pincipal Component Analysis) (0) | 2020.05.05 |
06. Feature Selection (0) | 2020.05.01 |
05. One-Hot Encoding (0) | 2020.05.01 |