You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中评估不同主题数K下的BTM主题模型?

适配BTM模型的困惑度与主题一致性实现方案

针对BTM包缺少内置评估指标的问题,以下是手动实现主题一致性和困惑度的方案,可辅助选择最优主题数K:

一、主题一致性(Topic Coherence)实现

主题一致性反映主题内词的语义相关性,这里采用UCI方法(基于词共现统计):

1. 提取模型主题词

从训练好的BTM模型中获取每个主题的Top-N核心词:

# 每个主题取前10个核心词
top_terms_per_topic <- topTerms(model, n = 10)

2. 构建词共现矩阵

基于原始分词语料,统计词对在同一文档内的共现频次:

library(tm)
# 转换为文档-词矩阵
dtm <- DocumentTermMatrix(Corpus(VectorSource(df_title_tok)))
# 计算词-词共现次数
cooccur_matrix <- crossprod(t(dtm))
diag(cooccur_matrix) <- 0  # 剔除词自身的共现统计

3. 计算主题一致性得分

对每个主题的Top词组合,计算两两共现频次的对数和并归一化:

compute_topic_coherence <- function(top_terms, cooccur_mat) {
  coherence_sum <- 0
  term_count <- length(top_terms)
  pair_count <- term_count * (term_count - 1) / 2
  
  if (pair_count == 0) return(0)
  
  for (i in 1:(term_count-1)) {
    for (j in (i+1):term_count) {
      w1 <- top_terms[i]
      w2 <- top_terms[j]
      # 跳过共现矩阵中不存在的词对
      if (!w1 %in% rownames(cooccur_mat) || !w2 %in% colnames(cooccur_mat)) next
      # 累加对数共现次数(+1避免log(0))
      coherence_sum <- coherence_sum + log(cooccur_mat[w1, w2] + 1)
    }
  }
  # 归一化后得到单个主题的一致性得分
  return(coherence_sum / pair_count)
}

# 计算所有主题的一致性得分,取平均值作为模型整体一致性
topic_coherences <- sapply(top_terms_per_topic, compute_topic_coherence, cooccur_mat = cooccur_matrix)
avg_coherence <- mean(topic_coherences)

二、困惑度(Perplexity)实现

困惑度衡量模型对未知数据的预测能力,需划分训练/测试集计算:

1. 划分训练与测试语料

set.seed(123)
train_idx <- sample(seq_along(df_title_tok), size = 0.8 * length(df_title_tok))
train_tok <- df_title_tok[train_idx]
test_tok <- df_title_tok[-train_idx]

2. 训练模型并提取核心参数

train_model <- BTM(
  train_tok,
  k = n_topics,
  alpha = 50/n_topics,
  beta = 0.01,
  iter = 1000,
  window = 15,
  background = FALSE,
  trace = FALSE,
  detailed = TRUE
)

# 提取词-主题分布(phi:行=主题,列=词)和主题先验alpha
phi <- train_model$phi
alpha <- train_model$alpha

# 生成测试集的滑动窗口(与模型window参数一致)
library(textmineR)
test_windows <- CreateWindows(
  documents = test_tok,
  window_size = 15,
  overlapping = TRUE
)

3. 计算测试集困惑度

compute_perplexity <- function(test_windows, phi, alpha) {
  total_log_prob <- 0
  total_word_count <- 0
  
  for (window in test_windows) {
    # 过滤模型未收录的词
    valid_words <- window[window %in% colnames(phi)]
    if (length(valid_words) == 0) next
    
    total_word_count <- total_word_count + length(valid_words)
    
    # 计算当前窗口的主题概率分布(alpha平滑 + 词主题概率加权)
    topic_weights <- colSums(phi[, valid_words, drop = FALSE]) + alpha
    topic_probs <- topic_weights / sum(topic_weights)
    
    # 累加每个词的对数概率
    word_log_probs <- sapply(valid_words, function(word) {
      log(sum(topic_probs * phi[, word]))
    })
    total_log_prob <- total_log_prob + sum(word_log_probs)
  }
  
  # 计算并返回困惑度
  return(exp(-total_log_prob / total_word_count))
}

test_perplexity <- compute_perplexity(test_windows, phi, alpha)

三、最优K值选择策略

  • 遍历候选K值(如2~20),分别训练模型并计算对应平均主题一致性、测试集困惑度
  • 优先选择平均主题一致性最高且困惑度较低的K值,最终结合人工校验(查看主题词语义关联)确定最优主题数

内容的提问来源于stack exchange,提问作者Valerio Ficcadenti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 02:57:52