Spark MLlib分布式机器学习源码分析:隐式狄利克雷分布(LDA)

原理    Spark是一个极为优秀的大数据框架,在大数据批处理上基本无人能敌,流处理上也有一席之地,机器学习则是当前正火热AI人工智能的驱动引擎,在大数据场景下如何发挥AI技术成为优秀的大数据挖掘工程师必备技能。本文结合机器学习思想与Spark框架代码结构来实现分布式机器学习过程,希望与大家一起学习进步~

目录

1.LDA原理介绍

2.LDA参数

3.Spark示例

4.源码解析


    本文采用的组件版本为:Ubuntu 19.10、Jdk 1.8.0_241、Scala 2.11.12、Hadoop 3.2.1、Spark 2.4.5,老规矩先开启一系列Hadoop、Spark服务与Spark-shell窗口:

1.LDA原理介绍

    隐式狄利克雷分布(LDA) 是一种主题模型,可以从文本文档集合中推断出主题。可以将LDA视为一种聚类算法,如下所示:

  • 主题对应于聚类中心,文档对应于数据集中的示例(行)。

  • 主题和文档都存在于特征空间中,其中特征向量是字数(词袋)的向量。

  • LDA不会使用传统的距离来估计聚类,而是使用基于文本文件生成方式的统计模型的功能。

    DA涉及到的先验知识有:二项分布、Gamma函数、Beta分布、多项分布、Dirichlet分布、马尔科夫链、MCMC、Gibs Sampling、EM算法等。限于篇幅,本文不设计具体理论推导,具体可参考知乎深度文章:https://zhuanlan.zhihu.com/p/31470216

2.LDA参数

    LDA通过setOptimizer功能支持不同的推理算法。EMLDAOptimizer使用似然函数的期望最大化学习聚类并产生综合结果,同时 OnlineLDAOptimizer使用迭代小批量采样进行在线变异推断 ,并且通常对内存友好。

    LDA将文档集合作为单词计数和以下参数(使用构建器模式设置)的向量:

  • k:主题数(即群集中心)

  • optimizer:用于学习LDA模型的优化程序, EMLDAOptimizer或者OnlineLDAOptimizer

  • docConcentration:Dirichlet参数,用于优先于主题的文档分布。较大的值鼓励更平滑的推断分布。

  • topicConcentration:Dirichlet参数,用于表示主题(单词)在先主题的分布。较大的值鼓励更平滑的推断分布。

  • maxIterations:限制迭代次数。

  • checkpointInterval:如果使用检查点(在Spark配置中设置),则此参数指定创建检查点的频率。如果maxIterations很大,使用检查点可以帮助减少磁盘上的随机文件大小,并有助于故障恢复。

    所有spark.mllib的LDA模型都支持:

  • describeTopics:以最重要的术语和术语权重的数组形式返回主题

  • topicsMatrix:返回一个vocabSize由k矩阵,其中各列是一个主题

    期望最大化在EMLDAOptimizer和DistributedLDAModel中实现。对于提供给LDA的参数:

  • docConcentration:仅支持对称先验,因此提供的k维向量中的所有值都必须相同。所有值也必须> 1.0。提供Vector(-1)会导致默认行为(值(50 / k)+1的统一k维向量)

  • topicConcentration:仅支持对称先验。值必须> 1.0。提供-1会导致默认值为0.1 + 1。

  • maxIterations:EM迭代的最大数量。

  • 注意:进行足够的迭代很重要。在早期的迭代中,EM通常没有用的主题,但是经过更多的迭代后,这些主题会大大改善。根据您的数据集,通常至少合理使用20次甚至50-100次迭代。

  • EMLDAOptimizer生成一个DistributedLDAModel,它不仅存储推断出的主题,还存储完整的训练语料库和训练语料库中每个文档的主题分布。DistributedLDAModel支持:

  • topTopicsPerDocument:训练语料库中每个文档的主要主题及其权重

  • topDocumentsPerTopic:每个主题的顶部文档以及该主题在文档中的相应权重。

  • logPrior:给定超参数docConcentration和topicConcentration时,估计主题和文档主题分布的对数概率

  • logLikelihood:给定推断的主题和文档主题分布,训练语料库的对数可能性

3.Spark示例

在以下示例中,我们加载代表文档语料库的单词计数向量。然后,我们使用LDA从文档中推断出三个主题。所需聚类的数量传递给算法。然后,我们输出主题,表示为单词上的概率分布。

import org.apache.spark.mllib.clustering.{DistributedLDAModel, 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)))
// 用唯一ID索引文章
val corpus = parsedData.zipWithIndex.map(_.swap).cache()
// 使用LDA将文章聚类为3类主题
val ldaModel = new LDA().setK(3).run(corpus)
//  输出主题。每个主题都是单词分布(匹配单词向量)
println(s"Learned topics (as distributions over vocab of ${ldaModel.vocabSize} words):")
val topics = ldaModel.topicsMatrix
for (topic <- Range(0, 3)) {
  print(s"Topic $topic :")
  for (word <- Range(0, ldaModel.vocabSize)) {
    print(s"${topics(word, topic)}")
  }
  println()
}
// 保存和加载模型
ldaModel.save(sc, "target/org/apache/spark/LatentDirichletAllocationExample/LDAModel")
val sameModel = DistributedLDAModel.load(sc,
  "target/org/apache/spark/LatentDirichletAllocationExample/LDAModel")

4.源码解析

    以上代码主要做了两件事:加载和切分数据、训练模型。在样本数据中,每一行代表一篇文档,经过处理后,corpus的类型为List((id,vector)*),一个(id,vector)代表一篇文档。将处理后的数据传给org.apache.spark.mllib.clustering.LDA类的run方法, 就可以开始训练模型。run方法的代码如下所示:

def run(documents: RDD[(Long, Vector)]): LDAModel = {
    val state = ldaOptimizer.initialize(documents, this)
    var iter = 0
    val iterationTimes = Array.fill[Double](maxIterations)(0)
    while (iter < maxIterations) {
      val start = System.nanoTime()
      state.next()
      val elapsedSeconds = (System.nanoTime() - start) / 1e9
      iterationTimes(iter) = elapsedSeconds
      iter += 1
    }
    state.getLDAModel(iterationTimes)
  }

    这段代码首先调用initialize方法初始化状态信息,然后循环迭代调用next方法直到满足最大的迭代次数。在我们没有指定的情况下,迭代次数默认为20。需要注意的是, ldaOptimizer有两个具体的实现类EMLDAOptimizer和OnlineLDAOptimizer,它们分别表示使用EM算法和在线学习算法实现参数估计。在未指定的情况下,默认使用EMLDAOptimizer。

    Spark kmeans族的聚类算法的内容至此结束,有关Spark的基础文章可参考前文:

 

    Spark MLlib分布式机器学习源码分析:矩阵向量

    Spark MLlib分布式机器学习源码分析:基本统计

    Spark MLlib分布式机器学习源码分析:线性模型

    Spark MLlib分布式机器学习源码分析:朴素贝叶斯

    Spark MLlib分布式机器学习源码分析:决策树算法

    Spark MLlib分布式机器学习源码分析:集成树模型

    Spark MLlib分布式机器学习源码分析:协同过滤

    Spark MLlib分布式机器学习源码分析:K-means聚类

 

    参考链接:

    http://spark.apache.org/docs/latest/mllib-clustering.html

    https://github.com/endymecy/spark-ml-source-analysis

历史推荐

“高频面经”之数据分析篇

“高频面经”之数据结构与算法篇

“高频面经”之大数据研发篇

“高频面经”之机器学习篇

“高频面经”之深度学习篇

爬虫实战:Selenium爬取京东商品

爬虫实战:豆瓣电影top250爬取

爬虫实战:Scrapy框架爬取QQ音乐

数据分析与挖掘

数据结构与算法

机器学习与大数据组件

欢迎关注,感谢“在看”,随缘稀罕~

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值