클러스터링 평가지표 - 실루엣 계수(Silhouette Coefficient)

민정·2022년 11월 21일
0

데이터공부

목록 보기
2/9
post-custom-banner

⚪️ 실루엣 계수(Silhouette Coefficient)


각 데이터 포인트와 주위 데이터 포인트들과의 거리 계산을 통해 값을 구하며, 군집 안에 있는 데이터들은 잘 모여있는지, 군집끼리는 서로 잘 구분되는지 클러스터링을 평가하는 지표

🌊 실루엣 계수 공식

실루엣계수공식

→ 정답을 갖고와서 군집화 모델을 정답과 비교하며 평가한다기 보다는 군집화를 얼마나 잘 수행했는지를 살펴보는 지표 중 하나

  • a(i): i번째 데이터에서 자신이 속한 군집 내의 다른 데이터들과의 평균적인 거리
  • b(i): i 번째 데이터에서 가장 가까운 다른 군집내의 다른 데이터들과의 평균적인 거리
  • b(i) - a(i):두 군집간의 거리가 얼마나 떨어져 있는지를 의미
    이를 정규화시켜주기 위해 a(i)와 b(i) 중 큰 값인 max{a(i),b(i)} 를 나누어준다. 따라서 실루엣 지표는 값의 크기에 따라 다음과 같은 의미를 가진다.
  • 1에 가까운 값 : 근처의 군집과의 거리가 멀다는 의미
  • 0에 가까운 값: 근처의 군집과의 거리가 가깝다는 의미
  • -(음수)인 값: 클러스터링이 잘못되었다는 의미

🍎 실루엣 계수 실습


사이킷런 내장데이터 iris 데이터를 활용하여 실습을 진행하였다

from sklearn.preprocessing import scale
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

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

average_coef = silhouette_score(iris.data,irisDF['cluster'])
print(f'평균 실루엣 값:{average_coef:.4f}')

KMeans를 이용하여 군집화를 하였다.
사이킷런에 내장된 silhouette_score 모듈을 활용하여 실루엣 계수 점수 측정 시 클러스터링 계수가 3개일 때 0.5528 을 나타낸다 ( 보통 실루엣 계수가 0.5이상이면 군집화가 잘 판단되었다고 본다 )

irisDF.head(10)

cluster결과값이 잘 저장된 것을 확인할 수 있다

😼 데이터 하나하나의 실루엣 계수를 살펴보자

score_samples = silhouette_samples(iris.data,irisDF['cluster'])
irisDF['silhouette_coeff'] = score_samples
irisDF

silhouette_samples 라이브러리를 활용하여 각 데이터의 실루엣 계수 값을 저장해주었다

😸 군집별 실루엣 평균 계수를 살펴보자

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

groupby 를 이용하여 클러스터별로 그룹화해준 후 실루엣 계수 평균 값을 구해보았다.

클러스터별 실루엣 계수 평균값을 알 수 있다.
클러스터 1이 실루엣계수의 평균 값이 가장 높은 것을 알 수 있다.

❗️❗️ 그렇지만 실루엣 계수만으로 그룹화가 잘되었다 판단할 수 없기 때문에 시각화를 해보아야 한다.

😺 군집 개수에 따른 실루엣 계수 시각화

🤡 실루엣 계수 시각화 함수

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) #입력값으로 클러스터링 갯수를 받아서 갯수별로 클러스터링 적용 후 실루엣 계수 계산
  fig,axs = plt.subplots(figsize=(4*n_cols,4),nrows = 1,ncols = n_cols)
  #클러스터링 갯수의 순서대로 적힌 클러스터링의 수만큼 sub figures를 가지는 axs 생성
  for ind, n_cluster in enumerate(cluster_lists):
    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'+'Shilhouette 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([])
    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 = "--")
from sklearn.datasets import make_blobs
#make_blobs를 통해 clustering을 위한 4개의 클러스터 중심의 500개 2차원 데이터 셋 생성 
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)

각 군집별로 실루엣 스코어를 나타냈다
실루엣 스코어만 보았을 때 군집의 개수가 2일 때가 최적화 같지만 군집간의 편차가 적은 군집이 3이나 4일때가 더 좋다!
따라서 이러한 문제 때문에 군집 수 최적화는 시각화도 같이 봐서 판단해야 한다

참조/레퍼런스

Silhouette-Analysis
군집화 평가

profile
공부 기록장
post-custom-banner

0개의 댓글