接上篇,SequenceFileTokenizerMapper的输出文件在/home/mahout/mahout-work-mahout0/20news-vectors/tokenized-documents/part-m-00000文件即可查看,同时可以编写下面的代码来读取该文件(该代码是根据前面读出聚类中心点文件改编的),如下:

package mahout.fansy.test.bayes.read;

import java.util.ArrayList;
import java.util.List; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Writable;
import org.apache.mahout.common.StringTuple;
import org.apache.mahout.common.iterator.sequencefile.PathFilters;
import org.apache.mahout.common.iterator.sequencefile.PathType;
import org.apache.mahout.common.iterator.sequencefile.SequenceFileDirValueIterable; public class ReadFromTokenizedDocuments { /**
* @param args
*/
private static Configuration conf; public static void main(String[] args) {
conf=new Configuration();
conf.set("mapred.job.tracker", "ubuntu:9001");
String path="hdfs://ubuntu:9000/home/mahout/mahout-work-mahout0/20news-vectors/tokenized-documents/part-m-00000"; getValue(path,conf);
} /**
* 把序列文件读入到一个变量中;
* @param path 序列文件
* @param conf Configuration
* @return 序列文件读取的变量
*/
public static List<StringTuple> getValue(String path,Configuration conf){
Path hdfsPath=new Path(path);
List<StringTuple> list = new ArrayList<StringTuple>();
for (Writable value : new SequenceFileDirValueIterable<Writable>(hdfsPath, PathType.LIST,
PathFilters.partFilter(), conf)) {
Class<? extends Writable> valueClass = value.getClass();
if (valueClass.equals(StringTuple.class)) {
StringTuple st = (StringTuple) value;
list.add(st);
} else {
throw new IllegalStateException("Bad value class: " + valueClass);
}
}
return list;
} }

通过上面的文件可以读取到第一个StringTuple的单词个数有1320个(去掉stop words的单词数);

然后就又是一堆参数的设置,一直到267行,判断processIdf是否为非true,因为前面设置的是tfdif,所以这里进入else代码块,如下:

if (!processIdf) {
DictionaryVectorizer.createTermFrequencyVectors(tokenizedPath, outputDir, tfDirName, conf, minSupport, maxNGramSize,
minLLRValue, norm, logNormalize, reduceTasks, chunkSize, sequentialAccessOutput, namedVectors);
} else {
DictionaryVectorizer.createTermFrequencyVectors(tokenizedPath, outputDir, tfDirName, conf, minSupport, maxNGramSize,
minLLRValue, -1.0f, false, reduceTasks, chunkSize, sequentialAccessOutput, namedVectors);
}

这里直接调用DictionaryVectorizer的createTermFrequencyVectors方法,进入该方法(DictionaryVectorizer的145行),可以看到首先也是一些参数的设置,然后就到了startWordCounting方法了,进入这个方法可以看到这个是一个Job的基本设置,其Mapper、Combiner、Reducer分别为:TermCountMapper、TermCountCombiner、TermCountReducer,下面分别来看各个部分的作用(其实和最基本的wordcount很相似):

TermCountMapper,首先贴代码:

protected void map(Text key, StringTuple value, final Context context) throws IOException, InterruptedException {
OpenObjectLongHashMap<String> wordCount = new OpenObjectLongHashMap<String>();
for (String word : value.getEntries()) {
if (wordCount.containsKey(word)) {
wordCount.put(word, wordCount.get(word) + 1);
} else {
wordCount.put(word, 1);
}
}
wordCount.forEachPair(new ObjectLongProcedure<String>() {
@Override
public boolean apply(String first, long second) {
try {
context.write(new Text(first), new LongWritable(second));
} catch (IOException e) {
context.getCounter("Exception", "Output IO Exception").increment(1);
} catch (InterruptedException e) {
context.getCounter("Exception", "Interrupted Exception").increment(1);
}
return true;
}
});

该部分代码首先定义了一个Mahout开发人员定义的Map类,然后遍历value中的各个单词(比如第一个value中有1320个单词);当遇到map中没有的单词就把其加入map中,否则把map中该单词的数量加1更新原来的单词的数量,即for循环里面做的事情;然后就是forEachPair方法了,这里应该是复写了该方法?好像是直接新建了一个类然后把这个新建的类作为forEachPair的参数;直接看context.write吧,应该是把wordCount(这个变量含有每个单词和它的计数)中的各个单词和单词计数分别作为key和value输出;

然后是TermCountCombiner和TermCountReducer,这两个代码一样的和当初学习Hadoop入门的第一个例子是一样的,这里就不多说了。查看log信息,可以看到reduce一共输出93563个单词。

然后就到了createDictionaryChunks函数了,进入到DictionaryVectorizer的215行中的该方法:

 List<Path> chunkPaths = Lists.newArrayList();

    Configuration conf = new Configuration(baseConf);

    FileSystem fs = FileSystem.get(wordCountPath.toUri(), conf);

    long chunkSizeLimit = chunkSizeInMegabytes * 1024L * 1024L;
int chunkIndex = 0;
Path chunkPath = new Path(dictionaryPathBase, DICTIONARY_FILE + chunkIndex);
chunkPaths.add(chunkPath); SequenceFile.Writer dictWriter = new SequenceFile.Writer(fs, conf, chunkPath, Text.class, IntWritable.class); try {
long currentChunkSize = 0;
Path filesPattern = new Path(wordCountPath, OUTPUT_FILES_PATTERN);
int i = 0;
for (Pair<Writable,Writable> record
: new SequenceFileDirIterable<Writable,Writable>(filesPattern, PathType.GLOB, null, null, true, conf)) {
if (currentChunkSize > chunkSizeLimit) {
Closeables.closeQuietly(dictWriter);
chunkIndex++; chunkPath = new Path(dictionaryPathBase, DICTIONARY_FILE + chunkIndex);
chunkPaths.add(chunkPath); dictWriter = new SequenceFile.Writer(fs, conf, chunkPath, Text.class, IntWritable.class);
currentChunkSize = 0;
} Writable key = record.getFirst();
int fieldSize = DICTIONARY_BYTE_OVERHEAD + key.toString().length() * 2 + Integer.SIZE / 8;
currentChunkSize += fieldSize;
dictWriter.append(key, new IntWritable(i++));
}
maxTermDimension[0] = i;
} finally {
Closeables.closeQuietly(dictWriter);
}

这里看到新建了一个Writer,然后遍历该文件的key和value,但是只读取key值,即单词,然后把这些单词进行编码,即第一个单词用0和它对应,第二个单词用1和它对应。

上面代码使用的dictWriter查看变量并没有看到哪个属性是存储单词和对应id的,所以这里的写入文件的机制是append就写入?还是我没有找到正确的属性?待查。。。

分享,快乐,成长

转载请注明出处:http://blog.csdn.net/fansy1990

Twenty Newsgroups Classification任务之二seq2sparse(2)的更多相关文章

  1. Twenty Newsgroups Classification任务之二seq2sparse(5)

    接上篇blog,继续分析.接下来要调用代码如下: // Should document frequency features be processed if (shouldPrune || proce ...

  2. Twenty Newsgroups Classification任务之二seq2sparse

    seq2sparse对应于mahout中的org.apache.mahout.vectorizer.SparseVectorsFromSequenceFiles,从昨天跑的算法中的任务监控界面可以看到 ...

  3. Twenty Newsgroups Classification任务之二seq2sparse(3)

    接上篇,如果想对上篇的问题进行测试其实可以简单的编写下面的代码: package mahout.fansy.test.bayes.write; import java.io.IOException; ...

  4. mahout 运行Twenty Newsgroups Classification实例

    按照mahout官网https://cwiki.apache.org/confluence/display/MAHOUT/Twenty+Newsgroups的说法,我只用运行一条命令就可以完成这个算法 ...

  5. Twenty Newsgroups Classification实例任务之TrainNaiveBayesJob(一)

    接着上篇blog,继续看log里面的信息如下: + echo 'Training Naive Bayes model' Training Naive Bayes model + ./bin/mahou ...

  6. 项目笔记《DeepLung:Deep 3D Dual Path Nets for Automated Pulmonary Nodule Detection and Classification》(二)(上)模型设计

    我只讲讲检测部分的模型,后面两样性分类的试验我没有做,这篇论文采用了很多肺结节检测论文都采用的u-net结构,准确地说是具有DPN结构的3D版本的u-net,直接上图. DPN是颜水成老师团队的成果, ...

  7. 深度学习数据集Deep Learning Datasets

    Datasets These datasets can be used for benchmarking deep learning algorithms: Symbolic Music Datase ...

  8. Open Data for Deep Learning

    Open Data for Deep Learning Here you’ll find an organized list of interesting, high-quality datasets ...

  9. 深度学习课程笔记(二)Classification: Probility Generative Model

    深度学习课程笔记(二)Classification: Probility Generative Model  2017.10.05 相关材料来自:http://speech.ee.ntu.edu.tw ...

随机推荐

  1. Qt如何读取ico文件中的image(使用QImageReader和QIcon)

    ico文件是一个容器,内部可以装载许多个image,我们可以通过QIcon的pixmap方法来获取需要的image QPixmap pixmap ( const QSize & size, M ...

  2. ASP.NET MVC 5 学习教程:修改视图和布局页

    原文 ASP.NET MVC 5 学习教程:修改视图和布局页 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...

  3. docker学习笔记12:Dockerfile 指令 ENTRYPOINT介绍

    本文介绍Dockerfile的 ENTRYPOINT指令的含义. 先回顾下CMD指令的含义,CMD指令可以指定容器启动时要执行的命令,但它可以被docker run命令的参数覆盖掉. ENTRYPOI ...

  4. 一步一步重写 CodeIgniter 框架 (7) —— Controller执行时将 Model获得的数据传入View中,实现MVC

    1. 实现过程 1) 上一节讲述了 View 视图的加载过程,它是在 Loader 类中加载的,并通过 Include 语句进行包含.那么为了在 View 中传递变量,只需要在 include 语句所 ...

  5. Windows Phone 8初学者开发—第20部分:录制Wav音频文件

    原文 Windows Phone 8初学者开发—第20部分:录制Wav音频文件 原文地址:http://channel9.msdn.com/Series/Windows-Phone-8-Develop ...

  6. cocos2d-x游戏开发系列教程-坦克大战游戏之子弹的碰撞检测处理

    在上篇我们加上了简单的坦克之间的碰撞检测,这篇我们继续加上子弹之间, 子弹与坦克之间的碰撞检测,对于上一篇碰撞处理不太完美的地方我们继续改进. 1.子弹之间的碰撞 //玩家子弹和敌方子弹之间的碰撞 C ...

  7. Android之——Fragment生命周期(日志截图版)

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46867159

  8. Java 螺纹第三版 第三章数据同步 读书笔记

    多线程间共享数据问题 一.Synchronizedkeyword      atomic一词与"原子"无关,它以前被觉得是物质的最小的单元,不能再被拆解成更小的部分.      当 ...

  9. iPhone应用程序开发基础之一: IBOutlet与IBAction

    在图形界面编程时,解决的第一问题就是如何将静态界面与代码关联起来,或者说是代码如何与界面上的对象 通信, 代码如何操作界面上的对象.在iPhone平台上,引入了IBOutlet与IBAction.通过 ...

  10. jqGrid笔记@简单实现

    jqGrid在MVC中的版本是已经通过 HtmlHelper 的扩展方法封装后的产物,webForm版本貌似也将其封装成了服务器端空间,所以我推荐下载原生的jqGrid版本的地址为:http://ww ...