Mahout Bayes分类器是按照《Tackling the Poor Assumptions of Naive Bayes Text Classiers》论文写出来了,具体查看论文

实现包括三部分:The Trainer(训练器)、The Model(模型)、The Classifier(分类器)

1、训练

首先,要对输入数据进行预处理,转化成Bayes M/R job读入数据要求的格式,即训练器输入的数据是KeyValueTextInputFormat格式,第一个字符是类标签,剩余的是特征属性(即单词)。以20个新闻的例子来说,从官网上下载的原始数据是一个分类目录,下面每个文件夹名就是类标签,里面是属于此类的一些文档(一个文件是一篇文章)。mahout通过org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups对数据进行预处理,完成的工作是对于原始的一个分类目录下面的所有文件,依次遍历,并将目录名作为类别名,就这样完成了inputDir-->outputFile的转变。如果要处理html文件的话,那么就需要在BayesFileFormatter调用html clean,extract body text的过程,生成cleaned text。

PrepareTwentyNewsgroups调用org.apache.mahout.classifier.BayesFileFormatter和org.apache.lucene.analysis.standard.StandardAnalyzer进行分析处理,将数据转换成了:类标签作为一个文件的名字,文件里每一个行(一个回车算一行)是包含在此类中的一篇文章(格式是:类标签 一篇文章中的所有单词)。

BayesFileFormatter的作用是把一个目录里的所有文件转换成一个文件,label \t content其中的文件内容全部经过tokenize,词之间加入空格,存入content。BayesFileFormatter.collapse的作用是将一个目录的所有文件加上label处理成MapReduce所需要的按行处理的文件格式,变成1个文件。

其次,调用org.apache.mahout.classifier.bayes.TrainClassifier进行训练,结果生成newsmodel。

这个类会根据命令行参数调用两个训练器:trainCNaiveBayes和trainNaiveBayes,其中trainCNaiveBayes函数调用CBayesDriver类;trainNaiveBayes调用BayesDriver类。

这里只分析org.apache.mahout.classifier.bayes.mapreduce.bayes.BayesDriver类,它实现了BayesJob接口,在runJob函数里调用4个map/reduce作业类:

第一个:BayesFeatureDriver负责Read the features in each document normalized by length of each document

第二个:BayesTfIdfDriver负责Calculate the TfIdf for each word in each label

第三个:BayesWeightSummerDriver负责alculate the Sums of weights for each label, for each feature

第四个:BayesThetaNormalizerDriver负责:Calculate the normalization factor Sigma_W_ij for each complement class

以20-news的例子分别分析这四个类:

⑴BayesFeatureDriver

所在包:package org.apache.mahout.classifier.bayes.mapreduce.common;

输入格式:KeyValueTextInputFormat.class

输出格式:BayesFeatureOutputFormat.class

输出key类型:StringTuple.class

输出value类型:DoubleWritable.class

Map:BayesFeatureMapper.class

Reduce:BayesFeatureReducer.class

注意:BayesFeatureDriver可以独立运行,默认的输入和输出:(没有试过,不知道可不可以独立运行,里面有main函数,应该是可以的,不过本人水平有限,目前不会)

input=new Path("/home/drew/mahout/bayes/20news-input");

output=new Path("/home/drew/mahout/bayes/20-news-features");

p=new BayesParameters(1) gramsize默认为1

BayesFeatureOutputFormat继承了MultipleOutputFormat,定义了产生的四个文件路径及名字,文件的格式还是SequenceFileOutputFormat.:

$OUTPUT/trainer-wordFreq

$OUTPUT/trainer-termDocCount

$OUTPUT/trainer-featureCount

$OUTPUT/trainer-docCount

①BayesFeatureMapper的输出为:

一行一个map,根据数据处理的格式即一篇文章一个map,以下的label指类标签,token是属性即单词,dKJ是某token在本篇文章中出现的次数,∑dKJ2是本篇文章中所有token出现次数的平方和,以下及后面的表格是觉得看着清楚自己画的,输出时只是里面的内容,例如:_WT,label,token空格value的值

key

value

_WT,label,token

Log[(1.0+dKJ)/(∑dKJ2)1/2]即为某词在一个文档中的TF值

通俗点就是:Log[(1.0+某属性在本篇文章中出现的次数)/(本篇文章中所有属性出现次数的平方和)1/2]

_DF,label,token

1.0

_FC,token

1.0

_LC,label

1.0

②BayesFeatureReducer的输出为:

相同的key放在一个reduce里执行合并

key

value

输出

_WT,label,token

∑Log[(1.0+dKJ)/(∑dKJ2)1/2]即某类中某属性的TF值

trainer-wordFreq

_DF,label,token

某label中出现某token的文档数

trainer-termDocCount

_FC,token

所有训练集文章中出现某token的文档数

trainer-featureCount

_LC,label

某label下的文档数

trainer-docCount

_FT,token

与_FC的value一样

没输出且只在mhaout-0.4里出现这部分计算,0.3里没有

⑵BayesTfIdfDriver

输入格式:SequenceFileInputFormat.class

输出格式:BayesTfIdfOutPutFormat.class

输出key类型:StringTuple.class

输出value类型:DoubleWritable.class

输入路径:就是第一个map/reduce生成的trainer-wordFreq、trainer-termDocCount、trainer-featureCount文件

输出:trainer-tfIdf文件

Map:BayesTfIdfMapper.class

Reduce:BayesTfIdfReducer.class

根据BayesFeatureReducer的输出文件计算TF-IDF值,但是只调用了以上的trainer-wordFreq、trainer-termDocCount、trainer-featureCount三个文件,计算完毕后会删除这些中间文件(目前还没搞懂在哪删除的,只看见bayesDriver里面有把),并生成两个文件trainer-tfIdf和trainer-vocabCount(BayesTfIdfOutPutFormat里有)。

①BayesTfIdfMapper的输出为:

TF值是调用trainer-wordFreq中的value

Idf=某类下的文档数/某类下出现该token的文档数

其中某类下出现该token的文档数是调用trainer-termDocCount中的value

key

value

_WT,label,token

TF值

_WT,label,token

logidf

_FS

1.0

②BayesTfIdfReducer的输出为:

key

value

输出

_WT,label,token

TF×logidf

trainer-tfidf

_FS

属性总数

trainer-VocabCount

⑶BayesWeightSummerDriver

输入文件格式:SequenceFileInputFormat.class

输出文件格式:BayesWeightSummerOutputFormat.class

输出key:StringTuple.class

输出value:DoubleWritable.class

输入路径:是第二个map/reduce生成的trainer-tfIdf文件

输出:trainer-weights文件

Map:BayesWeightSummerMapper.class

Reduce:BayesWeightSummerReducer.class

这里只调用了第二个map/reduce生成的trainer-tfIdf,没有调trainer-VocabCount

①BayesWeightSummerMapper的输出为:

key

value

_SJ,token

TFIdf值

_SK,label

TFIdf值

_SJSK

TFIdf值

②BayesWeightSummerReducer的输出为:

key

value

输出

_SJ,token

某属性的全部TFIdf总和

Sigma_j

_SK,label

某类下的所有属性的TFIdf总和

Sigma_k

_SJSK

所有的TFIdf值

Sigma_kSigma_j

⑷BayesThetaNormalizerDriver

输入文件格式:SequenceFileInputFormat.class

输出文件格式:SequenceFileOutputFormat.class

输出key:StringTuple.class

输出value:DoubleWritable.class

输入路径: 第二个map/reduce生成的trainer-tfIdf/下的trainer-tfIdf和trainer-VocabCount,以及trainer-weights/的Sigma_k和Sigma_kSigma_j

输出:trainer-thetaNormalizer文件

①BayesWeightSummerMapper的输出为:

Log里的分子中TFIdf是某类下某属性的TFIdf值,分母中VocabCount是属性总数

key

value

_LTN,label

Log[(TFIdf+1.0)/(sigma_k+VocabCount)]

②BayesWeightSummerReducer的输出为:

将Map的结果合并

key

value

_LTN,label

ΣLog[(TFIdf+1.0)/(sigma_k+VocabCount)]

2、模型

以上训练部分的四个job执行完毕后,整个bayes模型就建立完毕了,总共生成并保存三个目录文件:

trainer-tfIdf

trainer-weights

trainer-thetaNormalizer

我们可以将模型从分布式上Sequence文件导成本地的txt文件进行查看。

3、测试

调用类:TestClassifier

所在包:package org.apache.mahout.classifier.bayes;

根据命令行参数会选择顺序执行还是并行map/reduce执行,这里只分析并行map/reduce,执行时会调用BayesClassifierDriver类

分析BayesClassifierDriver类

先runjob,runjob中先运行BayesClassifierMapper再是BayesClassifierReducer,job执行完毕后会调用混合矩阵:ConfusionMatrix函数显示结果

⑴BayesClassifierMapper

首先,运行configure:先algorithm=new BayesAlgorithm()和datastore=new InMemoryDatastore(params),datastore时InMemoryDatastore(params)方法将模型装入到datastore中即装入Sigma_j、Sigma_k、Sigma_kSigma_j、thetaNormalizer、weight=TfIdf、alpha_i=1.0);再classifier=new classifierContext(algorithm,datastore),classifier.initialize(),即初始化classifier,初始化classifier是datastore.initialize()和algorithm.initialize(this.datastore)。

datastore的初始化:

调用SequenceFileModelReader的loadModel方法(五个Load方法):

①loadFeatureWeights(装入的是Sigma_j)生成hashmap Sigma_j{0,weight 1,weight …}其中0、1…等是属性的标号,weight是Sigma_j的value。

②loadLabelWeights(装入的是Sigma_k)生成hashmap Sigma_k{0,weight 1,weight …}其中0、1…等是label即类标签的标号,weight是Sigma_k的value。

③loadSumWeight(装入的是Sigma_kSigma_j)使datastore的成员变量Sigma_jSigma_k=value(训练得到的所有tfidf总和)。

④loadThetaNormalizer(装入的是ThetaNormalizer)生成hashmap thetaNormalizerPerlabel{0,weight 1,weight …}其中weight是传进来的value,使datastore的成员变量thetaNormalizer=Max(1.0 |weight|)。

⑤loadWeightMatrix(装入的是weight即tfidf)生成weightMatrix是SparseMatrix,其中行是属性的标号,列是label的标号,行列交叉的地方是tfidf。

algorithm的初始化:

调用datastore.getKeys,getKeys返回labeldicionary.Keys即返回一个集合,里面放的是所有的label。

其次,运行map:开始分类classifier.classifyDocument(),classifyDocument()调用algorithm.classifyDocument。先new result{unkonwm,0} categories=”label weight”即所有的label集合;再开始循环:针对每一个类进行循环,调用documenWeight:先计算文档中每个词的次数(frequency),生成一个Map叫wordlist,针对wordlist的each pair计算:∑[frequency×featureweight(datastore,label,word)]。其中featureweight共四个,都调用datastore.getWeight,以下分别分析:

①double result = 调用datastore.getWeight,稀疏矩阵的getQuick,取出矩阵的Tfidf值;

②double vocabCount =属性总数;

③double sumLableWeight =Sigma_k的值;

④double numerator =result + 1.0;

⑤double denominator = sumLableWeight + vocabCount;

⑥double weight =log(numerator/denominator)也就是=log[(Tfidf+1.0)/(Sigma_k+属性个数)];

返回的是result = -weight;

所以说,documenWeight返回的值是测试文档属于某类的概率的大小,即所有属性的在某类下的frequency×result之和与在其他类下的和值进行比较,最大值的,取出它的label,文档就属于此类。

key=_CT 正确label 分类label  value=1.0

⑵BayesClassifierReducer

只是合并map的结果。

key=_CT 正确label 分类label  value=正确分类的文档数

根据对以上∑(frequency×result)进行分析,参照贝叶斯多项式模型,frequency是对weight中取对数时转移到前面的,即log(numerator/denominator)frequency = frequency×log(numerator/denominator),weight是条件概率,即log[(numerator/denominator)frequency

×(numerator/denominator)frequency …] = ∑log(numerator/denominator)frequency因为按贝叶斯原理来说,后验概率=先验概率×条件概率,据我理解,此处为什么没有乘先验概率,可能是因为所用的20个新闻的数据每类中的文档数大致一样,先验概率几乎一样,所以没必要乘(个人猜测)。

⑶ConfusionMatrix函数显示结果

key=正确label  value={key=分类label value=值}

本文转载自:http://blog.163.com/jiayouweijiewj@126/blog/static/17123217720113115027394/

Mahout Bayes分类的更多相关文章

  1. Mahout 分类算法

    实验简介 本次课程学习了Mahout 的 Bayes 分类算法. 一.实验环境说明 1. 环境登录 无需密码自动登录,系统用户名 shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu ...

  2. 机器学习 101 Mahout 简介 建立一个推荐引擎 使用 Mahout 实现集群 使用 Mahout 实现内容分类 结束语 下载资源

      机器学习 101 Mahout 简介 建立一个推荐引擎 使用 Mahout 实现集群 使用 Mahout 实现内容分类 结束语 下载资源 相关主题   在信息时代,公司和个人的成功越来越依赖于迅速 ...

  3. mahout分类

    分类看起来比聚类和推荐麻烦多了 分类算法与聚类和推荐算法的不同:必须是有明确结果的,必须是有监督的,主要用于预测和检测 Mahout的优势 mahout的分类算法对资源的要求不会快于训练数据和测试数据 ...

  4. Mahout简介

    Mahout简介 一.mahout是什么 Apache Mahout是ApacheSoftware Foundation (ASF)旗下的一个开源项目,提供了一些经典的机器学习的算法,皆在帮助开发人员 ...

  5. Apache Mahout:适合所有人的可扩展机器学习框架

    http://www.ibm.com/developerworks/cn/java/j-mahout-scaling/ 在软件的世界中,两年就像是无比漫长的时光.在过去两年中,我们看到了社交媒体的风生 ...

  6. Apache Mahout 简介 通过可伸缩、商业友好的机器学习来构建智能应用程序

    在信息时代,公司和个人的成功越来越依赖于迅速有效地将大量数据转化为可操作的信息.无论是每天处理数以千计的个人电子邮件消息,还是从海量博客文章中推测用户的意图,都需要使用一些工具来组织和增强数据. 这其 ...

  7. mahout的特性(三)

    mahout的特性 虽然在开源领域中相对较为年轻,但 Mahout 已经提供了大量功能,特别是在集群和CF 方面. Mahout 的主要特性包括: Taste CF.Taste 是 Sean Owen ...

  8. 转】Mahout分步式程序开发 聚类Kmeans

    原博文出自于: http://blog.fens.me/hadoop-mahout-kmeans/ 感谢! Mahout分步式程序开发 聚类Kmeans Hadoop家族系列文章,主要介绍Hadoop ...

  9. Mahout分步式程序开发 聚类Kmeans(转)

    Posted: Oct 14, 2013 Tags: clusterHadoopkmeansMahoutR聚类 Comments: 13 Comments Mahout分步式程序开发 聚类Kmeans ...

随机推荐

  1. Android图表库MPAndroidChart(五)——自定义MarkerView实现选中高亮

    Android图表库MPAndroidChart(五)--自定义MarkerView实现选中高亮 在学习本课程之前我建议先把我之前的博客看完,这样对整体的流程有一个大致的了解 Android图表库MP ...

  2. Appium webdriver的capabilities配置

    Capabilities是由客户端发送给Appium服务器端的用来告诉服务器去启动哪种我们想要的会话的一套键值对集合.当中也有一些键值对是用来在自动化的过程中修改服务器端的行为方式. 必填的项目: d ...

  3. [ExtJS5学习笔记]第三十六节 报表组件mzPivotGrid

    mzPivotGrid 是一个报表组件,采用这个组件之后,可以令你的应用体现更多的价值. 什么是pivot grid 什么是mzPivotGrid 学习资源 与图表组件的融合 什么是pivot gri ...

  4. Linux 高性能服务器编程——TCP/IP协议族

    1 TCP/IP协议族体系结构 数据链路层:     职责:实现网卡接口的网络驱动程序,一处理数据在物理媒介(如以太网.令牌环等)上的传输.     常用协议:ARP协议(地址解析协议),RARP协议 ...

  5. UNIX网络编程——尝试探索基于Linux C的网卡抓包过程

     抓包首先便要知道经过网卡的数据其实都是通过底层的链路层(MAC),在Linux系统中我们获取网卡的数据流量其实是直接从链路层收发数据帧.至于如何进行TCP/UDP连接本文就不再赘述(之前的一段关于w ...

  6. 关于GCJ02和WGS84坐标系的一点实验

    大家都知道,在兲朝的电子地图的坐标都是经过了一个坐标偏移,叫GCJ_02的东西.在网上发现了将WGS84经纬度转成GCJ02的一个代码,写了个小程序测试了下看看全国各地的偏移量有多大. 关于WGS84 ...

  7. Swift基础之Animation动画研究

    最近研究了一下,Swift语言中关于Animation动画的实现学习,分两次进行相关内容的讲解 用表格列出各种动画情况 Demo首页显示展示了一种动画显示方式,代码如下: //绘画装饰    func ...

  8. Android简易实战教程--第二话《两种进度条》

    点击按钮模拟进度条下载进度,"下载"完成进度条消失. 代码如下: xml: <?xml version="1.0" encoding="utf- ...

  9. 【一天一道LeetCode】#349. Intersection of Two Arrays

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given t ...

  10. IBM SPSS 实习总结

    2015过完年,我知道导师要出国了,自己也算是水了一个idea 的论文.希望研二能找个实习,早听说西安IBM这边有学长在里面实习过,2月底联系了一下简历就塞了过去.面试就在锦业一路软件园他们上班的地方 ...