ItemCF_基於物品的協同過濾_MapReduceJava代碼實現思路


 


ItemCF_基於物品的協同過濾

1.    概念

2.    原理

如何給用戶推薦?
給用戶推薦他沒有買過的物品--103

3.    java代碼實現思路

數據集:
第一步:構建物品的同現矩陣
第二步:構建用戶的得分矩陣
第三步:同現矩陣*評分矩陣
第四步:拿到最終結果,排序,得到給用戶的推薦列表
 
問題一:物品同現矩陣和用戶得分矩陣如何構建?
問題二:矩陣相乘如何來做?
 

六個MapReduce

step1_第一個MapReduce:   目的-->去重去除數據集中重復的數據
     第一個MapReduce最終運行的結果:

  
   Mapper端: key:LongWritable(偏移量)     value:一行數據
                                  步驟一: context.write(value, NullWritable.get());    
                                         
   Reducer 端:key:一行數據    value:NullWritable
                                  步驟一: context.write(key, NullWritable.get());
                                    
step2_第二個MapReduce: 目的-->按用戶分組,計算所有物品出現的組合列表,得到用戶對物品的喜愛度得分矩陣
   第二個MapReduce最終運行的結果:
 
                     
    Mapper端: key:LongWritable(偏移量)     value: i1,u2723,click,2014/9/14 9:31 ||  i1,u2723,pay,2014/9/14 9:31
                                  步驟一:按照“,”切割, 得到item(i1), user(u2723), action(click)
                                  步驟二:構建輸出的key和value( key:user, value:item:物品的得分【根據用戶action得到】
                                   步驟三:輸出key,value
 
     Reducer 端:key:user(u2723)     value:{i1:1, i1:2, i3:2}
                                  步驟一:遍歷 {i1:1, i1:2, i3:2}對於迭代器中的每一個Text(i1:1),按照“:”切割,分別得到item(i1)action(1)對同一物品的action進行累加,將結果存儲到map對象中(map.put(item, action))
                                  步驟二:構建StringBuffer, key:user(u2723),value:{i1:3, i2:4, i3:5}, 並輸出
                                          
step3_第三個MapReduce: 目的-->對物品組合列表進行計數,建立物品的同現矩陣
   第三個MapReduce最終運行的結果:
                                   
 
    Mapper端: key:LongWritable(偏移量)     value: u26    i276:1,i201:1,i348:1,i321:1,i136:1,
                                  步驟一:切割"\t",得到tokens[1]
                                  步驟二: 雙重for循環,得到每一個物品和其他物品的同現的次數
                                   步驟三:輸出,(key=itemA:itemB,value=1) 這里只是得到了單用戶的物品同現,在Reducer端得到的是所有用戶--同一物品對其他物品的同現次數
 
    Reducer 端:第一種--key:itemA:itemB     value:{1,1,1}
                                  步驟一:對Iterable<IntWritable>遍歷,統計sum, 得到itemA:itemB同現的次數
 
step4_第四個MapReduce: 目的-->把物品同現矩陣和用戶得分矩陣相乘
   第四個MapReduce最終運行的結果:
                            
 
    Mapper端: key:LongWritable(偏移量)     value:  u14    i25:1,i223:1 ||   i100:i105    1
                                  步驟一:因為Mapper讀取了第二次輸出(用戶得分矩陣)和第三次輸出的結果(物品同現矩陣), 所以要對maptask所對應的split進行判斷,判讀所讀的數據集屬於哪一個,這里采用了重寫了setup(Context context)方法,定義了flag來進行標識                                   
                                             步驟二:
                                                              如果為同現矩陣(step3) // 樣本:  i100:i181    1
                                                         key:i100    value:A:i181,1  輸出
                                                                  如果為得分矩陣(step2) // 樣本:  u24  i64:1,i218:1,i100:2,
                                                         遍歷得分矩陣-- key:i100    value:B:u24,2,  輸出
 
   Reducer 端: key:i100     value: { A:i181,1,  A:i180,1  A:i167,3}   ||   { B:u24,2,B:u25,3, B:u26,3}

                                  步驟一:因為value中的A:B:標識同現矩陣,得分矩陣
                                                val.startWith("A:")
                                                   某一個物品 i100,針對它和其他物品的同現次數,存在mapA--> value: { A:i181,1,  A:i180,1  A:i167,3}                                                                      mapA.put(i181,1),map.put(i180,1)...       
                                                                val.startWith("B:")
                                                    該物品(key中的itemID), 所有用戶的推薦權重分數 mapB-- { B:u24,2,B:u25,3, B:u26,3}
                                                     mapB.put(u24,2),mapB.put(u25,3)...
                                             步驟二:進行矩陣相乘運算,對於物品i100,它的同現商品以及對應的次數存放到了mapA,而物品對於i100,所有用戶的評分已經存放到了mapB,只需要遍歷mapA,將其中同現的每一個商品乘以對應的mapB中每一個用戶對i100的評分
                                  步驟三:輸出, key=userId, value=itemId,result (u24    i101,8.0 )
                                                
                                                             
step5_第五個MapReduce:目的-->把相乘后的矩陣相加,獲得結果矩陣  
   第五個MapReduce最終運行的結果:
                  
 
     Mapper端: key:LongWritable(偏移量)     value:u13    i9,5.0
                                         步驟一:key=u13,value=i9,5.0  輸出
 
    Reducer端:key:u13    value:{i101,2.0, i103,4.5, i101, 5.7}
                                  步驟一:利用map對同一itemId矩陣求和  
                                   步驟二:輸出,key=userId, value=itemId,score( 樣本:  u13    i9,5.0)
                       
step6_第六個MapReduce: 目的-->按照推薦得分降序排序,取前十條(二次排序)
   第六個MapReduce最終運行的結果:
                               
 
    Mapper端: key:LongWritable(偏移量)     value: u13    i9,5.0
                                  步驟一:將用戶id,物品和得分封裝到一個對象 PairWritable
                                  步驟二:輸出,key:( PairWritable) value:(item:num)
 
    Shuffle中Sort:
                                  注意:
                                  重寫compare()方法,先比較Uid,相等的話,再比較Num

   Shuffle中Group:
                                   注意:
                                   重寫compare()方法,Uid相同的為一組
 
   Reducer key:   PairWritable    value:Text{i160:58.0,i352:9.0,i192:8.0,i455:7.0...}
                                   步驟一:取前十個,利用StringBuffer拼接
                                   步驟二:輸出,key=uid,value=sb.toString()
                     

 
 
 
 
 
 
 
 
 

 
 
 
 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM