TF-IDF_MapReduceJava代碼實現思路。本站提示廣大學習愛好者:(TF-IDF_MapReduceJava代碼實現思路)文章只能為提供參考,不一定能成為您想要的結果。以下是TF-IDF_MapReduceJava代碼實現思路正文
2017年2月16日, 星期四
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),因為它裡面包括常用的詞 匯,不同於數據集,並不是很大也可以加載到內存,提高程序的執行效率
// 把微博總數加載到內存
job.addCacheFile(newPath("/user/tfidf/output/weibo1/part-r-00003")
.toUri());
// 把df加載到內存
job.addCacheFile(newPath("/user/tfidf/output/weibo2/part-r-00000")
.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值前三位包含大骨湯的,就是商家要推送的對象