0Pricing
AI Engineering Academy · 강의

임베딩 군집화 및 시각화

임베딩 집합에 k-평균 군집화를 적용하고 UMAP으로 2차원에 시각화하여 데이터에서 자연스럽게 형성되는 주제 그룹을 발견합니다.

임베딩 군집화 및 시각화은(는) CoddyKit의 무료 AI Engineering Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Engineering Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

임베딩을 클러스터링하는 이유

수백 또는 수천 개의 문서가 있다면 모든 문서를 직접 읽지 않고도 어떤 주제가 존재하는지 파악하고 싶을 때가 많습니다. 임베딩 클러스터링은 의미적으로 유사한 문서를 자동으로 그룹화하여 데이터의 자연스러운 구조를 보여 줍니다.

일반적인 활용 사례로는 지원 티켓 자동 태깅, 콘텐츠 카테고리 발견, 중복 문서 찾기, 사용자가 가장 많이 묻는 내용 파악 등이 있습니다.

K-평균 클러스터링 개요

K-평균은 각 데이터 포인트를 가장 가까운 중심에 반복적으로 할당한 다음, 할당된 포인트의 평균으로 중심을 다시 계산하여 n개의 데이터 포인트를 k개의 클러스터로 나눕니다. 할당이 더 이상 변경되지 않으면 수렴합니다.

임베딩에 K-평균을 적용하면 고차원 임베딩 공간에서 서로 가까운 문서를 찾아 의미적 유사성에 따라 효과적으로 그룹화할 수 있습니다.

from sklearn.cluster import KMeans
import numpy as np

# corpus_embeddings: (n_docs, 1536) — pre-computed
corpus_embeddings = np.random.randn(200, 1536)  # placeholder

kmeans = KMeans(n_clusters=5, random_state=42, n_init='auto')
kmeans.fit(corpus_embeddings)

labels = kmeans.labels_
print(f'Cluster assignments: {labels[:10]}')
print(f'Unique clusters: {set(labels)}')

적절한 클러스터 수 선택하기

클러스터 수인 k를 선택하는 것이 가장 어렵습니다. 엘보 방법은 다양한 k 값에 대해 관성(중심까지의 거리 제곱합)을 그래프로 그리고, 클러스터를 더 추가해도 관성이 크게 줄어들지 않기 시작하는 지점을 찾습니다.

실루엣 점수는 한 포인트가 자신이 속한 클러스터에 얼마나 잘 맞는지를 가장 가까운 다른 클러스터와 비교하여 측정합니다. 1에 가까울수록 좋습니다. k를 3부터 20까지 시도하고 가장 높은 점수를 선택하십시오.

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import numpy as np

corpus_embeddings = np.random.randn(200, 50)  # placeholder (50D for speed)

best_k, best_score = 2, -1
for k in range(2, 11):
    km = KMeans(n_clusters=k, random_state=42, n_init='auto')
    labels = km.fit_predict(corpus_embeddings)
    score = silhouette_score(corpus_embeddings, labels, sample_size=100)
    print(f'k={k}: silhouette={score:.3f}')
    if score > best_score:
        best_score, best_k = score, k

print(f'Best k: {best_k}')

LLM으로 클러스터에 레이블 지정하기

클러스터링이 끝나면 각 클러스터에서 대표 문서 몇 개를 모델에 전달하여 LLM에게 사람이 읽을 수 있는 레이블을 생성하도록 요청할 수 있습니다. 이를 통해 원시 클러스터 번호를 의미 있는 카테고리 이름으로 자동 변환할 수 있습니다.

from openai import OpenAI

client = OpenAI()

def label_cluster(cluster_docs, n_examples=3):
    examples = '\n'.join(f'- {d}' for d in cluster_docs[:n_examples])
    prompt = f'Given these documents, provide a 3-word category label:\n{examples}\nLabel:'
    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        max_tokens=20
    )
    return response.choices[0].message.content.strip()

# Example usage:
# cluster_0_docs = [documents[i] for i in range(len(documents)) if labels[i] == 0]
# print(label_cluster(cluster_0_docs))

UMAP으로 차원 축소하기

1536차원 벡터는 직접 그래프로 나타낼 수 없습니다. UMAP(Uniform Manifold Approximation and Projection)은 국소적인 이웃 구조를 보존하면서 고차원 데이터를 2차원 또는 3차원으로 축소합니다. PCA와 달리 UMAP은 비선형 방식이며 클러스터를 훨씬 잘 보존합니다.

UMAP은 유사한 문서가 2차원 그래프에서도 서로 가깝게 유지되므로 텍스트 임베딩을 시각화할 때 표준적으로 사용됩니다.

import umap
import numpy as np

corpus_embeddings = np.random.randn(200, 1536)  # placeholder

reducer = umap.UMAP(
    n_components=2,
    metric='cosine',   # important for text embeddings
    random_state=42
)

embeddings_2d = reducer.fit_transform(corpus_embeddings)
print(f'Reduced shape: {embeddings_2d.shape}')  # (200, 2)

Matplotlib으로 클러스터 시각화하기

UMAP에서 2차원 좌표를 얻고 K-평균에서 클러스터 레이블을 얻었다면, 간단한 산점도로 클러스터 구조를 확인할 수 있습니다. 각 포인트를 클러스터 레이블에 따라 색칠하고, 차트를 이해하기 쉽도록 대표 문서 제목을 텍스트 주석으로 추가하십시오.

import matplotlib.pyplot as plt
import numpy as np

# Assume: embeddings_2d (n, 2), labels (n,), documents list
# Placeholder data:
np.random.seed(42)
embeddings_2d = np.random.randn(50, 2)
labels = np.random.randint(0, 5, 50)

fig, ax = plt.subplots(figsize=(10, 7))
scatter = ax.scatter(
    embeddings_2d[:, 0],
    embeddings_2d[:, 1],
    c=labels,
    cmap='tab10',
    s=60,
    alpha=0.8
)
plt.colorbar(scatter, label='Cluster')
ax.set_title('Document Embedding Clusters (UMAP)')
plt.tight_layout()
plt.savefig('/tmp/clusters.png', dpi=150)
print('Saved cluster plot')

중요한 UMAP 매개변수

시각화 품질에 영향을 주는 주요 UMAP 하이퍼매개변수는 다음과 같습니다.

  • n_neighbors(기본값 15): 값이 클수록 전역 구조를 더 많이 포착하고, 작을수록 국소 클러스터를 더 잘 드러냄
  • min_dist(기본값 0.1): 포인트가 얼마나 조밀하게 모이는지를 결정함. 값이 작을수록 클러스터는 더 조밀해지지만 클러스터 간 겹침이 증가함
  • metric: 텍스트 임베딩에는 항상 'cosine'을 사용해야 함 — 유클리드 거리는 적절하지 않음

데이터의 구조를 가장 잘 보여 주는 시각화를 찾을 때까지 n_neighbors를 5에서 50 사이로 실험해 보십시오.

계층적 클러스터링 대안

Agglomerative 계층적 클러스터링은 미리 k를 지정하지 않아도 중첩된 클러스터의 트리를 만듭니다. 선택한 거리 임계값에서 트리를 잘라 최종 클러스터를 얻습니다. 데이터에 자연적으로 존재하는 주제의 수를 모를 때 유용합니다.

from sklearn.cluster import AgglomerativeClustering
import numpy as np

corpus_embeddings = np.random.randn(100, 50)  # placeholder

cluster = AgglomerativeClustering(
    n_clusters=None,
    distance_threshold=1.5,
    metric='cosine',
    linkage='average'
)
labels = cluster.fit_predict(corpus_embeddings)

n_clusters = len(set(labels))
print(f'Found {n_clusters} natural clusters')

이상치와 거의 중복된 문서 찾기

임베딩은 거의 중복된 문서를 찾는 데도 매우 유용합니다. 모든 문서 쌍 사이의 코사인 유사도를 계산하고, 유사도가 0.95를 초과하는 쌍을 잠재적인 중복으로 표시하십시오. 문장을 바꿔 쓴 중복도 찾아내므로 텍스트 차이 비교보다 더욱 견고합니다.

import numpy as np

def find_near_duplicates(corpus_vecs, threshold=0.95):
    # corpus_vecs assumed L2-normalized
    sim_matrix = corpus_vecs @ corpus_vecs.T  # (n, n)
    duplicates = []
    n = len(corpus_vecs)
    for i in range(n):
        for j in range(i + 1, n):
            if sim_matrix[i, j] >= threshold:
                duplicates.append((i, j, float(sim_matrix[i, j])))
    return duplicates

# pairs = find_near_duplicates(corpus_embeddings)
# print(f'Found {len(pairs)} near-duplicate pairs')

실용적인 클러스터링 작업 흐름

실제 클러스터링 작업 흐름은 다음 단계를 순서대로 따릅니다.

  1. text-embedding-3-small로 모든 문서를 임베딩합니다
  2. 선택적으로 클러스터링 전에 UMAP으로 50차원으로 축소합니다(K-평균 속도 향상)
  3. K-평균으로 클러스터링하고, 최적의 실루엣 점수를 찾도록 k를 바꾸어 가며 실행합니다
  4. 대표 문서 5개를 사용하여 LLM으로 각 클러스터에 레이블을 지정합니다
  5. 클러스터별로 색칠한 2차원 UMAP 산점도를 시각화합니다
  6. 이상치(어떤 중심에서도 멀리 떨어진 포인트)를 검토합니다

클러스터링의 한계

임베딩 클러스터링에는 다음과 같이 염두에 두어야 할 중요한 한계가 있습니다.

  • K-평균은 구형 클러스터를 가정합니다 — 길쭉하거나 불규칙한 형태의 주제 그룹은 잘못 나뉠 수 있음
  • 임베딩은 의미를 압축합니다 — 두 문서가 의미적으로 가까워도 서로 다른 실행 가능한 카테고리에 속할 수 있음
  • 클러스터 레이블은 검증이 필요합니다 — LLM이 생성한 레이블이 타당한지 확인하려면 항상 각 클러스터에서 문서를 일부 추출해 검토해야 함

클러스터링은 정답으로 간주되는 분류 시스템이 아니라 탐색 도구로 사용하십시오.

빠른 확인

이 레슨에서 배운 AI 엔지니어링 개념을 제대로 이해했는지 확인해 보십시오.

레슨 요약

이 강의에서 배운 내용은 다음과 같습니다. k-means는 임베딩 공간에서 의미적으로 가까운 문서들을 그룹화합니다. UMAP은 코사인 거리를 사용하여 고차원 임베딩을 시각화를 위한 2차원으로 축소합니다. 또한 실루엣 점수는 레이블이 지정된 데이터 없이도 적절한 클러스터 수를 선택하는 데 도움을 줍니다. 다음으로는 메모리 내 검색을 넘어 실제 운영 환경의 벡터 데이터베이스를 살펴보겠습니다.

자주 묻는 질문

“임베딩 군집화 및 시각화” 강의는 무료인가요?

네 — “임베딩 군집화 및 시각화” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Engineering Academy 강의 전체를 잠금 해제할 수 있습니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“임베딩 군집화 및 시각화”에서 뭘 배우나요?

임베딩 집합에 k-평균 군집화를 적용하고 UMAP으로 2차원에 시각화하여 데이터에서 자연스럽게 형성되는 주제 그룹을 발견합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Engineering Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

AI Engineering Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 AI Engineering Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“임베딩 군집화 및 시각화” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 AI Engineering Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 AI Engineering Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 벡터 임베딩이란 무엇인가
  2. OpenAI로 임베딩 생성하기
  3. NumPy로 의미 검색하기
  4. 임베딩 군집화 및 시각화
← AI Engineering Academy(으)로 돌아가기