用Map/Reduce來做好友推薦

來源:互聯網
上載者:User

查看原文

Posted by 顏開

SNS網站都有一個功能,就是好友推薦(或者Follower推薦)。例如,在人人網上出現的“你可能認識的人”。怎麼來實現呢,有一個很簡單的辦法。如果小剛和小明不是好友,但是他們有很多的共同好友。那麼可以認為,A和B很可能相識。

從圖論的講法上看,就是先列出一個人(記為小A)的所有朋友的朋友,在尋找小A和這些人之間有多少長度為2的通路。將這些通路數排序,尋找最高的那幾個就可以了。

所以我們的Map/Reduce的任務就是:找出所有人的十個Top“推薦好友”。

社會化網路的圖一般都很簡單。我們假設輸入是按name排序的。

"ricky" => ["jay", "peter", "phyllis"]"peter" => ["dave", "jack", "ricky", "susan"]

我們使用兩輪Map/Reduce任務來完成這個操作。

第一輪MR任務

這個任務的目的是計算每一對距離是2的人之間的通路數。

在Map函數中,我們先將每對朋友做一個笛卡爾乘積,說的不大清楚,舉個例子,比如"ricky" => ["jay", "john", "mitch"]

那麼結果就是

 ["jay", "john"], ["jay", "mitch"], ["john", "mitch"]

他們都是通過ricky牽線搭橋認識的。將已經是朋友的組合篩選掉,再排好序。傳給Reducer。

在Reduce函數中, 相同的組合必定會傳給Reducer。所以Reducer只要數好有幾個相同的組合傳給他就行了.

Input record … person -> connection_liste.g. 

"ricky" => ["jay", "john", "mitch", "peter"]

also the connection list is sorted by alphabetical order 

def map(person, connection_list) 

 # Compute a cartesian product using nested loops  

for each friend1 in connection_list     

# Eliminate all 2-degree pairs if they already     

# have a one-degree connection     

emit([person, friend1, 0]) 
   

for each friend2 > friend1 in connection_list        

 emit([friend1, friend2, 1],  1) def
partition(key)  #use the
first two elements of the key to choose a reducer  return super.partition([key[0], key[1]]) 

 

def reduce(person_pair, frequency_list)  

# Check if this is a new pair  

if @current_pair != [person_pair[0], person_pair[1]] 
  

  @current_pair = [person_pair[0], person_pair[1]] 
    # Skip all subsequent pairs if these two person

      # already know each other     

 @skip = true if person_pair[2] == 0   if !skip 
    

path_count = 0      

for each count in
frequency_list     

    path_count += count 

    emit(person_pair, path_count)

 Output record … person_pair => path_counte.g. ["jay", "john"] => 5

第二輪MR任務

這一輪的MR任務是為了列出每個人距離為2的好友,查出他們直接究竟有幾條路徑。

在Map函數中,我們將每一組資料重新排列,保證一個人資訊落在一個reducer上在Reduce函數中,只要將每個人的可能好友之間的路徑數排個序就可以了.

Input record = Output record of round 1 def map(person_pair, path_count)  

emit([person_pair[0], path_count], person_pair[1]) def
partition(key)  #use the
first element of the key to choose a reducer  return super.partition(key[0]) def
reduce(connection_count_pair, candidate_list)  #
Check if this is a new person  if @current_person != connection_count_pair[0] 
  

  emit(@current_person, @top_ten) 
   

 @top_ten = []      

@current_person = connection_count_pair[0]   #Pick
the top ten candidates to connect with 

 if @top_ten.size < 10 
 

   for each candidate in candidate_list        

  @top_ten.append([candidate, connection_count_pair[1]]) 
      

  break if @pick_count > 10 Output
record … person -> candidate_count_list e.g.  "ricky" => [["jay", 5],  ["peter", 3] …]


這個應用只需要一輪mapreduce就可以完成:
1、在mapper輸出時,設定partitioner為按friend1來分桶,於是同一個friend1的就到一個reducer中了
2、reducer中,對同一個friend1且同friend2的求count,並且儲存到一個top_ten數組,當有新的的count大於top_ten中的最小count時,進行替代。最終得到friend1的top_ten

說明:
1、mapper中可以同時輸出(friend1,friend2),(friend2,friend1)
2、mapper中可以輸出介紹人,在reducer中將每個pair的介紹人求和

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.