用Map/Reduce来做好友推荐

本文介绍了一种基于社交网络的好友推荐算法实现方法,利用Map/Reduce进行两轮计算,第一轮计算每对距离为2的用户之间的通路数量,第二轮则根据通路数量找出每个用户的十大推荐好友。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SNS网站都有一个功能,就是好友推荐(或者Follower推荐)。例如,在人人网上出现的“你可能认识的人”。怎么来实现呢,有一个很简单的办法。如果小刚和小明不是好友,但是他们有很多的共同好友。那么可以认为,A和B很可能相识。

从图论的讲法上看,就是先列出一个人(记为小A)的所有朋友的朋友,在寻找小A和这些人之间有多少长度为2的通路。将这些通路数排序,寻找最高的那几个就可以了。

所以我们的Map/Reduce的任务就是:找出所有人的十个Top“推荐好友”。

社会化网络的图一般都很简单。我们假设输入是按name排序的。

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

我们使用两轮Map/Reduce任务来完成这个操作。

第一轮MR任务

这个任务的目的是计算每一对距离是2的人之间的通路数。

  • 在Map函数中,我们先将每对朋友做一个笛卡尔乘积,说的不大清楚,举个例子,比如
    1. "ricky" => ["jay", "john", "mitch"]

    那么结果就是

    1.  ["jay", "john"], ["jay", "mitch"], ["john", "mitch"]

    他们都是通过ricky牵线搭桥认识的。将已经是朋友的组合筛选掉,再排好序。传给Reducer。

  • 在Reduce函数中, 相同的组合必定会传给Reducer。所以Reducer只要数好有几个相同的组合传给他就行了.
Input record … person -> connection_list
  1. e.g. "ricky" => ["jay", "john", "mitch", "peter"]
  2. also the connection list is sorted by alphabetical order
  3.  
  4. def map(person, connection_list)
  5.   # Compute a cartesian product using nested loops
  6.   for each friend1 in connection_list
  7.      # Eliminate all 2-degree pairs if they already
  8.      # have a one-degree connection
  9.      emit([person, friend1, 0])
  10.      for each friend2 > friend1 in connection_list
  11.          emit([friend1, friend2, 1],  1)
  12.  
  13. def partition(key)
  14.   #use the first two elements of the key to choose a reducer
  15.   return super.partition([key[0], key[1]])
  16.  
  17. def reduce(person_pair, frequency_list)
  18.   # Check if this is a new pair
  19.   if @current_pair != [person_pair[0], person_pair[1]]
  20.       @current_pair = [person_pair[0], person_pair[1]]
  21.       # Skip all subsequent pairs if these two person
  22.       # already know each other
  23.       @skip = true if person_pair[2] == 0
  24.  
  25.   if !skip
  26.       path_count = 0
  27.       for each count in frequency_list
  28.           path_count += count
  29.       emit(person_pair, path_count)
  30.  
  31. Output record person_pair => path_count
  32. e.g. ["jay", "john"] => 5

第二轮MR任务

这一轮的MR任务是为了列出每个人距离为2的好友,查出他们直接究竟有几条路径。

  • 在Map函数中,我们将每一组数据重新排列,保证一个人信息落在一个reducer上
  • 在Reduce函数中,只要将每个人的可能好友之间的路径数排个序就可以了.
Input record = Output record of round 1
  1.  
  2. def map(person_pair, path_count)
  3.   emit([person_pair[0], path_count], person_pair[1])
  4.  
  5. def partition(key)
  6.   #use the first element of the key to choose a reducer
  7.   return super.partition(key[0])
  8.  
  9. def reduce(connection_count_pair, candidate_list)
  10.   # Check if this is a new person
  11.   if @current_person != connection_count_pair[0]
  12.       emit(@current_person, @top_ten)
  13.       @top_ten = []
  14.       @current_person = connection_count_pair[0]
  15.  
  16.   #Pick the top ten candidates to connect with
  17.   if @top_ten.size < 10
  18.       for each candidate in candidate_list
  19.           @top_ten.append([candidate, connection_count_pair[1]])
  20.           break if @pick_count > 10
  21.  
  22. Output record person -> candidate_count_list
  23.  
  24. e.g.  "ricky" => [["jay", 5],  ["peter", 3] ]

Follower推荐
如果我想要做Follower推荐而不是好友推荐怎么办呢?
很简单。只要将第一步的MR任务改为求“Follow关系”和“Followed”关系的笛卡尔乘积就可以了。这里就不列伪码了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值