[Python] Hierarchical clustering(계층적 군집분석)

2020. 8. 9. 16:40ML in Python/Python

 

 이 게시글은 오로지 파이썬을 통한 실습만을 진행한다. Hierarchical 군집분석의 개념 및 원리를 알고자하면 아래 링크를 통해학습을 진행하면 된다. 

https://todayisbetterthanyesterday.tistory.com/59

 

[Data Analysis 개념] Clustering(2) - Hierarchical clustering / DBSCAN

https://todayisbetterthanyesterday.tistory.com/58 [Data Analysis 개념] Clustering(1) - K-means/K-medoids 1. Clustering - 군집분석  군집분석은 비지도학습(unsupervised learning)의 일종으로 유사한 데..

todayisbetterthanyesterday.tistory.com

 

 Hierarchical Clustering은 Tree기반의 모델이다. 2차원의 데이터의 경우를 생각해보자. 2차원 데이터는 좌표로 가시적으로 군집을 시각화시킬수 있지만, 3차원은 보기가 힘들어진다. 그리고 4차원이 넘어서면, 시각화가 거의 불가능해진다. Hierarchical clustering은 이러한 3차원 이상의 군집에서도 dendogram을 통해 직관적인 cluster 형성이 가능하다는 장점이 있다. 가장 기본적인 Hierarchical Clustering을 먼저 확인해보자. 

 

기본적인 Hierarchical Clustering

# 기본 library
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 실습데이터 형성
X = np.array([[5,3],
    [10,15],
    [15,12],
    [24,10],
    [30,30],
    [85,70],
    [71,80],
    [60,78],
    [70,55],
    [80,91],])
import matplotlib.pyplot as plt

labels = range(1, 11)
plt.figure(figsize=(10, 7))
plt.subplots_adjust(bottom=0.1)
plt.scatter(X[:,0],X[:,1], label='True Position')

for label, x, y in zip(labels, X[:, 0], X[:, 1]):
    plt.annotate(
        label,
        xy=(x, y), xytext=(-3, 3),
        textcoords='offset points', ha='right', va='bottom')
plt.show()

 위의 scatter plot은 raw data를 도식화한 것이다. 여기서 plt.scatter()를 사용하지 않고, plt.annotate()함수를 사용해서 각 점의 위에다가 text와 함께 표시를 해주도록 하였다. 원래 annotation은 그래프에 화살표를 표시하고 화살표에다가 text를 함께 출력하는 것인데, 여기서는 arrowpoint를 지정해주지않아서 화살표에 대한 정의가 없다. 여튼, 이를 통해서 1번 점부터 10번 점까지 반복해서 표기를 한 것이다. 

 

from scipy.cluster.hierarchy import dendrogram, linkage
from matplotlib import pyplot as plt

linked = linkage(X, 'single')

 hierarchical clustering은 scipy.cluster.hierarchy 패키지를 통해서 구현할 수 있다. 그리고 hierarchical clustering의 특성 중 하나인 clustering을 dendogram으로 표현하기 위해서 dendogram 또한 함께 import를 하였다. 

 linkage함수에 인수로 feature data X를 넣었는데 이는 거리를 계산하는 method 알고리즘의 차이이다. scipy에 보다 자세한 설명이 나와있는데 이 자리의 인수는 아래의 종류와 같다. 

labelList = range(1, 11)

plt.figure(figsize=(10, 7))
dendrogram(linked,
            orientation='top',
            labels=labelList,
            distance_sort='descending',
            show_leaf_counts=True)
plt.show()

 학습된 결과를 dendogram을 통해서 시각화하면 위와 같다. leaf node까지 표현되어 10개의 cluster를 만들수 있긴 하지만, 여기서 합당한 cluster 개수는 2로 보인다. 이는 색이 다르게 표현되는 결과를 가져온다.

 이제 기존 데이터를 통해서 실습해보는 과정을 갖자. 

shopping data Hierarchical Clustering

 

 실습에 사용될 데이터는 아래의 데이터이다. 실습을 따라 진행하고 싶다면, 아래 데이터를 python 파일 위치와 같은 경로에 넣어주면 바로 실습이 가능하다. 

shopping-data.csv
0.00MB

 

customer_data = pd.read_csv('./shopping-data.csv')
customer_data.head()

 데이터의 형태는 위와같다. 

data = customer_data.iloc[:, 3:5].values

import scipy.cluster.hierarchy as shc

plt.figure(figsize=(10, 7))
plt.title("Customer Dendograms")
dend = shc.dendrogram(shc.linkage(data, method='ward'))

 이번에는 ward method 알고리즘을 통해서 Hierarchical Clustering을 진행하였다. 이는 거리계산방법의 차이라고 위에서 언급했다. 

 scipy를 통해 Hierarchical Clustering을 실습해보았다. sklearn에는 AgglomerativeClustering (병합군집)이라는 것이 존재한다.

 병합 군집은 계층적 군집을 만들어서 군집이 반복하여 진행되면서 모든 포인트들이 하나의 포인트를 가진 클러스터에서 마지막 클러스터까지 이동하여 최종 군집이 형성되는 것이다. 여기서 주의할 점은 병합군집(agglomerative clustering)은 군집이 한 번 형성되면 군집에 속한 개체가 다른 군집으로 이동할 수 없는 특성을 가지고있다는 점이다. 

 위의 그림을 보면 최초의 중앙점으로 부터 포인트들이 증가해가며 군집이 커지는 모양을 확인할 수 있다. 

from sklearn.cluster import AgglomerativeClustering

cluster = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
cluster.fit_predict(data)

 위의 결과는 군집 분석의 결과이다. sklearn같은 경우는 dendrogram을 통해서 확인하는 함수가 존재하지 않는다. 그렇기에 만약 dendrogram을 통해서 시각화를 진행하고 싶다면 scipy라이브러리를 활용하면 된다. 

plt.figure(figsize=(10, 7))
plt.scatter(data[:,0], data[:,1], c=cluster.labels_, cmap='rainbow')

 군집 형성의 최종 결과를 색이 다른 scatter plot을 통해서 나타낼 수 있다. 

 

Boston House data Hierarchical Clustering

 이 데이터는 shopping data와 다른 데이터이다. 이를 통해서 dendrogram을 형성하고, 병합군집을 동시에 확인해보자. 

Boston_house.csv
0.03MB

 

# 데이터 불러오기
data = pd.read_csv("./Boston_house.csv") 
data.head() # 데이터 확인

target=data['Target']
data = data.drop(['Target'], axis = 1) 
data.shape

plt.figure(figsize=(10, 7))
plt.title("Customer Dendograms")
dend = shc.dendrogram(shc.linkage(data, method='ward'))

 위의 이미지는 scipy의 Hierarchy 라이브러리에서 활용한 dendrogram이다. 

from sklearn.cluster import AgglomerativeClustering

cluster = AgglomerativeClustering(n_clusters=2, affinity='euclidean', linkage='ward')
cluster.fit_predict(data)

 그리고 위의 결과는 sklearn의 agglomerativeClustering을 활용한 결과이다. 

np.mean([x for x, y in zip(target,cluster.fit_predict(data)) if  y == 0])

 y = 0 군집의 평균은 위와 같다. 

np.mean([x for x, y in zip(target,cluster.fit_predict(data)) if  y == 1])

 y = 1 군집의 평균은 위와 같다. 

data.iloc[cluster.fit_predict(data)==0,:].describe()

 

data.iloc[cluster.fit_predict(data)==1,:].describe()

 

기술통계의 요약인 describe()함수를 사용하여 각 변수별 사분위수와 평균/표준편차를 확인할 수 있다. 

 

 이상으로 Hierarchical Clustering과  Agglomerative Clustering을 확인해 보았다. 그리고 이를 dendrogram으로 시각화 하는 과정을 거쳤다. 위에서 보았지만, dendrogram으로 표현한다고 하더라도, 변수가 많아지고 나눠지는 leaf node가 많아지면 너무 많은 data가 plot에 표출되기에 쉽게 보이지는 않는다. 이 과정은 plot을 가공하거나 그렇지 않다면 tree의 depth를 줄이는 방법으로 약간이나마 해소가 가능하긴 하다. 

 다음 clustering model로 DBSCAN과정을 실습해보자.