[파이썬 머신러닝 가이드] 군집화 - 군집 평가 (Clustering Evaluation)

목차

1. inertia


2. silhouette 

군집 평가 (Cluster Evaluation)

대부분의 군집화 데이터 세트는 비교할 만한 타깃 레이블을 가지고 있지 않기 때문에 군집화가 효율적으로 잘 됐는지 평가할 수 있는 대표적인 방법으로 실루엣 분석 이용 + inertia

 

1. inertia

inertia = 샘플과 가까운 centroid와의 거리 제곱의 합 or 평균.

→ 작을수록 좋은 값이나, 처음엔 큰 폭으로 떨어지나 갈수록 작아지는 폭이 줄어듦.

cluster 증가할수록 감소함(가까운 cluster가 증가하며 centroid가 증가할테니) but 작아지는 폭이 줄어드는 것.

 

2. silhouette 분석

** 내가 속한 cluster의 다른 샘플들과의 거리 = a

나랑 제일 근접한 cluster의 모든 샘플들과의 거리 =b

b-a / max(b-a) = 실루엣 coefficient(실루엣 계수)

→ 이걸 각각 평균 내면 실루엣 score

  • -1 ≤silhouette score ≤ 1
    • +1 → 우리끼리 뭉쳐 있고, 다른 cluster랑 멀다 → 잘 뭉쳐있음. 군집화 잘 됨
    •  0 → 젤 가까운거랑 우리의 boundary에 걸쳐 있다. 근처의 군집과 가까워져 간다.
    • -1 → 남의 동네에 더 가까움, 아예 다른 군집에 데이터가 할당됨.

 

** 효율적으로 잘 분리됐다는 것은 다른 군집과의 거리는 떨어져 있고, 동일 군집끼리의 데이터는 서로 가깝게 잘 뭉쳐 있다는 의미

 

  • 좋은 군집화가 되려면?
  1. 전체 실루엣 계수의 평균값, 즉 사이킷런의 silhouette_score() 값은 0 ~ 1 사이의 값을 가지며, 1에 가까울수록 좋음
  2. 하지만 전체 실루엣 계수의 평균과 더불어 개별 군집의 평균 값의 편차가 크지 않아야함.

즉, 개별 군집의 실루엣 평균값이 전체 실루엣 계수의 평균값에서 크게 벗어나지 않는 것이 중요함.

만약 전체 실루엣 계수의 평균값은 높지만, 특정 군집의 실루엣 계수 평균값만 유난히 높고 다른 군집들의 실루엣 계수 평균값은 낮으면 좋은 군집화 조건이 아님.

 

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

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

skleaern.metrics import silhoutte_samples, silhouette_score

from sklearn.preprocessing import scale
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
# 실루엣 분석 metric 값을 구하기 위한 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=feature_names)
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(3)
silhouette_samples( ) return 값의 shape (150,)
붓꽃 데이터셋 Silhouette Analysis Score:0.553

Out[1]:

 
sepal_length
sepal_width
petal_length
petal_width
cluster
silhouette_coeff
0
5.1
3.5
1.4
0.2
1
0.852955
1
4.9
3.0
1.4
0.2
1
0.815495
2
4.7
3.2
1.3
0.2
1
0.829315
irisDF.groupby('cluster')['silhouette_coeff'].mean()
cluster
0    0.417320
1    0.798140  #높음.
2    0.451105
Name: silhouette_coeff, dtype: float64