Spark LDA

关于LDA的理论部分,参考其他博客(链接待定),本文主要记录spark中LDA的实现。

spark1.4版本的LDA原文比较简单,下面主要是以翻译官网为主。

理论部分

LDA是一个主题模型,它能够推理出一个文本文档集合的主题。LDA可以认为是一个聚类算法,原因如下:

  • 主题对应聚类中心,文档对应数据集中的样本(数据行)
  • 主题和文档都在一个特征空间中,其特征向量是词频向量
  • 跟使用传统的距离来评估聚类不一样的是,LDA使用评估方式是一个函数,该函数基于文档如何生成的统计模型。

LDA以词频向量表示的文档集合作为输入,输出结果提供:

  • Topics:推断出的主题,每个主题是单词上的概率分布。
  • Topic distributions for documents:对训练集中的每个文档,LDA给一个在主题上的概率分布。

LDA参数

  • K:主题数量(或者说聚簇中心数量)
  • maxIterations:EM算法的最大迭代次数
  • docConcentration:文档在主题上分布的先验参数。当前必须大于1,值越大,推断出的分布越平滑。默认为-1,自动设置。
  • topicConcentration:主题在单词上的先验分布参数。当前必须大于1,值越大,推断出的分布越平滑。默认为-1,自动设置。
  • checkpointInterval:检查点间隔。maxIterations很大的时候,检查点可以帮助减少shuffle文件大小并且可以帮助故障恢复。

LDA算法

通过设置setOptimizer 函数,spark提供不同的推断算法。

  1. EMLDAOptimizer 通过在likelihood函数上计算最大期望EM,提供较全面的结果。例如1.4版本想得到训练文档的主题分布,就只能使用这种算法。
  2. OnlineLDAOptimizer 通过在小批量数据上迭代采样实现online变分推断,对于内存较友好。

注意:在1.4.*版本的Mllib中,LDA还不支持新文档的预测,另外也没有python的API。1.5版本提供了预测新版本的功能(效果还不确定)。

下面讨论1.5版本中的两种算法。

Expectation Maximization

EM算法主要在EMLDAOptimizer和DistributedLDAModel类中实现。

需要提供给算法的参数有:

  • docConcentration: 只支持对称先验,K维向量的值都相同,必须>1.0。向量-1表示默认,k维向量值为(50/k)+1。
  • topicConcentration: 只支持对称先验,值必须>1.0。向量-1表示默认。
  • maxIterations:最大迭代次数。

EMLDAOptimizer生成的结果为DistributedLDAModel类, 后者不仅存储了推断的主题,还有整个训练集的主题分布。DistributedLDAModel提供:

  • topTopicsPerDocument: 训练集中每篇文档权重最高的主题。
  • topDocumentsPerTopic: 每个主题中权重最高的文档以及对应权重。
  • logPrior: 根据模型分布计算的log probability。
  • logLikelihood: 根据训练集的模型分布计算的log likelihood。
  • topicDistributions: 训练集中每篇文档的主题分布,相当于theta。
  • topicsMatrix: 主题-词分布,相当于phi。

Online Variational Bayes

OnlineVB算法主要在OnlineLDAOptimizer和LocalLDAModel类中实现。

需要提供给算法的参数有:

  • docConcentration: 可以通过传递一个k维等价于Dirichlet参数的向量作为非对称先验。值应该>=0。向量-1表示默认,k维向量值取(1.0/k)。
  • topicConcentration: 只支持对称先验。值必须>=0。-1表示默认,取值为(1.0/k)。
  • maxIterations: 提交的最小批次的最大数量。

此外,OnlineLDAOptimizer 还接受下面的参数:

  • miniBatchFraction: 每次迭代时采样的部分语料,取值范围(0,1]。
  • optimizeDocConcentration: 默认false,是否在训练时优化docConcentration。
  • tau0 and kappa: 用于学习率的衰减,公式 (τ0+iter)的−κ次方,iter为当前迭代次数。tau0 默认1024,kappa默认0.51,取值范围(0.5, 1]。(我对onlineVB不太了解,参数的意义还需要再看论文。)

OnlineLDAOptimizer生成的结果为LocalLDAModel类, 只存储了推断的主题信息,提供的输出结果:

  • logLikelihood(documents): 模型评价指标,越大越好。
  • logPerplexity(documents): 模型评价指标,越小越好。

此外,在查看了1.5的API文档发现,LocalLDAModel不仅提供了上面两个结果,还有一个更重要的信息:

topicDistributions(documents: RDD[(Long, Vector)]):这也是1.5版本用来预测新文档的方法。DistributedLDAModel类中提供的该方法只存储了训练文档的主题分布,而LocalLDAModel的该方法需要传递以词频向量表示的文档,也可以是新文档,进而实现了预测。

1.5版本的API可以查看1.5.0API

代码示例

下面的示例中,我们加载了用词向量表示的文本文件,然后用LDA训练三个主题。然后打印主题,用主题在词上的概率分布表示主题。

import org.apache.spark.mllib.clustering.LDA
import org.apache.spark.mllib.linalg.Vectors

// 输入的文件每行用词频向量表示一篇文档
val data = sc.textFile("data/mllib/sample_lda_data.txt")
val parsedData = data.map(s => Vectors.dense(s.trim.split(' ').map(_.toDouble)))
val corpus = parsedData.zipWithIndex.map(_.swap).cache()

val ldaModel = new LDA().setK(3).run(corpus)

// 打印主题
println("Learned topics (as distributions over vocab of " + ldaModel.vocabSize + " words):")
val topics = ldaModel.topicsMatrix
for (topic <- Range(0, 3)) {
  print("Topic " + topic + ":")
  for (word <- Range(0, ldaModel.vocabSize)) { print(" " + topics(word, topic)); }
  println()
}

你可能感兴趣的:(spark,LDA)