共计 2438 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
传统文本聚类方法如 TF-IDF 和 LDA 在处理短文本时存在明显不足:

- 语义丢失:TF-IDF 仅统计词频,无法捕捉 ” 手机 ” 和 ” 智能手机 ” 的语义关联
- 稀疏矩阵问题:短文本的单词共现频率低,导致 LDA 生成的文档 - 主题分布不可靠
- 语境缺失:” 苹果公司 ” 和 ” 水果苹果 ” 在传统方法中会被视为同一主题
技术对比
LDA/NMF 的局限性
- 基于词袋模型,忽略词序和语法结构
- 依赖人工设定主题数量(K 值)
- 对停用词和措辞变化敏感
BERT-Topic 优势
- 深度语义编码:利用 Transformer 架构捕获上下文信息
- 动态主题发现:通过聚类自动确定主题数量
- 跨语言能力:多语言 BERT 模型支持混合语料分析
数学表达差异:
传统方法主题生成:
$$p(t|d) = \sum_{w}p(t|w)p(w|d)$$
BERT-Topic 的语义相似度计算:
$$sim(d_i,d_j) = \frac{E(d_i) \cdot E(d_j)}{|E(d_i)| |E(d_j)|}$$
实现详解
1. 嵌入生成
推荐使用 sentence-transformers 的 paraphrase-MiniLM 模型:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
embeddings = model.encode(texts, batch_size=32, show_progress_bar=True)
2. UMAP 降维
关键参数经验值:
n_neighbors: 通常设为 15-50,值越小保留局部特征越多min_dist: 0.05-0.2 之间,控制点分布的紧密程度metric: 多语言数据建议使用 ’cosine’
import umap
umap_model = umap.UMAP(
n_neighbors=20,
min_dist=0.1,
metric='cosine',
random_state=42
)
reduced_embeddings = umap_model.fit_transform(embeddings)
3. HDBSCAN 聚类
设置原则:
min_cluster_size: 根据数据量调整,一般取总样本数的 1%-5%cluster_selection_epsilon: 控制合并小簇的阈值min_samples: 建议设为min_cluster_size的 1 /3
import hdbscan
clusterer = hdbscan.HDBSCAN(
min_cluster_size=50,
cluster_selection_epsilon=0.3,
min_samples=15,
prediction_data=True
)
clusters = clusterer.fit(reduced_embeddings)
完整代码示例
# 数据预处理
import re
from nltk.corpus import stopwords
def clean_text(text):
text = re.sub(r'[^\w\s]', '', text.lower())
words = [w for w in text.split() if w not in stopwords.words('english')]
return ' '.join(words)
# 主题可视化
from bertopic import BERTopic
import matplotlib.pyplot as plt
topic_model = BERTopic(
language="multilingual",
calculate_probabilities=True,
verbose=True
)
topics, probs = topic_model.fit_transform(texts)
# 可视化主题词
fig = topic_model.visualize_barchart(top_n_topics=5)
fig.show()
# 主题间关系
fig = topic_model.visualize_hierarchy()
fig.show()
生产建议
内存优化
- 批量处理:设置
batch_size=16-64 - 使用
fp16精度:model.encode(..., convert_to_numpy=True, device='cuda', fp16=True)
多语言策略
- 单一语种:选择对应语言模型如
bert-base-chinese - 混合语种:使用
paraphrase-multilingual-MiniLM-L12-v2 - 低资源语言:考虑 XLM-RoBERTa
评估指标
from sklearn.metrics import silhouette_score
score = silhouette_score(reduced_embeddings, clusters.labels_)
print(f"轮廓系数: {score:.3f}")
# 主题一致性
from gensim.models import CoherenceModel
coherence = CoherenceModel(topics=topic_model.get_topics(),
texts=processed_texts,
dictionary=dictionary,
coherence='c_v'
).get_coherence()
延伸思考
可以尝试以下 Prompt 优化主题质量:
prompt = """
请用 3 - 5 个关键词概括以下文本的主题,要求:1. 包含核心实体
2. 反映情感倾向
3. 区分具体场景
文本:{input_text}
"""
实际项目中我们发现:
– 电商评论聚类时,加入价格区间特征可提升主题区分度
– 新闻数据需要特别处理命名实体(如人名 / 地名)
– 社交媒体文本建议先进行 emoji 标准化
建议下一步尝试:
1. 结合 Zero-Shot 分类验证主题合理性
2. 用 t -SNE 替代 UMAP 对比可视化效果
3. 在聚类前加入文本长度标准化
正文完
发表至: 自然语言处理
近一天内
