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. 【SSH系列】---Hibernate的基本映射

    开篇前言       在前面的博文中,小编分别介绍了[SSH系列]-- hibernate基本原理&&入门demo,通过这篇博文,小伙伴们对hibernate已经有了基本的了解,以及h ...

  2. Android Multimedia框架总结(七)C++中MediaPlayer的C/S架构补充及MediaService介绍

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼,文章链接: http://blog.csdn.net/hejjunlin/article/details/52465168 前面一篇主要介绍 ...

  3. 深入浅出seesion和cookie

    session在计算机中,尤其是在网络应用中,称为"会话控制".session 对象存储特定用户会话所需的属性及配置信息.session跟踪是Web程序中常用的技术,用来跟踪用户的 ...

  4. 【NPR】铅笔画

    写在前面 今天打算写一篇跟Unity基本无关的文章.起因是我上个星期不知怎么的搜到了一个网站 ,里面实现的效果感觉挺好的,后来发现是2012年的NPAR会议的最佳论文.看了下文章,觉得不是很难,就想着 ...

  5. GCD API记录(二)

    前言 这是关于GCD的第二篇文章,GCD的API有100多个,通过快捷键Option + 单击,可以在Reference中的Grand Central Dispatch (GCD) Reference ...

  6. API创建/更新员工薪水

    DECLARE lb_inv_next_sal_date_warning BOOLEAN; lb_proposed_salary_warning BOOLEAN; lb_approved_warnin ...

  7. 根据iOS 10 的新特性,创建iMessage App,可用于自定义表情

    第一. 介绍(原文作者 澳大利亚19岁少年--Davis Allie ----原文地址) 随着iOS10的发布,苹果对开发者开放了Messages应用程序,开发人员现在可以创建他们自己的各种类型 并且 ...

  8. 安装解压版本的MySQL,安装过程中的常见命令,检查windows系统错误日志的方式来检查MySQL启动错误,关于Fatal error: Can't open and lock privilege

     以端口 port = 3306 # 设置mysql的安装目录 basedir=D://Installed//mysql-5.6.26-winx64//mysql-5.6.26-winx64 # ...

  9. 06_MyBatis,Spring,SpringMVC整合

     项目结构 Spring的配置: beans.xml <?xml version="1.0" encoding="UTF-8"?> <be ...

  10. C++对象模型的那些事儿之六:成员函数调用方式

    前言 C++的成员函数分为静态函数.非静态函数和虚函数三种,在本系列文章中,多处提到static和non-static不影响对象占用的内存,而虚函数需要引入虚指针,所以需要调整对象的内存布局.既然已经 ...