본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Silhouette Coefficient; 실루엣 지수, Silhouette Score
각 관측값이 자기 군집에 얼마나 잘 붙어 있고 이웃 군집과는 얼마나 떨어져 있는지를 -1~1 사이 값으로 나타내는 군집 분석 평가 지표

Rousseeuw(1987)가 군집 결과를 해석하고 검증하는 그래픽 도구로 제안했다. 정답 레이블 없이 군집 내부의 응집도와 군집 간 분리도만으로 계산하는 내부 평가 지표이며, K-Means, 계층적 군집 분석 등 어떤 군집 방법의 결과에도 쓸 수 있다. 전체 평균 실루엣이 큰 군집 수를 고르는 데 자주 쓴다.

관측값 i가 군집 A에 속할 때,

  • a(i): i와 같은 군집 A의 다른 모든 점 사이 평균 거리(응집도). 작을수록 좋다.
  • d(i, C): i와 다른 군집 C의 모든 점 사이 평균 거리.
  • b(i): 가장 가까운 이웃 군집까지의 평균 거리 b(i)=minC≠Ad(i,C). 클수록 좋다.

s(i)=b(i)−a(i)max⁡{a(i), b(i)}

  • 군집에 점이 i 하나뿐이면 s(i) = 0으로 둔다.
  • 전체 실루엣 계수는 모든 관측값 s(i)의 평균이다. 군집 수 k가 2 이상 n − 1 이하일 때만 정의된다.
  • 거리는 보통 유클리드 거리를 쓰지만 다른 비유사도도 쓸 수 있다. 변수 단위가 다르면 미리 척도를 맞춘다.
s(i) 값 뜻
1에 가까움 a(i)가 b(i)보다 훨씬 작다. 자기 군집에 잘 묶여 있고 이웃 군집과 멀다
0 근처 a(i) ≈ b(i). 두 군집의 경계에 놓여 있다
음수 a(i) > b(i). 이웃 군집이 더 가까우므로 잘못 배정되었을 가능성이 크다
  • 실루엣 그림(silhouette plot)은 군집별로 s(i)를 정렬해 막대로 그린 것이다. 막대가 짧거나 음수가 많은 군집, 다른 군집보다 크기가 유난히 작거나 큰 군집을 찾는 데 쓴다.
  • 평균 실루엣은 볼록하고 크기가 비슷한 군집에 유리하다. 길쭉하거나 밀도가 다른 군집(DBSCAN이 찾는 모양 등)에서는 실제 구조보다 낮게 나올 수 있다.

군집 수 선택 지표 비교

편집 원본 편집
지표 계산 좋은 값 특징
엘보 방법(SSE) 군집 내 제곱합 ∑k∑x∈Ck‖x−μk‖2 감소가 꺾이는 지점 k가 늘면 항상 줄어든다. 꺾이는 점이 뚜렷하지 않으면 판단이 주관적이다
실루엣 계수 위 s(i)의 평균 클수록(최대 1) 관측값 단위 해석이 가능하다. 모든 점 쌍의 거리가 필요해 계산량이 n2에 비례한다
Calinski-Harabasz tr(Bk)/(k−1)tr(Wk)/(n−k) (군집 간 분산 대 군집 내 분산의 비) 클수록 계산이 빠르다. 볼록한 군집에 유리하다
Davies-Bouldin 각 군집과 가장 비슷한 군집 사이의 (군집 내 산포 합 / 중심 간 거리) 평균 작을수록(최소 0) 중심 기반이라 계산이 빠르다. 유클리드 거리 전제
  • 정답 레이블이 있으면 조정 랜드 지수(ARI) 같은 외부 지표를 쓸 수 있지만, 실루엣·CH·DB는 레이블 없이 쓰는 내부 지표이다.
  • 지표마다 고르는 k가 다를 수 있으므로 여러 지표와 업무적 해석을 함께 본다.
library(cluster)
X <- iris[, 1:4]
d <- dist(X)                                  # 유클리드 거리

for (k in 2:6) {
  km  <- kmeans(X, centers = k, nstart = 10)
  sil <- silhouette(km$cluster, d)
  cat(k, summary(sil)$avg.width, "\n")        # 평균 실루엣
}

pm <- pam(X, k = 3)                           # PAM 결과는 바로 실루엣 계산 가능
plot(silhouette(pm))                          # 실루엣 그림
import numpy as np
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
from sklearn.metrics import (silhouette_score, silhouette_samples,
                             calinski_harabasz_score, davies_bouldin_score)

X = load_iris().data

print(" k   SSE(inertia)  silhouette  CH       DB")
for k in range(2, 7):
    km = KMeans(n_clusters=k, n_init=10, random_state=0).fit(X)
    lab = km.labels_
    print(f"{k:2d} {km.inertia_:12.2f} {silhouette_score(X, lab):10.4f}"
          f" {calinski_harabasz_score(X, lab):8.2f} {davies_bouldin_score(X, lab):7.4f}")

# k=3일 때 군집별 평균 실루엣과 음수인 관측값 수
lab3 = KMeans(n_clusters=3, n_init=10, random_state=0).fit_predict(X)
s = silhouette_samples(X, lab3)
for c in range(3):
    print(f"군집 {c}: n={np.sum(lab3 == c)}, 평균 s={s[lab3 == c].mean():.4f}, 음수={np.sum(s[lab3 == c] < 0)}")

실행 결과:

 k   SSE(inertia)  silhouette  CH       DB
 2       152.35     0.6810   513.92  0.4043
 3        78.85     0.5528   561.63  0.6620
 4        57.23     0.4981   530.77  0.7803
 5        46.45     0.4887   495.54  0.8060
 6        39.04     0.3648   473.85  0.9142
군집 0: n=62, 평균 s=0.4173, 음수=0
군집 1: n=50, 평균 s=0.7981, 음수=0
군집 2: n=38, 평균 s=0.4511, 음수=0
  • 평균 실루엣과 Davies-Bouldin은 k = 2를, Calinski-Harabasz는 k = 3을 가장 좋게 본다. SSE는 k = 2→3에서 크게 줄고(152.35 → 78.85) 그 뒤로 완만해져 엘보가 k = 3 근처에 있다.
  • 붓꽃 자료의 실제 품종은 3개지만 versicolor와 virginica가 서로 겹쳐 있어, 거리만 보면 setosa와 나머지의 두 덩어리로 나누는 것이 가장 깔끔하다. 그래서 실루엣이 k = 2에서 가장 크다.
  • k = 3에서 50개짜리 군집(setosa)은 평균 실루엣이 0.80으로 매우 잘 분리되고, 나머지 두 군집은 0.42~0.45로 경계가 가깝다. 음수 값은 없어 명백히 잘못 배정된 점은 없다.
  • 이처럼 지표마다 결론이 다를 수 있으므로, 실기에서는 여러 지표의 결과와 군집의 업무적 의미를 함께 근거로 군집 수를 정해 서술한다.
  • s(i) = (b(i) − a(i)) / max(a(i), b(i))에서 a(i)는 같은 군집 내 평균 거리, b(i)는 가장 가까운 다른 군집까지의 평균 거리이다.
  • 실루엣은 -1~1 범위이고 1에 가까울수록 잘 군집된 것, 0 근처는 경계, 음수는 잘못 배정된 것으로 해석한다.
  • 평균 실루엣이 가장 큰 k를 고르는 방법과 엘보 방법(SSE)의 차이를 설명할 수 있어야 한다. SSE는 k가 늘면 항상 줄어든다.
  • Calinski-Harabasz는 클수록, Davies-Bouldin은 작을수록 좋다는 방향을 구분한다.