콘텐츠로 이동
Data Prep
상세

BIRCH

논문 정보

항목 내용
제목 BIRCH: An Efficient Data Clustering Method for Very Large Databases
저자 Tian Zhang, Raghu Ramakrishnan, Miron Livny
연도 1996
학회 SIGMOD (ACM SIGMOD International Conference on Management of Data)
링크 ACM DL

핵심 아이디어

BIRCH (Balanced Iterative Reducing and Clustering using Hierarchies)는 대규모 데이터를 한 번의 스캔으로 클러스터링할 수 있게 설계됨.

핵심 혁신: 1. CF (Clustering Feature): 클러스터의 요약 통계량 2. CF Tree: CF들을 저장하는 균형 트리 (B+ Tree와 유사) 3. 점진적 클러스터링: 데이터를 순차적으로 처리, 메모리 제한 내에서 동작

데이터 전체가 아닌 CF만 저장하므로 메모리 효율적.

알고리즘

Clustering Feature (CF)

n개의 d차원 데이터 포인트 \(\{x_1, ..., x_n\}\)에 대해:

\[CF = (n, LS, SS)\]
  • \(n\): 포인트 수
  • \(LS = \sum_{i=1}^{n} x_i\): 선형 합 (d차원 벡터)
  • \(SS = \sum_{i=1}^{n} x_i^2\): 제곱 합 (스칼라 또는 d차원)

CF의 핵심 속성: 가산성 $\(CF_1 + CF_2 = (n_1 + n_2, LS_1 + LS_2, SS_1 + SS_2)\)$

CF만으로 계산 가능한 것들: - 중심점: \(\bar{x} = LS / n\) - 반경: \(R = \sqrt{\frac{SS}{n} - (\frac{LS}{n})^2}\) - 직경: \(D = \sqrt{\frac{2nSS - 2LS^2}{n(n-1)}}\)

CF Tree 구조

                [CF₁, CF₂, CF₃]         ← Root (비리프 노드)
                /      |      \
    [CF₁₁...CF₁ₖ]  [CF₂₁...CF₂ₖ]  [CF₃₁...CF₃ₖ]  ← 비리프 노드
        /    \          |              |
   [entries]  [entries] [entries]   [entries]    ← Leaf 노드
  • Branching Factor (B): 비리프 노드의 최대 자식 수
  • Threshold (T): 리프 노드 엔트리의 최대 반경/직경
  • Leaf entries: 서브클러스터를 나타내는 CF들

단계별 절차

Phase 1: CF Tree 구축 (한 번의 데이터 스캔)
  각 데이터 포인트 x에 대해:
  1. 루트에서 시작하여 가장 가까운 CF를 따라 리프까지 이동
  2. 리프에서 가장 가까운 엔트리 찾기
  3. x를 흡수해도 threshold 이내면 → CF 업데이트
  4. 아니면 → 새 엔트리 생성
  5. 노드가 꽉 차면 → 분할

Phase 2 (선택): 더 작은 CF Tree로 재구축

Phase 3 (선택): 전역 클러스터링
  - 리프의 CF들에 Agglomerative/K-Means 적용

Phase 4 (선택): 클러스터 정제
  - 각 데이터를 가장 가까운 클러스터에 재할당

시간/공간 복잡도

항목 복잡도
시간 O(n) - 한 번의 스캔
공간 O(B × L) - B: branching factor, L: 리프 수

장단점

장점

장점 설명
확장성 O(n) 시간, 제한된 메모리
점진적 스트리밍 데이터 처리 가능
노이즈 처리 Outlier로 분리 가능
유연성 다른 클러스터링 알고리즘과 결합

단점

단점 설명
구형 클러스터 가정 비구형에 부적합
파라미터 민감 threshold, branching factor 튜닝 필요
삽입 순서 의존 데이터 순서에 따라 결과 다름
차원의 저주 고차원에서 성능 저하

언제 쓰는가

적합한 경우

  • 대규모 데이터 (> 100K, 수백만까지)
  • 메모리 제약이 있을 때
  • 스트리밍 데이터
  • 구형/컴팩트한 클러스터
  • 전처리/요약 단계로 사용 (K-Means 전에)

부적합한 경우

  • 비구형 클러스터 (DBSCAN/HDBSCAN 사용)
  • 고차원 데이터
  • 클러스터 크기가 매우 다를 때

Python 코드

import numpy as np
from sklearn.cluster import Birch
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import time

# 대규모 데이터 생성
n_samples = 50000
X, y_true = make_blobs(n_samples=n_samples, centers=5, cluster_std=0.8, random_state=42)

# BIRCH 적용
start = time.time()
birch = Birch(
    threshold=0.5,          # 리프 노드 반경 임계값
    branching_factor=50,    # 노드당 최대 자식/엔트리 수
    n_clusters=5,           # 최종 클러스터 수 (None이면 서브클러스터 반환)
    compute_labels=True
)
labels = birch.fit_predict(X)
elapsed = time.time() - start

print(f"데이터 크기: {n_samples:,}")
print(f"처리 시간: {elapsed:.3f}초")
print(f"서브클러스터 수: {len(birch.subcluster_centers_)}")
print(f"최종 클러스터 수: {len(np.unique(labels))}")

# 시각화
plt.figure(figsize=(10, 6))
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=1, alpha=0.5)
plt.scatter(birch.subcluster_centers_[:, 0], birch.subcluster_centers_[:, 1], 
            c='red', marker='x', s=50, label='Subcluster centers')
plt.title('BIRCH Clustering')
plt.legend()
plt.show()

Threshold 영향 분석

thresholds = [0.1, 0.3, 0.5, 0.7, 1.0]
results = []

for t in thresholds:
    birch = Birch(threshold=t, branching_factor=50, n_clusters=None)
    birch.fit(X)
    n_subclusters = len(birch.subcluster_centers_)
    results.append({'threshold': t, 'subclusters': n_subclusters})

import pandas as pd
df = pd.DataFrame(results)
print(df)

# 시각화
plt.figure(figsize=(8, 5))
plt.plot(df['threshold'], df['subclusters'], 'bo-')
plt.xlabel('Threshold')
plt.ylabel('Number of Subclusters')
plt.title('Effect of Threshold on BIRCH')
plt.show()

점진적 학습 (Partial Fit)

# 스트리밍 시뮬레이션
birch_streaming = Birch(threshold=0.5, n_clusters=5)

chunk_size = 10000
for i in range(0, len(X), chunk_size):
    chunk = X[i:i+chunk_size]
    birch_streaming.partial_fit(chunk)
    n_sub = len(birch_streaming.subcluster_centers_) if birch_streaming.subcluster_centers_ is not None else 0
    print(f"Processed {min(i+chunk_size, len(X)):,} samples, Subclusters: {n_sub}")

# 최종 라벨 예측
final_labels = birch_streaming.predict(X)

BIRCH + K-Means 파이프라인

from sklearn.pipeline import Pipeline
from sklearn.cluster import KMeans

# BIRCH로 요약 후 K-Means로 정제
pipeline = Pipeline([
    ('birch', Birch(threshold=0.5, n_clusters=None)),  # 서브클러스터 생성
    # K-Means는 BIRCH의 subcluster_centers_에 적용
])

# 또는 직접 결합
birch = Birch(threshold=0.5, n_clusters=None)
birch.fit(X)

# 서브클러스터에 K-Means 적용
kmeans = KMeans(n_clusters=5, random_state=42)
subcluster_labels = kmeans.fit_predict(birch.subcluster_centers_)

# 원본 데이터의 최종 라벨
final_labels = subcluster_labels[birch.labels_]

관련 기법

참고 문헌

  1. Zhang, T., Ramakrishnan, R., & Livny, M. (1996). BIRCH: An Efficient Data Clustering Method for Very Large Databases. Proceedings of the 1996 ACM SIGMOD International Conference on Management of Data, 103-114.
  2. Zhang, T., Ramakrishnan, R., & Livny, M. (1997). BIRCH: A New Data Clustering Algorithm and Its Applications. Data Mining and Knowledge Discovery, 1(2), 141-182.