📢 转载信息
原文链接:https://machinelearningmastery.com/document-clustering-with-llm-embeddings-in-scikit-learn/
原文作者:Jason Brownlee
文档聚类(Document clustering)是一种无监督学习任务,用于将文档集合组织成组或集群。传统的聚类方法通常依赖于词袋(Bag-of-Words)模型或TF-IDF等技术来表示文档,这些方法侧重于词频,但往往忽略了单词的语义含义。
大型语言模型(LLM)的嵌入(embeddings)为文档聚类带来了革命性的改进。LLM能够生成高维度的、富含语义信息的向量表示,这些嵌入能够更好地捕捉文档的深层含义。本文将介绍如何利用LLM嵌入与Scikit-Learn库结合,实现现代化的文档聚类。
我们将探讨以下步骤:
- 准备工作:设置环境并准备数据。
- 生成嵌入:使用预训练的LLM(如Sentence Transformers)生成文档嵌入。
- 进行聚类:使用Scikit-Learn中的聚类算法(如K-Means或DBSCAN)处理嵌入。
- 评估结果:分析聚类效果。
1. 准备工作
要完成此示例,我们需要安装几个关键库,包括用于LLM嵌入的sentence-transformers和用于聚类及数据处理的scikit-learn和numpy。
pip install sentence-transformers scikit-learn numpy
我们将使用一个小型数据集来演示流程。假设我们有一个包含几篇关于不同主题(如“运动”、“科学”、“政治”)的文章的列表。
# 示例文档数据
documents = [
"The latest football match ended in a tie.",
"Scientists discovered a new planet in a distant galaxy.",
"The government announced new policy changes today.",
"The team celebrated their victory after the intense game.",
"Researchers published findings on quantum computing progress.",
"New regulations will impact international trade agreements."
]
2. 生成 LLM 嵌入
LLM嵌入是此流程的核心。我们将使用sentence-transformers库中的预训练模型来将每个文本文档转换为一个固定长度的向量。all-MiniLM-L6-v2是一个常用且高效的模型。
这些嵌入向量捕获了文本的语义信息,使相似的文档在向量空间中彼此靠近。
from sentence_transformers import SentenceTransformer
# 加载预训练模型
model_name = 'all-MiniLM-L6-v2'
model = SentenceTransformer(model_name)
# 生成嵌入
print(f"Generating embeddings for {len(documents)} documents...")
embeddings = model.encode(documents)
print(f"Shape of embeddings: {embeddings.shape}")
# 预期的输出形状是 (6, 384),表示6个文档,每个嵌入维度为384
请注意,输出的嵌入维度(384)取决于所选模型的架构。嵌入的质量直接影响聚类的性能。
3. 使用 Scikit-Learn 进行文档聚类
一旦我们有了语义丰富的嵌入向量,就可以使用Scikit-Learn提供的任何聚类算法了。对于这种向量数据,K-Means是最常见且易于实现的算法之一。我们将尝试将文档聚类为3个组(与我们示例数据的主题数相对应)。
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
# 假设我们希望聚类成3个组
n_clusters = 3
# 初始化并训练KMeans模型
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
kmeans.fit(embeddings)
# 获取分配的簇标签
cluster_labels = kmeans.labels_
print("Cluster Assignments:")
for i, label in enumerate(cluster_labels):
print(f"Document {i+1}: Cluster {label}")
# 评估聚类质量(轮廓系数)
if n_clusters > 1:
silhouette_avg = silhouette_score(embeddings, cluster_labels)
print(f"Silhouette Score: {silhouette_avg:.4f}")
轮廓系数(Silhouette Score)是一个衡量聚类内聚和分离程度的指标,值越接近+1表示聚类效果越好。
使用 DBSCAN 进行基于密度的聚类
另一种流行的选择是DBSCAN(基于密度的聚类),它不需要预先指定簇的数量,并且能够识别出噪声点。
from sklearn.cluster import DBSCAN
# DBSCAN 需要 'eps' (邻域半径) 和 'min_samples' (簇内最小样本数)
# 这里的参数选择高度依赖于嵌入的特性和距离度量
dbscan = DBSCAN(eps=0.5, min_samples=2)
dbscan_labels = dbscan.fit_predict(embeddings)
print("\nDBSCAN Cluster Assignments:")
for i, label in enumerate(dbscan_labels):
# 标签 -1 表示噪声点
print(f"Document {i+1}: Cluster {label}")
DBSCAN 的关键在于选择合适的 eps 参数。如果嵌入向量是标准化的(或在使用模型生成时已经归一化),这个距离参数的选择会更直观。
4. 结果分析与可视化
在实际应用中,高维嵌入很难直接可视化。通常我们会使用降维技术,如主成分分析(PCA)或t-SNE,将384维的嵌入降至2D或3D以便绘图。
下面展示如何使用PCA将嵌入降至2维,并使用Matplotlib进行简单的散点图可视化。
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
# 使用PCA降维到2D
pca = PCA(n_components=2)
reduced_embeddings = pca.fit_transform(embeddings)
# 可视化 K-Means 结果
plt.figure(figsize=(10, 7))
plt.scatter(reduced_embeddings[:, 0], reduced_embeddings[:, 1], c=cluster_labels, cmap='viridis', marker='o')
plt.title('Document Clustering using LLM Embeddings (PCA Reduced)')
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
# 标记数据点
for i, txt in enumerate(documents):
plt.annotate(f'{i+1}', (reduced_embeddings[i, 0], reduced_embeddings[i, 1]), fontsize=9)
plt.colorbar(label='Cluster ID')
plt.grid(True)
plt.show()
通过这种结合LLM语义理解和Scikit-Learn统计方法的流程,我们可以高效地对大规模文档集进行有意义的组织和分析,显著超越了依赖词汇匹配的传统方法。
关键点总结:LLM嵌入提供了强大的语义表示,使得Scikit-Learn中的标准聚类算法能够处理更复杂的文本数据结构。
🚀 想要体验更好更全面的AI调用?
<>欢迎使用青云聚合API,约为官网价格的十分之一,支持300+全球最新模型,以及全球各种生图生视频模型,无需翻墙高速稳定,文档丰富,小白也可以简单操作。
评论区