TF-IDF_MapReduceJava代码实现思路

TF-IDF

1.    概念

2.    原理

3.    java代码实现思路

数据集:

三个MapReduce

第一个MapReduce:(利用ik分词器,将一篇博文,也就是一条记录中的content进行词的拆分)

第一个MapReduce最终运行的结果:

1. 得到数据集中微博的总数

2. 得到每个词在当前所属微博的TF值

Mapper端:key:LongWritable(偏移量)   value:3823890314914825    今天天气晴好,姐妹们约起,一起去逛街。

步骤一:拆分读取(按照‘\t‘), 得到id, content

步骤二:利用ik分词器对内容进行分词(今天,天气,姐妹),遍历分词结果,对分词结果中的每一个             词输出(w_id, 1)

步骤三:当对内容进行遍历完成之后,记录当前这一条微博,输出(count,1)

 

第一个MR自定义分区:extends HashPartitioner<Text, IntWritable>,重写getPartition

默认的分区规则:key.hash()%reduce的个数

这里对key的值进行判断,如果key.equals("count"),交给最后一个reduce,否则,交给reduceCount-1

Reducer端:第一种--key:w_id   value:{1,1,1}     第二种--key:count   value{1,1,1.....}

步骤一:将经过shuffle过程后的数据,进行整合(key相同的值为一组,对迭代器中的值进行遍历)

步骤二:将reduce后的结果进行写出,context.write(key, new IntWritable(sum))

                                                 !注意

因为这里在FirstJob中设置了Reduce的个数 (job.setNumReduceTasks(4)),所以最后会有                                                              四个文件输出,而key=count又指定了Reduce,所以key:count   value{1,1,1.....}在最后一个文                                                                件,key:w_id   value:{1,1,1}在前三个文件

第二个MapReduce:   从第一个MapReduce输出的结果中读取,作为本次的输入

第二个MapReduce最终运行的结果:

1. 得到每一个词在数据集中多少条微博中出现过,即DF值

 

Mapper端:key:LongWritable(偏移量)   value:今天_3823890314914825   2

步骤一:获取当前mapper task的数据片段(split),根据FlieSplit的所属文件名进行判断,保证不是最后一个文 件(因为最后一个文件的内容是count 1075

步骤二:这时mapper端输入的value值是今天_3823890314914825   2

对数据处理,按照“\t”切割,再按照“_”切割,输出context.write(今天,1)//注意这里将要统计的是包含今天的文件总数,所以不关注微博id

 

Reducer端:key:w  value:{1,1,1}     数据样例:key=今天,value={1,1,1,1,1}  //每一个1表示数据集中有一条微博包含今天这个词

步骤一:将经过shuffle过程后的数据,进行整合(key相同的值为一组,对迭代器中的值进行遍历)

步骤二:将reduce后的结果进行写出,context.write(key, new IntWritable(sum))

   

经过第二个MapReduce操作后,就获得了每一个词的df(document frequency)值   

                                   

第三个MapReduce:   目的-->计算TF*IDF值

第三个MapReduce最终运行的结果:

1. 得到每一条微博中,每个词的TF-IDF值

结果样例:{3823890314914825 今天:2.78834   逛街:3.98071   姐妹:1.98712}

技巧:

第一个MapReduce输出的第四个文件(count  1075),计算每一个单词的TF-IDF值都需要用到,所以将这个文件在job运  时加载到内存中以提高运行效率

第二个MapReduce输出的文件-->每一个单词在数据集中多少条微博出现过,即df值(今天  5),因为它里面包括常用的词  汇,不同于数据集,并不是很大也可以加载到内存,提高程序的执行效率

    1. // 把微博总数加载到内存
  1. job.addCacheFile(newPath("/user/tfidf/output/weibo1/part-r-00003")
  2. .toUri());
  3. // 把df加载到内存
  4. job.addCacheFile(newPath("/user/tfidf/output/weibo2/part-r-00000")
  5. .toUri());

 

Mapper端:key:LongWritable(偏移量)   value:今天_3823890314914825   2

步骤一:在正式执行map方法之前先执行setup(Context context)方法

目的:将加载到内存中的微博总数,以及DF值,封装到Map对象中(cmap,df),便于map的操作

步骤二:开始执行map操作,因为mapper端的输入是第一次MapReduce的输出,所以还需要进行判断,是否   是最后一个文件(count,1075)

对数据处理,按照“\t”切割,得到tf值-->v[1]=2,同时将v[0]按照“_”切割,得到单词(今  天)和微博id(3823890314914825)

从cmap中获取“count”,从df中获取该单词的df值,在根据该单词的tf值,计算该单词的TF*IDF值

double s = tf * Math.log(cmap.get("count") / df.get(w));

步骤三:将数据输出,key=微博的id,value=(w:tf*idf值)

 

Reducer端:key=微博的id, value=(w:tf*idf值)

数据样例:key=3823890314914825,value={今天:2.89101, 逛街:3.08092}

步骤一:将经过shuffle过程后的数据,进行整合(key相同的值为一组,对迭代器中的值进行遍历,定义StringBuffer,对迭代器中每一个单词以及对应的TF*IDF值拼接

步骤二:将reduce后的结果进行写出,context.write(key, new Text(sb.toString()))

 

4.    商家如何做到精准营销?

经过以上过程,我们拿到的最终数据是3823890314914825  {今天:2.89101, 逛街:3.08092},即每一条微博中每个词的TF*IDF值

比如韩国料理要推送大骨汤,这时候只需要对数据集中的每一条微博中的每一个词对应的TFIDF值做一个降序,然后取前3位,

对整个数据集中的数据遍历,凡是TF*IDF值前三位包含大骨汤的,就是商家要推送的对象

时间: 2024-08-02 06:59:45

TF-IDF_MapReduceJava代码实现思路的相关文章

PageRank_网页排名_MapReduceJava代码实现思路

2017年2月15日, 星期三 PageRank 1.    概念 2.    原理 3.    java代码实现思路 1.定义收敛标准 每次算出新的pr-oldpr=差值 ,所有页面的差值累加 ,除以pagecount,得到avg差值 ,如果.小于0.01 2.计算总页面数,并且算出每个页面的初始pr值=1/pagecount 3.     A  0.25 B  D ----- A  0.35 B D--- A  0.29 B D----   数据集: 一个MapReduce(如何做到循环)

ItemCF_基于物品的协同过滤_MapReduceJava代码实现思路

2017年2月19日, 星期日 ItemCF_基于物品的协同过滤 1.    概念 2.    原理 如何给用户推荐? 给用户推荐他没有买过的物品--103 3.    java代码实现思路 数据集: 第一步:构建物品的同现矩阵 第二步:构建用户的得分矩阵 第三步:同现矩阵*评分矩阵 第四步:拿到最终结果,排序,得到给用户的推荐列表 问题一:物品同现矩阵和用户得分矩阵如何构建? 问题二:矩阵相乘如何来做?   六个MapReduce step1_第一个MapReduce: 目的-->去重去除数据

【JS 设计模式 】用组合模式来实现树形导航--代码结构思路分析(一)

树导航效果图: 组合模式的描述: 将对象组合成树形结构以表示"部分-整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性. 我们把部分用Leaf表示, 把整体用Composite表示.组合模式是有一定规律的,在实现树导航的情况下,Composite需要包含一个以上Leaf,也可以包含一个以上Leaf和一个以Composite,为什么说要包含一个以上的,如果Composite不包含任何子child的话那么它就是Leaf,Leaf表示是最后一层结节. 树形导航代码片段:

【JS 设计模式 】用组合模式来实现树形导航--JS代码结构思路分析(二)

[JS 设计模式 ]用组合模式来实现树形导航--代码结构思路分析(一) 根据上一节中的HTML代码结构我们通过JS来渲染HTML代码,我们先提供一下JS的代码片段,这代码代码不是一个完整的代码是经过简化的.通过JS代码来分析如何组装HTML的 Composite类型的代码: function TreeComposite(id, name, total, level, last) { var root = document.createDocumentFragment(); var panel =

写代码的思路之写一个功能的思路

如果让你实现一个功能,你要完成这个功能的一般思路是什么? 我是一位初学者,希望和大家共享下我在书写代码时的思路,希望对大家有帮助. 以下是我实现一个简单‘日历“这一功能的思路: 当我决定要做一个日历的时候,我会先制作一个”日历“模型,即要实现的”日历“的模型(样子),我用控件制作的: 之后我会按照”日历“模型上面的控件从上到下,从左到右依次声明,但先不实现: 之后一个控件一个控件实现,在设计控件的属性的时候是严格按照之前”日历“模型的属性,这会提高效率: 一个控件实现了之后要做一次测试,保证该控

(如数据结构算法题)编程不是难在处理问题的思路,而在用代码将思路描述出来。

初学编程总觉得好简单,不就是加减乘除,或者什么,思路太简单了,就这样这样做就可以了,代码就不用写了,反正这么简单. 其实难就难在,如何用代码这种语言将你的思路书写下来. 写代码会受到很多的限制,你想要这样干,但你要如何让机器这样干. 编程所要做的唯一一件事就是:拆分. 拆分一整个件事成为一个个步骤---->流程图. 拆分流程图中每一个步骤成为更详细的.具体的----->一条条代码. 所以流程图是人脑中的大逻辑框架,不画出这个大框架,则会在更细节的代码中迷失. 由于拆分出来的一个个细节步骤(每条

KMP代码及思路解析

首先推荐这篇KMP思想的介绍:字符串匹配的KMP算法 KMP代码的关键是: 1.得到搜索串每个字符的匹配值 2.当字符匹配失败时的转移 (搜索串指搜索目标串.) 1: 第一个循环:遍历每个字符,表示搜索的是 该字符及之前所有字符组成的串. 第二个循环:遍历所有长度的子串. 第三个循环:比较子串是否相同. 搜索的目标是:所有相同的子串中最长字串的长度.所以维护一个maxl变量. (在此"子串"指前缀和后缀.) (代码中未清零model数组.) 2: 匹配失败时的转移就很简单了. 若当前字

AI核心代码解题思路

输入的是字符串,故考虑使用string类的对象或者char型数组来接收输入. 首先是主函数: int main() { string s; int n, i; cin >> n; getchar(); //吸收回车符 for(i=1; i<=n; ++i){ getline(cin, s); cout << s << endl; cout << "AI: "; go(s);//AI根据s输出对话 } return 0; } 然后是g

web MVC程序开发增删改查参考代码。思路是面向对象思想,以及在HTML代码中嵌入C#代码

第一步:在Model中写好查询,删除,修改,添加方法,用sql_link类 using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MvcApplication2.Models { public class InfoBf { private MydbDataContext _Context = new MydbDataContext(); //查询 public