【发布时间】:2016-01-24 15:55:52
【问题描述】:
我在 spark 上为一组文档运行 LDA,并观察到 topicMatrix 的值(代表词项上的主题分布)大于 1,例如 548.2201、685.2436、138.4013... 这些值是什么意思?这些是分布的对数值还是什么。如何将这些值转换为概率分布值。 提前致谢。
【问题讨论】:
标签: apache-spark lda apache-spark-mllib
我在 spark 上为一组文档运行 LDA,并观察到 topicMatrix 的值(代表词项上的主题分布)大于 1,例如 548.2201、685.2436、138.4013... 这些值是什么意思?这些是分布的对数值还是什么。如何将这些值转换为概率分布值。 提前致谢。
【问题讨论】:
标签: apache-spark lda apache-spark-mllib
在这两种模型(即DistributedLDAModel 和LocalLDAMoel)中,我相信topicsMatrix 方法将返回(大约,由于Dirichlet 对主题的先验,有一些正则化)预期的词-主题计数矩阵.要检查这一点,您可以使用该矩阵并将所有列相加。结果向量(长度为主题计数大小)应该大约等于字数(在所有文档中)。无论如何,要获得主题(字典中单词的概率分布),您需要对列进行归一化topicsMatrix 返回的矩阵的总和为 1。
我还没有完全测试它,但是这样的东西应该可以标准化topicsMatrix返回的矩阵的列:
import breeze.linalg.{DenseVector => BDV}
import org.apache.spark.mllib.linalg._
def normalizeColumns(m: Matrix): DenseMatrix = {
val bm = Matrices.toBreeze(m).toDenseMatrix
val columnSums = BDV.zeros[Double](bm.cols).t
var i = bm.rows
while (i > 0) { i -= 1; columnSums += bm(i, ::) }
i = bm.cols
while (i > 0) { i -= 1; bm(::, i) /= columnSums(i) }
new DenseMatrix(bm.rows, bm.cols, bm.data)
}
【讨论】:
LocalLDAModel。 LocalLDAModel 不保留训练集中每个文档的主题分布(尽管它确实保留了计算它所需的一切),因此不支持 topicDistributions 方法的无参数版本(与 DistributedLDAModel 不同.) 您可以使用ldaModel.topicDistributions(docs) 获取RDD 的文档(无论是在训练集中还是在训练集外)的主题分布。
在纯scala中对topicsMatrix返回的矩阵的列进行归一化
def formatSparkLDAWordOutput(wordTopMat: Matrix, wordMap: Map[Int, String]): scala.Predef.Map[String, Array[Double]] = {
// incoming word top matrix is in column-major order and the columns are unnormalized
val m = wordTopMat.numRows
val n = wordTopMat.numCols
val columnSums: Array[Double] = Range(0, n).map(j => (Range(0, m).map(i => wordTopMat(i, j)).sum)).toArray
val wordProbs: Seq[Array[Double]] = wordTopMat.transpose.toArray.grouped(n).toSeq
.map(unnormProbs => unnormProbs.zipWithIndex.map({ case (u, j) => u / columnSums(j) }))
wordProbs.zipWithIndex.map({ case (topicProbs, wordInd) => (wordMap(wordInd), topicProbs) }).toMap
}
【讨论】: