TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 머신러닝>

[머신러닝] 군집화: 군집 평가

by 기록자_Recordian 2024. 10. 25.
728x90
반응형
군집화란?
 

[머신러닝] 군집화 (Clustering)

군집화(Clustering) [군집]군집은 비슷한 샘플을 클러스터 또는 비슷한 샘플의 그룹으로 할당하는 작업으로, 데이터 분석, 고객 분류, 추천 시스템, 검색 엔진, 이미지 분할, 준지도 학습, 차원 축소

puppy-foot-it.tistory.com


이전 내용
 

[머신러닝] 군집화: k-평균

군집화란? [머신러닝] 군집화 (Clustering)군집화(Clustering) [군집]군집은 비슷한 샘플을 클러스터 또는 비슷한 샘플의 그룹으로 할당하는 작업으로, 데이터 분석, 고객 분류, 추천 시스템, 검색 엔

puppy-foot-it.tistory.com


군집 평가(Clustering Evaluation)

 

대부분의 군집화 데이터 세트는 비교할 만한 타깃 레이블을 가지고 있지 않고, 분류와 유사해 보일 수 있으나 성격이 많이 다르다.  군집화가 효율적으로 잘 됐는지 평가할 수 있는 대표적인 방법으로 실루엣 분석을 이용한다.

 

◆ 실루엣 분석(silhouetter analysis)

실루엣 분석은 각 군집 안의 거리가 얼마나 효율적으로 분리돼 있는지를 나타내는데, 효율적으로 잘 분리됐다는 것은 다른 군집과의 거리는 떨어져 있고, 동일 군집끼리의 데이터는 서로 가깝게 잘 뭉쳐 있다는 의미이다.

군집화가 잘 될수록 개별 군집은 비슷한 정도의 여유공간을 가지고 떨어져 있을 것이다.

 

실루엣 분석은 실루엣 계수(silhouette coefficient)를 기반으로 하는데, 실루엣 계수는 개별 데이터가 가지는 군집화 지표이다. 개별 데이터가 가지는 실루엣 계수는 해당 데이터가 같은 군집 내의 데이터와 얼마나 가깝게 군집화돼 있고, 다른 군집에 있는 데이터와는 얼마나 멀리 분리돼 있는지를 나타내는 지표이다.

실루엣 계수

  • -1에서 1 사이의 값을 가짐.
  • 1로 가까워질수록 근처의 군집과 더 멀리 떨어져 있음.
  • 0에 가까울수록 근처의 군집과 가까워짐.
  • - 값은 아예 다른 군집에 데이터 포인트가 할당됐음을 의미.

[좋은 군집화가 되기 위한 기준]

  • 전체 실루엣 계수의 평균값(사이킷런의 silhouette_score() 값)이 1에 가까울수록 좋다.
  • 전체 실루엣 계수의 평균값과 더불어 개별 군집의 평균값의 편차가 크지 않아야 한다. 개별 군집의 실루엣 계수 평균값이 전체 실루엣 계수의 평균값에서 크게 벗어나지 않아야 한다.

[사이킷런에서 제공하는 실루엣 분석을 위한 메서드]

  • sklearn.metrics.silhouette_sample(X, labels, metric='euclidean', **kwds): 인자로 X feature 데이터 세트와 각 피처 데이터 세트가 속한 군집 레이블 값인 labels 데이터를 입력해주면 각 데이터 포인트의 실루엣 계수를 계산해 반환
  • skelarn.metrics.silhouette_score(X, labels, metric='euclidean', sample_size=None, **kwds): 인자로 X feature 데이터 세트와 각 피처 데이터 세트가 속한 군집 레이블 값인 labels 데이터를 입력해주면 전체 데이터의 실루엣 계수 값을 평균해 반환한다. (= np.mean(silhouette_samples() ). 일반적으로 이 값이 높을수록 군집화가 어느정도 잘 됐다고 판단할 수 있으나, 무조건 높다고 해서 군집화가 잘 됐다고 판단할 수는 없다.

붓꽃 데이터 세트를 이용한 군집 평가

 

from sklearn.preprocessing import scale
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
# 실루엣 분석 평가 지표 값을 구하기 위한 API 값 추가
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline

iris = load_iris()
feature_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
irisDF = pd.DataFrame(data=iris.data, columns=['sepal_length', 'sepal_width', 'petal_length', 'petal_width'])
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300, random_state=0).fit(irisDF)
irisDF['cluster'] = kmeans.labels_

# iris의 모든 개별 데이터에 실루엣 계수 값 계산
score_samples = silhouette_samples(iris.data, irisDF['cluster'])
print('silhouette_samples() return 값의 shape', score_samples.shape)

# irisDF에 실루엣 계수 칼럼 추가
irisDF['silhouette_coeff'] = score_samples

# 모든 데이터의 평균 실루엣 계수 값 계산
average_score = silhouette_score(iris.data, irisDF['cluster'])
print('붓꽃 데이터 세트 Silhouette Analysis Score:{0:.3f}'.format(average_score))                                  
irisDF.head()

군집별 평균 실루엣 계수 값도 확인

irisDF.groupby('cluster')['silhouette_coeff'].mean()

▶ 1번 군집은 실루엣 계수 평균값이 0.79인데 반해, 0번과 2번은 각 0.42, 0.43으로 평균값이 1번에 비해 상대적으로 낮고, 이로인해 전체 평균 실루엣 계수값이 0.551 정도가 되었다.


군집별 평균 실루엣 계수의 시각화 (군집 개수 최적화)

 

개별 군집별로 적당히 분리된 거리를 유지하면서도 군집 내의 데이터가 서로 뭉쳐 있는 경우에 K-평균의 적절한 군집 개수가 설정됐다고 판단할 수 있다.

visualize_silhouette() 함수는 군집 개수를 변화시키면서 K-평균 군집을 수행했을 때 개별 군집별 평균 실루엣 계수 값을 시각화해서 군집의 개수를 정하는 데 도움을 주며, 내부 파라미터로 여러 개의 군집 개수를 리스트로 가지는 첫 번째 파라미터와 피처 데이터 세트인 두 번째 파라미터를 가지고 있다.

# 여러개의 클러스터링 갯수를 List로 입력 받아 각각의 실루엣 계수를 면적으로 시각화한 함수 작성
def visualize_silhouette(cluster_lists, X_features): 

    from sklearn.datasets import make_blobs
    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_samples, silhouette_score

    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    import math

    # 입력값으로 클러스터링 갯수들을 리스트로 받아서, 각 갯수별로 클러스터링을 적용하고 실루엣 개수를 구함
    n_cols = len(cluster_lists)

    # plt.subplots()으로 리스트에 기재된 클러스터링 수만큼의 sub figures를 가지는 axs 생성 
    fig, axs = plt.subplots(figsize=(4*n_cols, 4), nrows=1, ncols=n_cols)

    # 리스트에 기재된 클러스터링 갯수들을 차례로 iteration 수행하면서 실루엣 개수 시각화
    for ind, n_cluster in enumerate(cluster_lists):

        # KMeans 클러스터링 수행하고, 실루엣 스코어와 개별 데이터의 실루엣 값 계산. 
        clusterer = KMeans(n_clusters = n_cluster, max_iter=500, random_state=0)
        cluster_labels = clusterer.fit_predict(X_features)

        sil_avg = silhouette_score(X_features, cluster_labels)
        sil_values = silhouette_samples(X_features, cluster_labels)

        y_lower = 10
        axs[ind].set_title('Number of Cluster : '+ str(n_cluster)+'\n' \
                          'Silhouette Score :' + str(round(sil_avg,3)) )
        axs[ind].set_xlabel("The silhouette coefficient values")
        axs[ind].set_ylabel("Cluster label")
        axs[ind].set_xlim([-0.1, 1])
        axs[ind].set_ylim([0, len(X_features) + (n_cluster + 1) * 10])
        axs[ind].set_yticks([])  # Clear the yaxis labels / ticks
        axs[ind].set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])

        # 클러스터링 갯수별로 fill_betweenx( )형태의 막대 그래프 표현. 
        for i in range(n_cluster):
            ith_cluster_sil_values = sil_values[cluster_labels==i]
            ith_cluster_sil_values.sort()

            size_cluster_i = ith_cluster_sil_values.shape[0]
            y_upper = y_lower + size_cluster_i

            color = cm.nipy_spectral(float(i) / n_cluster)
            axs[ind].fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_sil_values, \
                                facecolor=color, edgecolor=color, alpha=0.7)
            axs[ind].text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
            y_lower = y_upper + 10

        axs[ind].axvline(x=sil_avg, color="red", linestyle="--")

 

만약 피처 데이터 세트 X_features에 대해서 군집이 다를 때 각 군집별 평균 실루엣 계수 값을 알고 싶다면,

이전에 했던 make_blobs() 함수를 통해 4개 군집(2, 3, 4, 5) 중심의 500개 2차원 데이터 세트를 만들고 이를 K-평균으로 군집화할 때 4개의 군집 중 최적의 군집 개수를 시각화로 알아본다.

# make_blobs를 통해 군집화를 위한 4개의 군집 중심의 500개 2차원 데이터 세트 생성
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=500, n_features=2, centers=4, cluster_std=1,
                  center_box=(-10.0, 10.0), shuffle=True, random_state=1)

# 각 군집 개수, 해당 군집별 실루엣 계수 평균값 시각화
visualize_silhouette([2, 3, 4, 5], X)

▶ 4개의 군집일 때 가장 최적이 됨을 알 수 있다.

 

[붓꽃 데이터를 이용해 K-평균 최적의 군집 개수 파악]

from sklearn.datasets import load_iris
iris=load_iris()
visualize_silhouette([2, 3, 4, 5], iris.data)

▶ 군집 개수를 2개로 하는 것이 가장 좋아 보인다.

  • 나머지의 경우 평균 실루엣 계수 값 2개보다 작음. 1번 군집과 0, 2번 군집과의 실루엣 계수 편차 큼.

실루엣 계수를 통한 K-평균 군집 평가 방법은 직관적으로 이해하기 쉬우나, 데이터양이 늘어나면 수행 시간이 크게 늘어난다. 따라서 군집별로 임의의 데이터를 샘플링해 실루엣 계수를 평가하는 방안을 고민해야 한다.


다음 내용

 

[머신러닝] 군집화: 평균 이동

군집화란? [머신러닝] 군집화 (Clustering)군집화(Clustering) [군집]군집은 비슷한 샘플을 클러스터 또는 비슷한 샘플의 그룹으로 할당하는 작업으로, 데이터 분석, 고객 분류, 추천 시스템, 검색 엔

puppy-foot-it.tistory.com


[출처]

파이썬 머신러닝 완벽 가이드

코딩의 숲 - T Story 블로그

 

728x90
반응형