위계적(hierarchical) 알고리즘: 큰 군집 안에 작은 군집들이 포함되는 형태로 나눔
K-Means
대표적인 클러스터링 알고리즘의 하나
"K개의 평균"이라는 뜻
각 사례가 다른 군집보다 자신이 속한 군집의 중심점에 가장 가깝게 만듦
각 군집의 중심점은 해당 군집에 속한 사례들의 평균
예시: (다음 장 그림 참고)
사례들을 두 개의 군집으로 나눌 경우, 무작위로 두 군집의 중심점을 설정(a)
각 사례들을 두 중심점 중 더 가까운 중심점의 군집으로 분류(b)
각 군집에 속한 사례들을 평균하여 새로운 중심점을 설정(c)
더 이상 군집에 변화가 없을 때까지 (b)~(c)의 과정을 반복
Spherical K-Means
문서 또는 단어의 경우 코사인 유사도를 사용
normalize할 경우 모든 점이 구면에(spherical) 위에 생김
같은 군집의 점들을 평균한 후 L2 normalize하면 중심점도 구면에
노말라이제이션
싸이킷런은 K-Means 클러스터링에 유클리드 거리만 지원
코사인 유사도는 지원 X
문서 임베딩을 L2 Normalize하면 비슷한 효과
from sklearn.preprocessing import normalize
norm_doc_emb = normalize(doc_emb, 'l2')
문서 클러스터링
문서들을 9개의 클러스터로 나눔
from sklearn.cluster import KMeans
km = KMeans(n_clusters=9, random_state=1234)
km.fit(norm_doc_emb)
클러스터 번호 얻기
cluster = km.predict(norm_doc_emb)
문서 클러스터링
i번째 문서의 클러스터 번호
i = 0
cluster_idx = cluster[i]
클러스터 번호가 같은 문서
df[cluster == cluster_idx]
관성 inertia
각 사례와 그 사례가 속한 군집의 중심점까지 거리의 제곱합
각 군집들이 얼마나 조밀하게 모여있는지를 나타냄
군집의 수가 증가할 수록 감소
군집의 수와 관성을 스크리 플롯으로 시각화
플롯의 기울기가 꺾이는 지점을 군집의 수를 결정할 수 있음
관성의 스크리플롯으로 클러스터 수 결정
inertia = []
ks = np.arange(1, 20)
for k in ks:
km = KMeans(n_clusters=k, random_state=1234)
km.fit(norm_doc_emb)
inertia.append(km.inertia_)
import matplotlib.pyplot as plt
plt.plot(ks, inertia)
plt.xticks(ks);
실루엣 계수 Silhouette Coefficient
max(a,b)b−a
a: 군집 내 가장 가까운 사례와 거리
b: 다른 군집의 가장 가까운 사례와 거리
-1에서 +1 사이의 값
+: 다른 군집과 멀리 떨어져 있음(b>a)
0: 두 군집의 경계선에 있음(b=a)
-: 다른 군집에 더 가까이 있음(b<a)
실루엣 계수 (1) 계수 구하기
from sklearn.metrics import silhouette_samples
clusterer = KMeans(n_clusters=6, random_state=10)
cluster_labels = clusterer.fit_predict(norm_doc_emb)
silhouette = silhouette_samples(norm_doc_emb, cluster_labels)
# 클러스터 및 계수 크기 순 정렬
sil = pd.DataFrame({
'cluster': cluster_labels,
'silhouette': silhouette,
})
sil = sil.sort_values(by=['cluster', 'silhouette'], ascending=False)