报告 spark LDA 模型的对数似然/困惑度(本地模型与分布式模型不同?)

Reporting log-likelihood / perplexity of spark LDA model (different in local vs distributed models?)

给定一个训练语料库 docsWithFeatures,我在 Spark 中训练了一个 LDA 模型(通过 Scala API),如下所示:

import org.apache.spark.mllib.clustering.{LDA, DistributedLDAModel, LocalLDAModel}
val n_topics = 10;
val lda = new LDA().setK(n_topics).setMaxIterations(20)
val ldaModel = lda.run(docsWithFeatures)

val distLDAModel = ldaModel.asInstanceOf[DistributedLDAModel]

现在我想报告模型的对数似然和困惑度。

我可以这样得到对数似然:

scala> distLDAModel.logLikelihood
res11: Double = -2600097.2875547716

但这就是事情变得奇怪的地方。我还想要 perplexity,它只针对本地模型实现,所以我 运行:

val localModel  = distLDAModel.toLocal

这让我得到了这样的(日志)困惑:

scala> localModel.logPerplexity(docsWithFeatures)
res14: Double = 0.36729132682898674

但是本地模型也支持对数似然计算,我运行是这样的:

scala> localModel.logLikelihood(docsWithFeatures)
res15: Double = -3672913.268234148

这是怎么回事?两个对数似然值不应该相同吗?分布式模型的文档说

"logLikelihood: log likelihood of the training corpus, given the inferred topics and document-topic distributions"

而对于本地模型,它表示:

"logLikelihood(documents): Calculates a lower bound on the provided documents given the inferred topics."

我猜这些是不同的,但我不清楚如何或为什么。我应该使用哪一个?也就是说,在给定训练文档的情况下,模型的 "true" 可能性是多少?

总而言之,两个主要问题:

1 - 这两个对数似然值有何不同以及为什么不同,我应该使用哪个?

2 - 在报告困惑度时,我认为应该使用 logPerplexity result 的指数是否正确? (但为什么模型给出的是对数困惑度而不是简单的困惑度?我是不是漏掉了什么?)

1) 这两个对数似然值不同,因为它们计算的是两个不同模型的对数似然。 DistributedLDAModel 正在有效地计算对数似然 w.r.t。一个模型,其中主题的参数和每个文档的混合权重是常量(正如我在另一个 post 中提到的,DistributedLDAModel 本质上是正则化 PLSI,尽管您需要使用 logPrior 也考虑了正则化),而 LocalLDAModel 认为主题参数以及每个文档的混合权重都是随机变量。因此,在 LocalLDAModel 的情况下,您必须整合(边缘化)主题参数和文档混合权重,以计算对数似然(这就是变分 approximation/lower 界限的必要条件,尽管即使没有近似值,对数似然也不相同,因为模型只是不同。)

至于你应该使用哪一个,我的建议(不知道你最终想做什么)是使用附加到你最初训练的 class 的对数似然法(即DistributedLDAModel.) 作为旁注,我可以看到通过 toLocalDistributedLDAModel 转换为 LocalLDAModel 的主要(唯一?)原因是启用计算一组新的(训练外的)文档的主题混合权重(有关更多信息,请参阅我在该线程上的 post:),该操作不是(但可能是) DistributedLDAModel.

支持

2) log-perplexity 只是负对数似然除以语料库中的标记数。如果将对数困惑度除以 math.log(2.0),则结果值也可以解释为在给定模型的情况下编码语料库(作为词袋)所需的每个标记的近似位数。