Spark GraphX 学习笔记——LDA实战:路透社电报新闻分类

15 篇文章 0 订阅
6 篇文章 0 订阅
1. 隐含狄利克雷分布(Latent Dirichlet allocation,LDA)
	1)LDA 属于无监督学习,所有的主题并不需要事先指定,是在聚类过程中逐渐形成的 。

	2)MLlib 的 LDA 使用了 GraphX 来提高计算效率,尽管它的输入和输出都不是图。

	3)LDA 是基于隐含变量的,在这里隐含变量指的是算法自动推断出来的“主题”。这些主题由一些与之关联的单词描述,但并不具有明确的主题名称 。

	4)一旦主题被推断出来,每篇文档在不同主题上会有不 同的分数。这是 LDA 的一个基本原则和假设:每篇文档同时会在所有不同的主题上有所涉及,而不仅仅是其中一两个。

2. LDA实战——路透社电报新闻分类

	1)下载数据:
		在如下网址:
			https://archive.ics.uci.edu/ml/machine-learning-databases/
		下载数据:
			reuters21578.tar.gz

	2)使用命令解压其中单个文件reut2-000.sgm
		tar -xzvf reuters21578.tar.gz reut2-000.sgm

	3)使用命令对文件数据进行清洗,文件名为rcorpus
		cat reut2-000.sgm | tr '\n' ' ' | sed -e 's/<\/BODY>/\n/g' | sed -e 's/^.*<BODY>//' | tr -cd '[[:alpha:]] \n' >rcorpus

	4)生成词袋
		(1)过滤停用词(stop words)
			停用词是指过于普遍,而携带的信息量有限
			一般使用停用词词表,但本次实验中只是简单地将一些较短(少于或等于 5 个字母〉的单词过滤掉,同时也会过滤掉 “ Reuter”这个特殊单词。

		(2)在函数 bagsFrornDocurnentPerLine()里,所有内容经过 split()操作后会转化成传统的 Scala 集合(而不是 ROD )。因此,后续采用的是 groupBy()这种 Scala 集合上的操作方法,而不是 ROD 上的操作方法 groupByKey()

		(3)实现代码:

import org.apache.spark.mllib.linalg._
import org.apache.spark.mllib.clustering._
import org.apache.spark.rdd._
def bagsFromDocumentPerLine(filename:String) =
	sc.textFile(filename)
	// 对每一行,按空格分割出每个单词
	.map(_.split(" ")
		// 过滤操作,过滤掉长度小于等于5和等于reuter的单词
		.filter(x => x.length > 5 && x.toLowerCase != "reuter")
		// 全部转化为小写
		.map(_.toLowerCase)
		// 根据单词进行分组
		.groupBy(x => x)
		.toList
		// 转化得到一个(单词,出现次数)的集合
		.map(x => (x._1, x._2.size)))

// 将文件rcorpus的路径传入
val rddBags:RDD[List[Tuple2[String,Int]]] =
	bagsFromDocumentPerLine("file:///usr/local/spark/input/rcorpus")

val vocab:Array[Tuple2[String,Long]] =
	rddBags.flatMap(x => x)
		.reduceByKey(_ + _)
		.map(_._1)
		// zipWithIndex 给每篇文档附上文档ID
		.zipWithIndex
		.collect

// 前半部分是将词典里字符串形式的单词转换成对应的索引下标
// 后半部分是将它转换为LDA可处理的稀疏向量(SparseVector)形式
// 后半部分:先将词袋转换成稀疏向量,然后使用zipWithIndex()给每篇文档附上文档ID
def codeBags(rddBags:RDD[List[Tuple2[String,Int]]]) =
	rddBags.map(x => (x ++ vocab).groupBy(_._1)
		.filter(_._2.size > 1)
		.map(x => (x._2(1)._2.asInstanceOf[Long].toInt, x._2(0)._2.asInstanceOf[Int].toDouble))
		.toList)
.zipWithIndex.map(x => (x._2, new SparseVector(
	vocab.size, x._1.map(_._1).toArray, x._1.map(_._2).toArray)
.asInstanceOf[Vector]))

// setK(5)是将文档聚类到5个主题上
// run()返回的是一个机器学习模型,里面提供了需要的多种信息:每个主题的描述单词清单,每篇文档属于不同主题的程度。
val model = new LDA().setK(5).run(codeBags(rddBags))

// 查看每个主题的最相关的前6个单词
model.describeTopics(6).map(_._1.map(vocab(_)._1))

执行结果:
	res1: Array[Array[String]] = Array(
		Array(billion, exchange, trading, market, system, credit), 
		Array(tonnes, billion, production, market, exports, january), 
		Array(billion, president, government, american, economic, analysts), 
		Array(company, shares, common, quarter, management, profit), 
		Array(billion, prices, agreement, report, coffee, september))

观察第一篇文档的主题分布情况。由于 topicDistributions()函数会改变文档的顺序,所以需要用 filter()来获得文档 ID 为 0 的文章:
	model.asInstanceOf[DistributedLDAModel].topicDistributions.filter(_._1 == 0).collect

执行结果:一个Array,前者是文档ID,后者是和5个主题的相关性
	res2: Array[(Long, org.apache.spark.mllib.linalg.Vector)] = Array((0,[0.05294417725510889,0.1639072664938587,0.05902558780467674,0.026385449794035468,0.6977375186523203]))

3. 使用上述训练好的模型对没有见过的文章进行主题预测
	
	1)首先将存储在集群中的 DistributedLDAModel (分布式 LDA 模型),转换成完全存储在driver上的 LocalLDAModel (本地 LDA 模型),因为预测函数仅可使用LocalLDAModel 。

	2)选择了reut2-001.sgm中的第一篇文章进行test。

	3)将模型转换为 LocalLDAModel 并进行主题预测 :
	model.asInstanceOf[DistributedLDAModel].toLocal.topicDistributions(codeBags(bagsFromDocumentPerLine("file:///usr/local/spark/input/test"))).collect

	执行结果:
		res3: Array[(Long, org.apache.spark.mllib.linalg.Vector)] = Array((0,[0.18995659732316772,0.24368239811339498,0.18208886519362716,0.21355056631476005,0.1707215730550501]))

4. 如何在LDA实现中使用图(用图来代替LDA中的稀疏举证)
	
	1)在 Spark 1.6 中, LDA 可以使用两个不同的算法来实现:默认的为基于图的最大期望( EM )算法 ,或者是在线变分贝叶斯算法。在这里我们会着重讨论 EM 算法 。EM 算法被用于解决存在有未知或隐藏变量的概率问题,正如 LDA 模型里的隐含变量。 LDA 建立了一个概率方程组 , 如一个单词属于一个特定主题的概率和一个单词在一篇特定文档中 的概率。

	2)求解上述概率方程组时, EM 算法的两个主要步骤是,期望和最大化,运作的方式与 K-Means 方法类似。在期望步骤中,我们会对一些变量进行猜测或估计。然后,在最大化步骤中 , 计算对应的误差,这些变量会被相应地进行调整。这样的过程经过多次迭代后,在期望步骤中做出的猜测会越来越接近真实的概率值 。

代码语言:scala
参考书籍:Spark GraphX in Action

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值