LDA、NMF、BERTopic主题建模后,如何映射主题到文档并确定归属?
主题建模后关联主题与文档的方法
主题建模完成后,核心是通过模型输出的文档-主题分布来关联主题和文档,不同模型的具体操作略有差异,以下是针对NMF、LDA、BERTopic的落地方法:
一、NMF(非负矩阵分解)
NMF训练后会输出两个关键矩阵:
W矩阵:文档-主题权重矩阵(形状为[文档数, 主题数]),每个元素代表对应文档属于该主题的权重H矩阵:主题-词权重矩阵(用于查看主题关键词)
关联操作:
- 文档映射到主题:遍历
W矩阵的每一行,取权重最高的主题作为文档的主主题;也可设置阈值,保留所有权重超过阈值的主题(支持多主题分配) - 主题对应文档:筛选
W矩阵中目标主题列权重超过阈值的文档,或直接取该主题权重排名靠前的文档
示例代码(基于sklearn):
from sklearn.decomposition import NMF from sklearn.feature_extraction.text import TfidfVectorizer # 假设docs是你的原始文档列表 vectorizer = TfidfVectorizer(max_features=1000) X = vectorizer.fit_transform(docs) # 训练NMF模型,设定5个主题 nmf_model = NMF(n_components=5, random_state=42) doc_topic_weights = nmf_model.fit_transform(X) # 获取每篇文档的主主题 doc_main_topic = doc_topic_weights.argmax(axis=1) # 获取主题0对应的文档(权重阈值设为0.2) topic_0_docs = [docs[i] for i in range(len(docs)) if doc_topic_weights[i][0] > 0.2]
二、LDA(潜在狄利克雷分配)
LDA输出的是文档-主题概率分布(每行概率和为1),不同库的实现略有区别:
- sklearn版:
transform()方法直接返回文档-主题概率矩阵 - gensim版:
get_document_topics()方法返回每篇文档的(主题ID, 概率)列表
关联操作:
- 文档映射到主题:取概率最高的主题作为主主题,或保留所有概率超过阈值的主题
- 主题对应文档:筛选目标主题概率超过阈值的文档
示例代码(sklearn版):
from sklearn.decomposition import LatentDirichletAllocation from sklearn.feature_extraction.text import CountVectorizer vectorizer = CountVectorizer(max_features=1000) X = vectorizer.fit_transform(docs) lda_model = LatentDirichletAllocation(n_components=5, random_state=42) doc_topic_probs = lda_model.fit_transform(X) # 每篇文档的主主题 doc_main_topic = doc_topic_probs.argmax(axis=1) # 获取主题2对应的文档(概率阈值设为0.15) topic_2_docs = [docs[i] for i in range(len(docs)) if doc_topic_probs[i][2] > 0.15]
三、BERTopic
BERTopic是基于Transformer的主题模型,内置了完善的文档-主题关联功能,操作更直观:
- 训练后
topics_属性直接给出每篇文档对应的主题ID(-1代表噪声主题) get_document_info(docs)可返回包含文档内容、主题ID、主题概率、主题关键词的结构化DataFrame
关联操作:
- 文档映射到主题:直接读取
model.topics_即可得到每篇文档的主题分配 - 主题对应文档:通过主题ID筛选匹配的文档
示例代码:
from bertopic import BERTopic model = BERTopic(nr_topics=5) topics, probs = model.fit_transform(docs) # 生成文档-主题映射列表 doc_topic_map = list(zip(docs, topics)) # 获取主题3对应的文档 topic_3_docs = [doc for doc, topic in doc_topic_map if topic == 3] # 更便捷的结构化方式 doc_info_df = model.get_document_info(docs) topic_3_docs = doc_info_df[doc_info_df.Topic == 3].Document.tolist()
通用注意事项
- 阈值调整:根据业务需求设定权重/概率阈值,严格匹配则阈值设高,需覆盖更多弱相关文档则阈值设低
- 多主题支持:若业务允许一篇文档属于多个主题,不要仅取权重最高的主题,保留所有超过阈值的主题即可
- 主题可读性:模型生成的主题以关键词集合呈现,建议人工为每个主题命名,方便后续文档分类的理解
内容的提问来源于stack exchange,提问作者Navya
相关产品推荐
相关产品推荐

