MLLib实践Naive Bayes
引言
本文基于Spark (1.5.0) ml库提供的pipeline完整地实践一次文本分类。pipeline将串联单词分割(tokenize)、单词频数统计(TF),特征向量计算(TF-IDF),朴素贝叶斯(Naive Bayes)模型训练等。
本文将基于“20 NewsGroups” 数据集训练并测试Naive Bayes模型。这二十个新闻组数据集合是收集大约20,000新闻组文档,均匀的分布在20个不同的集合。我将使用'20news-bydate.tar.gz'文件,因为该数据集中已经将数据划分为两类:train和test,非常方便我们对模型进行训练和评价。
20news-bydate.tar.gz - 20 Newsgroups sorted by date; duplicates and some headers removed (18846 documents)
Naive Bayes算法介绍
NB算法属于有监督分类算法,对输入数据: _M_表示输入样本容量,我们的目标是将其对号入座到某一个分类结果:
我们将选择可能性最大的那个分类结果,或者说概率最大的那个分类:
\(y^j=\text{arg}max_y\{P(y|X^j)\},j\in\{1,...,M\}\)
根据贝叶斯公式:
\(\begin{align}P(y|(x_i,...,x_N))&=\frac{P(x_1,...,x_N|y)P(y)}{P(x_1,...,x_N)}\end{align}\)
我们在分类时只需要考虑分子上的两项乘积,并由此可以得出结论:后验概率∝似然概率✖️先验概率(最大后验概率问题转化为最大似然问题)。
进一步地,Naive Bayes模型假设了似然函数的计算时简单地假设_X_的各维度之间独立,这样可以简化似然概率计算公式为:
即给定分类下某个输入_X_出现的概率等于该分类下输入_X_各个维度分别出现的概率乘积。
综上,在naive bayes算法框架下,对于某个输入_X_:
- 如果_X_属于某个分类_y_的概率的概率大于属于其它分类的概率,则判定该输入属于分类_y_;
- _X_属于某个分类_y_的概率正比于分类_y_自身出现的概率✖️该分类_y_条件下_X_各个维度出现的概率的乘积。
那么,模型训练的目标就很明朗了,我们需要基于给定的训练样本计算出:
- 各个分类的先验概率:
- 训练样本中,每个分类条件下,输入各个维度出现的似然概率:
模型用于分类新数据的计算:
spark mllib中算法流程
spark中对NaiveBayes算法的实现非常清晰明了,算法通过combineByKey
计算每个分类下:
\(p_k=\frac{\sum_{j=1}^M\mathbb{I}(y^j=y_k)}{M}\)和\(\theta(,k)=\frac{\sum_{j=1}^M\mathbb{I}(y^j=y_k)\cdot{X^j}+\alpha}{\sum_{j=1}^M{X^j}+\alpha\cdot{M}}\)
20 newsgroups实践
数据集分为train和test两组,分别用于训练和测试。每组数据都分为20类,每类数据存放在各自子文件下:
.
├── 20news-bydate-test
│ ├── alt.atheism
│ ├── comp.graphics
│ ├── comp.os.ms-windows.misc
│ ├── comp.sys.ibm.pc.hardware
│ ├── comp.sys.mac.hardware
│ ├── comp.windows.x
│ ├── misc.forsale
│ ├── rec.autos
│ ├── rec.motorcycles
│ ├── rec.sport.baseball
│ ├── rec.sport.hockey
│ ├── sci.crypt
│ ├── sci.electronics
│ ├── sci.med
│ ├── sci.space
│ ├── soc.religion.christian
│ ├── talk.politics.guns
│ ├── talk.politics.mideast
│ ├── talk.politics.misc
│ └── talk.religion.misc
└── 20news-bydate-train
├── alt.atheism
├── comp.graphics
├── comp.os.ms-windows.misc
├── comp.sys.ibm.pc.hardware
├── comp.sys.mac.hardware
├── comp.windows.x
├── misc.forsale
├── rec.autos
├── rec.motorcycles
├── rec.sport.baseball
├── rec.sport.hockey
├── sci.crypt
├── sci.electronics
├── sci.med
├── sci.space
├── soc.religion.christian
├── talk.politics.guns
├── talk.politics.mideast
├── talk.politics.misc
└── talk.religion.misc
原始文档将经过如下流程训练得到NaiveBayes模型:
代码中的几点注解:
- 各类数据根据所在的子文件夹来分类,我们在写代码时需要利用子文件夹名称,这时可以通过调用
sc.wholeTextFiles(...)
函数得到RDD(String,String)
类型的原始数据,_1表示文件的绝对路径,_2表示该文件的内容。我们进一步从_1中截取出子文件夹的名称f.split("/").takeRight(2).head
. - pipeline框架基于DataFrame,所有我们需要将
RDD
转为DataFrame:
import sqlContext.implicits._
labelNameAndData.toDF("id", "sentence").cache()```
- 所有的转换都使用ml提供的类,未做任何定制或改动,当前模型在测试集上的准确度为82%。
代码:
```scala
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.classification.NaiveBayes
import org.apache.spark.ml.evaluation.MulticlassClassificationEvaluator
import org.apache.spark.ml.feature.{HashingTF, IDF, Tokenizer}
import org.apache.spark.{Logging, SparkConf, SparkContext}
object NBTest extends App with Logging {
def createRawDf(s: String) = {
//sc.setLogLevel("INFO")
val fileNameData = sc.wholeTextFiles(s)
val uniqueLabels = Array("alt.atheism", "comp.graphics", "comp.os.ms-windows.misc", "comp.sys.ibm.pc.hardware", "comp.sys.mac.hardware", "comp.windows.x", "misc.forsale", "rec.autos", "rec.motorcycles", "rec.sport.baseball", "rec.sport.hockey", "sci.crypt", "sci.electronics", "sci.med", "sci.space", "soc.religion.christian", "talk.politics.guns", "talk.politics.mideast", "talk.politics.misc", "talk.religion.misc")
val uniqueLabelsBc = sc.broadcast(uniqueLabels)
val labelNameAndData = fileNameData
.map { case (f, data) => (f.split("/").takeRight(2).head, data) }
.mapPartitions {
itrs =>
val labelIdMap = uniqueLabelsBc.value.zipWithIndex.toMap
itrs.map {
case (labelName, data) => (labelIdMap(labelName), data)
}
}
import sqlContext.implicits._
labelNameAndData.toDF("id", "sentence").cache()
}
def createTrainPpline() = {
val tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words")
val hashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures")
val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
//val vecAssembler = new VectorAssembler().setInputCols(Array("features")).setOutputCol("id")
val nb = new NaiveBayes().setFeaturesCol("features").setLabelCol("id")
new Pipeline().setStages(Array(tokenizer, hashingTF, idf, nb))
}
val conf = new SparkConf().setMaster("local[2]").setAppName("nb")
.set("spark.ui.enabled", "false")
val sc = new SparkContext(conf)
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
val training = createRawDf("file:////root/work/test/20news-bydate-train/*")
val ppline = createTrainPpline()
val nbModel = ppline.fit(training)
val test = createRawDf("file:////root/work/test/20news-bydate-test/*")
val testRes = nbModel.transform(test)
val evaluator = new MulticlassClassificationEvaluator().setLabelCol("id")
val accuracy = evaluator.evaluate(testRes)
println("Test Error = " + (1.0 - accuracy))
}
MLLib实践Naive Bayes的更多相关文章
- Spark MLlib 之 Naive Bayes
1.前言: Naive Bayes(朴素贝叶斯)是一个简单的多类分类算法,该算法的前提是假设各特征之间是相互独立的.Naive Bayes 训练主要是为每一个特征,在给定的标签的条件下,计算每个特征在 ...
- Naive Bayes理论与实践
Naive Bayes: 简单有效的常用分类算法,典型用途:垃圾邮件分类 假设:给定目标值时属性之间相互条件独立 同样,先验概率的贝叶斯估计是 优点: 1. 无监督学习的一种,实现简单,没有迭代,学习 ...
- PGM:贝叶斯网表示之朴素贝叶斯模型naive Bayes
http://blog.csdn.net/pipisorry/article/details/52469064 独立性质的利用 条件参数化和条件独立性假设被结合在一起,目的是对高维概率分布产生非常紧凑 ...
- 机器学习---用python实现朴素贝叶斯算法(Machine Learning Naive Bayes Algorithm Application)
在<机器学习---朴素贝叶斯分类器(Machine Learning Naive Bayes Classifier)>一文中,我们介绍了朴素贝叶斯分类器的原理.现在,让我们来实践一下. 在 ...
- 【Spark机器学习速成宝典】模型篇04朴素贝叶斯【Naive Bayes】(Python版)
目录 朴素贝叶斯原理 朴素贝叶斯代码(Spark Python) 朴素贝叶斯原理 详见博文:http://www.cnblogs.com/itmorn/p/7905975.html 返回目录 朴素贝叶 ...
- [Machine Learning & Algorithm] 朴素贝叶斯算法(Naive Bayes)
生活中很多场合需要用到分类,比如新闻分类.病人分类等等. 本文介绍朴素贝叶斯分类器(Naive Bayes classifier),它是一种简单有效的常用分类算法. 一.病人分类的例子 让我从一个例子 ...
- Microsoft Naive Bayes 算法——三国人物身份划分
Microsoft朴素贝叶斯是SSAS中最简单的算法,通常用作理解数据基本分组的起点.这类处理的一般特征就是分类.这个算法之所以称为“朴素”,是因为所有属性的重要性是一样的,没有谁比谁更高.贝叶斯之名 ...
- [ML] Naive Bayes for Text Classification
TF-IDF Algorithm From http://www.ruanyifeng.com/blog/2013/03/tf-idf.html Chapter 1, 知道了"词频" ...
- 朴素贝叶斯方法(Naive Bayes Method)
朴素贝叶斯是一种很简单的分类方法,之所以称之为朴素,是因为它有着非常强的前提条件-其所有特征都是相互独立的,是一种典型的生成学习算法.所谓生成学习算法,是指由训练数据学习联合概率分布P(X,Y ...
随机推荐
- vmstat工具
vmstat vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写, 是实时系统监控工具.该命令通过使用knlist子程序和/dev/kmen伪设备驱动器访问这些数 ...
- Educational Codeforces Round 58
D. GCD Counting 题意: 给出n个点的树,每个点有一个权值,找出一条最长的路径使得路径上所有的点的gcd>1 题解: gcd>1的一定不会有很多.所以暴力搞一下就行,不需要点 ...
- TextView UI美化-------自适应字体控件
http://www.cnblogs.com/psuwgipgf/p/4874158.html 一. TextView字体随大小变化自适应TextView 实现依靠于第三方类库 第三方类来源: htt ...
- .Net多线程 并行编程(三)---并行集合
为了让共享的数组,集合能够被多线程更新,我们现在(.net4.0之后)可以使用并发集合来实现这个功能. 而System.Collections和System.Collections.Generic命名 ...
- Algorithmic Trading[z]
Algorithmic Trading has been a hot topic for equity/derivative trading over a decade. Many ibanks an ...
- Python高级用法篇——笔记
1.Python3字典中items()和python2.x中iteritems()的区别 在Python2.x中,items( )用于 返回一个字典的拷贝列表[Returns a copy of th ...
- Linux wget命令
一.简介 wget是一个Linux系统中的下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器.wget支持HTTP,HTTPS ...
- PAT 1083 是否存在相等的差(20)(代码+思路)
1083 是否存在相等的差(20 分) 给定 N 张卡片,正面分别写上 1.2.--.N,然后全部翻面,洗牌,在背面分别写上 1.2.--.N.将每张牌的正反两面数字相减(大减小),得到 N 个非负差 ...
- 一名优秀的UI设计师应该具备哪些条件?
想做好一个好的UI设计师除了应该具有一定的审美能力,还要了解整个产品的开发过程,因为目前国内的软件行业还不能对UI设计形成应有的重视度,所以对我们的要求就更高了,你要能作出夺人眼球的东西,还要站在用户 ...
- Eclipse使用。
1. 如何把项目部署到jetty根目录. 先部署.然后在jetty安装根目录下找到contexts,在里面找到你项目名.xml文件.打开后,把<Set name="configurat ...