logo

문서 클러스터링

클러스터링 clustering

  • 비슷한 사례들을 하나의 군집(cluster)으로 만드는 비지도 학습
  • 파티션(partition) 알고리즘: 수평적인 군집들로 나눔
    • K-Means
    • Mixture of Gaussian
    • Spectral Clustering
  • 위계적(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

  • : 군집 내 가장 가까운 사례와 거리
  • : 다른 군집의 가장 가까운 사례와 거리
  • -1에서 +1 사이의 값
  • +: 다른 군집과 멀리 떨어져 있음()
  • 0: 두 군집의 경계선에 있음()
  • -: 다른 군집에 더 가까이 있음()

실루엣 계수 (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)

실루엣 계수 (2) 시각화

  • 실루엣 계수 시각화
n = len(sil)
plt.plot(range(n), sil.silhouette)

# 평균선
avg = silhouette.mean()
plt.plot([0, n], [avg, avg], '--')
  • 각각의 클러스터가 봉우리로 표현
  • 각 봉우리의 폭과 높이가 비슷한 것이 바람직
Previous
문장 BERT를 이용한 키워드 추출