(http://youzitool.com 新博客,欢迎访问)

这几天一直在忙着找暑假实习,实在没精力来写新的文章。刚好这几天放假,我把前几天做了的另一个例子拿出来跟大家分享一下。

这个例子是使用hadoop来实现TF-IDF。

TF-IDF(term frequency–inverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术。具体的信息就麻烦大家自己百度一下了。

因为要实现的细节比较多,所以我直接将代码放上来。大家可以参看代码里面的注释,我写的比较详细。

我采用了两个MapReduce任务顺序执行来实现TF-IDF功能。

public class My_TDIF {//part1------------------------------------------------------------------------public static class Mapper_Part1 extends Mapper<LongWritable, Text, Text, Text> {String File_name = ""; //保存文件名,根据文件名区分所属文件int all = 0; //单词总数统计static Text one = new Text("1");String word;public void map(LongWritable key, Text value, Context context)throws IOException, InterruptedException {FileSplit split = (FileSplit) context.getInputSplit();String str = split.getPath().toString();File_name = str.substring(str.lastIndexOf("/")+1); //获取文件名StringTokenizer itr = new StringTokenizer(value.toString());while (itr.hasMoreTokens()) {word = File_name ;word += " ";word += itr.nextToken(); //将文件名加单词作为key es: test1 hello 1all++;context.write(new Text(word), one);}}public void cleanup(Context context) throws IOException,InterruptedException {//Map的最后,我们将单词的总数写入。下面需要用总单词数来计算。String str = "";str += all;context.write(new Text(File_name + " " + "!"), new Text(str));//主要这里值使用的 "!"是特别构造的。 因为!的ascii比所有的字母都小。}}public static class Combiner_Part1 extends Reducer<Text, Text, Text, Text> {float all = 0;public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {int index = key.toString().indexOf(" ");//因为!的ascii最小,所以在map阶段的排序后,!会出现在第一个if (key.toString().substring(index + 1, index + 2).equals("!")){for (Text val : values) {//获取总的单词数。all = Integer.parseInt(val.toString());}//这个key-value被抛弃return;}float sum = 0; //统计某个单词出现的次数for (Text val : values) {sum += Integer.parseInt(val.toString());}//跳出循环后,某个单词数出现的次数就统计完了,所有 TF(词频) = sum / allfloat tmp = sum / all;String value = "";value += tmp; //记录词频//将key中单词和文件名进行互换。es: test1 hello -> hello test1String p[] = key.toString().split(" ");String key_to = "";key_to += p[1];key_to += " ";key_to += p[0];context.write(new Text(key_to), new Text(value));}}public static class Reduce_Part1 extends Reducer<Text, Text, Text, Text> {public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {for (Text val : values) {context.write(key, val);}}}public static class MyPartitoner extends Partitioner<Text, Text>{//实现自定义的Partitioner@Overridepublic int getPartition(Text key, Text value, int numPartitions) {//我们将一个文件中计算的结果作为一个文件保存//es: test1 test2String ip1 = key.toString();ip1 = ip1.substring(0, ip1.indexOf(" "));Text p1 = new Text(ip1);return Math.abs((p1.hashCode() * 127) % numPartitions);} }//part2-----------------------------------------------------public static class Mapper_Part2 extendsMapper<LongWritable, Text, Text, Text>{public void map(LongWritable key, Text value, Context context)throws IOException, InterruptedException{String val = value.toString().replaceAll(" ", " "); //将vlaue中的TAB分割符换成空格 es: Bank test1 0.11764706 -> Bank test1 0.11764706int index = val.indexOf(" ");String s1 = val.substring(0, index); //获取单词 作为key es: helloString s2 = val.substring(index + 1); //其余部分 作为value es: test1 0.11764706s2 += " ";s2 += "1"; //统计单词在所有文章中出现的次数, “1” 表示出现一次。 es: test1 0.11764706 1context.write(new Text(s1), new Text(s2));}} public static class Reduce_Part2 extendsReducer<Text, Text, Text, Text>{int file_count;public void reduce(Text key, Iterable<Text>values, Context context)throws IOException, InterruptedException{//同一个单词会被分成同一个groupfile_count = context.getNumReduceTasks(); //获取总文件数float sum = 0;List<String> vals = new ArrayList<String>();for (Text str : values){int index = str.toString().lastIndexOf(" ");sum += Integer.parseInt(str.toString().substring(index + 1)); //统计此单词在所有文件中出现的次数vals.add(str.toString().substring(0, index)); //保存}float tmp = sum / file_count; //单词在所有文件中出现的次数除以总文件数 = DFfor (int j = 0;j < vals.size(); j++){String val = vals.get(j);String end = val.substring(val.lastIndexOf(" "));float f_end = Float.parseFloat(end); //读取TFval += " ";val += tmp;val += " ";val += f_end / tmp; // f_end / tmp = tf-idf值context.write(key, new Text(val));}} }public static void main(String[] args) throws Exception {Path tmp = new Path("tmp"); //设置中间文件临时存储目录 //part1----------------------------------------------------Configuration conf1 = new Configuration();//设置文件个数,在计算DF(文件频率)时会使用FileSystem hdfs = FileSystem.get(conf1);FileStatus p[] = hdfs.listStatus(new Path(args[1]));//获取输入文件夹内文件的个数,然后来设置NumReduceTasksJob job1 = new Job(conf1, "My_tdif_part1");job1.setJarByClass(My_TDIF.class);job1.setMapperClass(Mapper_Part1.class);job1.setCombinerClass(Combiner_Part1.class); //combiner在本地执行,效率要高点。job1.setReducerClass(Reduce_Part1.class);job1.setMapOutputKeyClass(Text.class);job1.setMapOutputValueClass(Text.class);job1.setOutputKeyClass(Text.class);job1.setOutputValueClass(Text.class);job1.setNumReduceTasks(p.length);job1.setPartitionerClass(MyPartitoner.class); //使用自定义MyPartitonerFileInputFormat.addInputPath(job1, new Path(args[1]));FileOutputFormat.setOutputPath(job1, tmp);job1.waitForCompletion(true);//part2----------------------------------------Configuration conf2 = new Configuration();Job job2 = new Job(conf2, "My_tdif_part2");job2.setJarByClass(My_TDIF.class);job2.setMapOutputKeyClass(Text.class);job2.setMapOutputValueClass(Text.class);job2.setOutputKeyClass(Text.class);job2.setOutputValueClass(Text.class);job2.setMapperClass(Mapper_Part2.class);job2.setReducerClass(Reduce_Part2.class);//需要提醒下,我这里没有使用自定义Partitioner,默认的Partitioner会根据key来划分,而我们正//好需要这种方式来将所有文件中同一个单词化为同一个组,方便我们统计一个单词在所以文件中出现的次数。job2.setNumReduceTasks(p.length);FileInputFormat.setInputPaths(job2, tmp);FileOutputFormat.setOutputPath(job2, new Path(args[2]));job2.waitForCompletion(true);hdfs.delete(tmp, true);} }

最后,我再针对此代码补充几点。

1:因为hadoop对处理小文件的效率比较低,如果需要处理很多小文件,我推荐大家可以将很多小文件合并成一个SequenceFile,用文件名作为key,内容作为value。然后处理SequenceFile文件,提高效率

2: 本代码中还有很多可以改进的地方。比如:本代码的最后输出包含了很多中间数据,大家可以根据自己的需要删除不需要的数据。

本代码是根据输入的文件数来确定ReduceTask数和最后的文件输出数,大家也可以自己修改。最后文件的输出内容也是无序的,如果大家需要可以参看本博的另一篇博文(http://blog.csdn.net/jackydai987/archive/2011/03/12/6244725.aspx)进行多文件输出。

3:本文只是提供一个简单的思路,如果代码中有什么不对的地方请各位大大不要见笑,和给偶提出来,在下感激不尽。

运用hadoop计算TF-IDF相关推荐

  1. 搜索引擎:文本分类——TF/IDF算法

    原理 TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类.TFIDF实际上是:TF * IDF,TF ...

  2. 关键词提取算法—TF/IDF算法

    关键词提取算法一般可分为有监督学习和无监督学习两类. 有监督的关键词提取方法可以通过分类的方式进行,通过构建一个较为完善的词表,然后判断每个文档与词表中的每个词的匹配程度,以类似打标签的方式,达到关键 ...

  3. tf/idf_Neo4j:带密码的TF / IDF(和变体)

    tf/idf 几周前,我写了一篇博客文章,介绍了如何使用scikit-learn在HIMYM成绩单上运行TF / IDF,以按情节找到最重要的短语,然后我很好奇在Neo4j中很难做到. 我首先将Wik ...

  4. Neo4j:带密码的TF / IDF(和变体)

    几周前,我写了一篇博客文章,介绍了如何使用scikit-learn在HIMYM成绩单上运行TF / IDF,以按情节找到最重要的短语,然后我很好奇在Neo4j中很难做到. 我首先将Wikipedia的 ...

  5. scitkit-learn:计算机科学论文的TF / IDF和余弦相似度

    几个月前,我下载了数千篇计算机科学论文的元数据,这样我就可以尝试编写一个迷你推荐引擎来告诉我接下来应该读什么论文. 由于我没有任何人可以阅读每篇论文的数据,因此排除了协作过滤方法,所以我认为我可以尝试 ...

  6. 文本特征抽取的向量空间模型(VSM)和TF/IDF方法

    文本特征抽取 两组小说,一组是爱情的,另一组是科幻的.我们能否用支持向量机训练一个模型,用来识别小说类型呢? 这个并不容易.因为支持向量机这类机器学习算法只能接受数学里面的向量作为输入.如果用它来做文 ...

  7. tf-idf词向量和bow_使用词袋Bow和TF IDF进行多标签分类

    tf-idf词向量和bow 1.加载数据 (1. Load the data) For this study, we are using Kaggle data for Toxic Comment C ...

  8. 【笔记】手敲版 TF IDF

    注1: 1.  涉及计算向向量夹角  [笔记]向量点乘(内积)和叉乘(外积.向量积):对两个向量执行点乘运算,是对这两个向量对应位一一相乘之后求和的操作,点乘的结果是一个标量:叉乘结果是一个向量,它垂 ...

  9. Hadoop安装配置,并使用Hadoop计算圆周率测试Hadoop是否安装成功

    一.实验目的 掌握如何安装.配置和运行Hadoop,并使用Hadoop计算圆周率测试Hadoop是否安装成功. 二.实验环境 (1)Linux Ubuntu 16.04 (2)jdk-8u162-li ...

  10. hadoop矩阵乘法源码_使用Hadoop计算共现矩阵

    hadoop矩阵乘法源码 这篇文章继续我们在MapReduce的数据密集型文本处理一书中实现MapReduce算法的系列. 这次,我们将从文本语料库创建单词共现矩阵. 本系列以前的文章是: 使用Map ...

最新文章

  1. Android Studio第三十四期 - git企业级应用命令
  2. python3 hashlib加密库 md5 sha1 sha256 sha384 sha512 加盐
  3. python比java简单好学-python和java哪个学起来更简单
  4. 全景视频的跟踪与合成方法
  5. 基于源码编辑器的跑酷游戏设计
  6. 程序员面试系列——有符号数的溢出
  7. Avalonia跨平台入门第六篇之Grid动态分割
  8. centos6 yum源_Centos6安装Zabbix3.4.15注意事项
  9. pods报错修复方法
  10. https报文 完整_报文 HTTP HTTPS
  11. MySQL安装详细图解
  12. 按3倍中误差去除粗差(C++)
  13. 宝塔安装RSSHub订阅服务
  14. Flutter 内外边距
  15. Java利用递归算法实现24点游戏
  16. linux 光标切换快捷键,光标操作快捷键,光标快捷键
  17. OneNote笔记本分类方法
  18. SLCP验厂辅导,SLCP是向最终用户分享已验证的评估数据的关键
  19. POJ 1659 Frogs‘ Neighborhood (Havel 定理)
  20. C++ 数据结构(三)列表(3)有序列表

热门文章

  1. 从XData大数据一体机看曙光转型
  2. SpringBoot实战(十八):签到奖励实现方案
  3. 英语字谜求解程序(JAVA):iMessage-GamePigeon的“字谜”
  4. platform总线
  5. 成都大数据培训之Python一系列的知识整理
  6. imx6ul链接地址、运行地址、加载地址、位置无关、mmu的关系
  7. html5字体加重,javascript – Html5画布字体重量渲染比它应该重得多
  8. Ada学习(2)Statements
  9. python中等待一秒的语句_selenium之等待时间(python)
  10. 解决多线程并发安全问题