双词主题模型(BTM)中文档/推文主题分配及LDAvis匹配异常咨询
问题描述
- 我是主题建模领域新手,问题浅显还请见谅。
- 用双词主题模型(BTM)对短文本(客户反馈推文)建模挖掘主题,搭配LDAvis做可视化分析。
- 想给每条文档分配单一主题方便手动定性分析,但关键词搜索效果差——关键词常跨多个主题,单关键词筛选出的子集包含多主题数据,且客户反馈里的关键词往往有多重含义。
- 尝试用BTM输出的
scores数组每行最大值分配主题,语法运行成功,但结果和LDAvis可视化不匹配:比如LDAvis显示“apps”只出现在主题10,但含“apps”的两条推文被分到了不同主题,想问这个分配方法是否正确? - 刚接触R语言,只会把主题单独写入csv,不知道怎么把主题添加到原始数据框
data再保存。
已运行的代码
1. BTM建模与主题分配
# Run bi-term topic modeling set.seed(9082374) model <- BTM(x, k = 10, alpha = 0.1, beta = 0.01, iter = 2000, trace = 100, detailed=TRUE) # Predict topic scores for new data scores <- predict(model, x) # 最初错误使用which.min,后改为which.max final.topic <- apply(scores, 1, which.min) fwrite(list(final.topic), file="topic_max.csv") library(data.table) final.topic <- apply(scores, 1, which.max) fwrite(list(final.topic), file="topic_max.csv")
2. LDAvis可视化代码(运行遇困难)
term.table1 <- table(x$text) # Create JSON data for LDAvis docsize <- table(x$id) scores <- scores[names(docsize), ] json <- createJSON( phi = t(model$phi), theta = scores, doc.length = as.integer(docsize), vocab = as.character(rownames(model$phi)), term.frequency = term.table1) serVis(json)
问题解答
1. 主题分配方法的正确性
用which.max(scores)分配主题的方法是合理的——scores每行对应文档在各主题的概率,取概率最高的主题作为文档的主导主题是主题建模中的常规操作。出现和LDAvis不一致的情况,原因可能是:
- LDAvis的展示逻辑:LDAvis展示的是主题-词概率(phi矩阵)的相对高权重词,会过滤低权重词。“apps”可能在其他主题也有概率,但因权重低未被展示,而你的推文可能包含其他主题的强关联词,导致最高概率主题不是主题10,这是短文本的正常现象。
- 代码修正点:你最初用了
which.min(取概率最小的主题),这是错误的,后来改成which.max才正确,要确保最终使用的是后者的结果。
2. 将主题添加到原始数据框并保存
如果用data.table处理:
library(data.table) # 给原始数据框新增主题列,确保final.topic长度和data行数一致 data[, assigned_topic := final.topic] # 保存带主题的数据集 fwrite(data, file = "data_with_topics.csv")
如果是基础R数据框:
# 新增主题列 data$assigned_topic <- final.topic # 保存到csv,row.names=FALSE避免生成多余行号 write.csv(data, file = "data_with_topics.csv", row.names = FALSE)
3. LDAvis代码的潜在问题及修正
你的LDAvis代码可能因词频、文档长度统计错误导致运行失败,修正后参考:
# 统计所有词的频率(x是分词后的文档列表) all_terms <- unlist(x) term.frequency <- table(all_terms) # 统计每个文档的词数(即文档长度) doc.length <- sapply(x, length) # 生成LDAvis所需JSON数据 json <- createJSON( phi = t(model$phi), theta = scores, doc.length = doc.length, vocab = rownames(model$phi), term.frequency = as.integer(term.frequency) ) serVis(json)
内容的提问来源于stack exchange,提问作者vaibhavchutani
相关产品推荐
相关产品推荐

