1. Shilhouette Score
- Unsupervised-Clustering에서 군집이 얼마나 잘 묶였는지 평가하는 평가지표
- Dunn Index는 각각의 군집 구조를 단위로 대한 분리도를 측정
- 반면에 Shilhouette Score는 각각의 개별 데이터 포인트로 자신의 속한 군집과 얼마나 잘 결합, 얼마나 잘 분리되어 있는지를 거리의 평균으로 측정
- -1 ~ 1 사이의 값의 범위를 가지며 높을수록 좋음
- Dunn Index에 비해 이상치에 강건하여 Shilhouette Score로 많이 사용

2. 알고리즘

응집도
- 특정 데이터 포인터(P)가 얼마나 잘 뭉쳐 있는지 계산
- P가 속한 군집B 내에 있는 모들 데이터 포인트들 사이의 거리를 계산하고 평균을 구함
a(i)=∣CI∣−11j∈CI,i=j∑d(i,j)
분리도
- 데이터 포인트 P가 다른 군집들과 얼마나 잘 떨어져 있는지를 계산
- 군집B를 제외한 나머지 군집을 하나 선택 → 군집A선택
- 데이터 P와 군집A에 속한 포인트들 사이의 거리 측정 및 평균구함
- 군집B도 동일하기 구하고 A, C중 작은 값을 선택
b(i)=J=Imin⎝⎜⎛∣CJ∣1j∈CJ∑d(i,j)⎠⎟⎞
Shilhouette 계수 계산
- 모든 데이터 포인트에 대해서 $s(i)를 계산하여 평균냄
- 분자(b(i)−a(i))는 직관적으로 0이면 이웃 군집과의 경계에 위치한 데이터 포인터라고 생각할 수 있음
- 정규화를 위해 max(a(i),b(i))로 나누어줌
s(i)=max(a(i),b(i))b(i)−a(i)
코드
import pandas as pd
import numpy as np
X_COLS = ['A', 'B', 'C']
list_s = []
for idx, data in df.iterrows():
x = data[X_COLS]
y = data['LABEL']
same_cluster_points = df.loc[df['LABEL'] == y, X_COLS].copy()
if same_cluster_points.shape[0] == 1:
list_s.append(0.0)
continue
a = np.sum(np.sqrt(((same_cluster_points - x)**2).sum(axis=1))) / (same_cluster_points.shape[0] - 1)
b = 1e9
for label in df['LABEL'].unique():
if label != y:
other_cluster_points = df.loc[df['LABEL'] == label, X_COLS].copy()
dist = np.sum(np.sqrt(((other_cluster_points - x)**2).sum(axis=1))) / other_cluster_points.shape[0]
b = min(b, dist)
list_s.append((b - a) / max(a, b))
final_silhouette_score = np.mean(list_s)
print(final_silhouette_score)