頂點a、b、c到i分別是社交**的使用者,兩頂點之間的邊表示兩頂點代表的使用者之間相互關注。那麼如何根據使用者之間相互關注所構成的圖,來向每個使用者推薦好友呢?可能大家都聽說過六度人脈的說法,所謂六度人脈是指:地球上所有的人都可以通過五層以內的熟人鏈和任何其他人聯絡起來。通俗地講:「你和任何乙個陌生人之間所間隔的人不會超過六個,也就是說,最多通過六個人你就能夠認識任何乙個陌生人。」其實這個理論在社交網路中同樣成立。
現在我們以上圖為例,介紹下如何利用使用者之間相互關注所構成的圖,來向每個使用者推薦好友。首先我們不得不假設的是如果兩使用者之間相互關注,那麼我們認為他們認識或者說是現實中的好友,至少應該認識。假設我們現在需要向使用者i推薦好友,我們發現使用者i的好友有h、g、c。其中h的好友還有a,g的好友還有f,c的好友還有b、f。那麼使用者i、h、g、c、a、b、f極有可能是同乙個圈子裡的人。我們應該把使用者a、b、f推薦給使用者i認識。進一步的想,使用者f跟兩位i的好友c、g是好友,而使用者a、b都分別只跟一位i的好友是好友,那麼相對於a、b來說,f當然更應該推薦給使用者i認識。
可能你會發現,在上面的分析中,我們使用了使用者i的二度人脈作為他的推薦好友,而且我們對使用者i的每個二度人脈進行了投票處理,選舉出最優推薦。其實,我覺得,二度人脈的結果只能看看某個使用者的在社交**上的人際關係鏈,而基於投票選舉產生的二度人脈才是好友推薦功能中所需要的好友。
我們可以依據上圖生成原始資料:
a,b
a,hb,c
c,ic,d
c,fd,f
d,ee,f
f,gg,i
g,hh,i
每行有兩個使用者id,以逗號分割,表示這兩個使用者之間相互關注即認識,把資料儲存到degfriend.txt中。
二度好友的計算需要兩輪的mapreduce。第一輪mapreduce的map中,例如輸入是「h,i」,我們的輸出是key=h,value=「h,i」跟key=i,value=「h,i」兩條結果。前者表示i可以通過h去發現他的二度好友,後者表示h可以通過i去發現他的二度好友。
根據第一輪mapreduce的map,第一輪mapreduce的reduce 的輸入是例如key =i,value= 。其實reduce 的輸入是所有與key代表的結點相互關注的人。如果h、c、g是與i相互關注的好友,那麼h、c、g就可能是二度好友的關係,如果他們之間不是相互關注的。對應最上面的圖,h與c是二度好友,g與c是二度好友,但g與c不是二度好友,因為他們是相互關注的。第一輪mapreduce的reduce的處理就是把相互關注的好友對標記為一度好友(「deg1friend」)並輸出,把有可能是二度好友的好友對標記為二度好友(「deg2friend」)並輸出。
第二輪mapreduce則需要根據第一輪mapreduce的輸出,即每個好友對之間是否是一度好友(「deg1friend」),是否有可能是二度好友(「deg2friend」)的關係,確認他們之間是不是真正的二度好友關係。如果他們有deg1friend的標籤,那麼不可能是二度好友的關係;如果有deg2friend的標籤、沒有deg1friend的標籤,那麼他們就是二度好友的關係。另外,特別可以利用的是,某好友對deg2friend標籤的個數就是他們成為二度好友的支援數,即他們之間可以通過多少個都相互關注的好友認識。
兩輪mapreduce的**如下:
import sys
for line in sys.stdin:
line = line.strip()
eachterm = line.split(',')
if eachterm[0] < eachterm[1]:
value = eachterm[0] + '-' + eachterm[1]
elif eachterm[0] > eachterm[1]:
value = eachterm[1] + '-' + eachterm[0]
print '%s\t%s\n%s\t%s'%(eachterm[0], value, eachterm[1], value)
reducer_friend1.py
from operator import itemgetter
import sys
list_relation = {}
for line in sys.stdin:
line = line.strip()
key, value = line.split('\t')
try:
list_relation[key] = list_relation.get(key, '') + '|' + value
except valueerror:
pass
sorted_list_relation = sorted(list_relation.items(),key=itemgetter(0))
for key, value in sorted_list_relation:
values = value[1:].split('|')
hisfriends =
for value in values:
eachterm = value.split('-')
print "%s\t%s" % (value,'deg1friend')
if eachterm[0]== key:
elif eachterm[1] == key:
for element1 in hisfriends:
for element2 in hisfriends:
if element1 < element2:
print "%s-%s\t%s"%(element1,element2,'deg2friend')
import sys
def1friend =
def2friend =
for line in sys.stdin:
line = line.strip()
eachterm = line.split('\t')
if eachterm[1] == 'deg1friend':
if def1friend.count(eachterm[0]) == 0:
elif eachterm[1] == 'deg2friend':
if def2friend.count(eachterm[0]) == 0:
for element in def2friend:
if def1friend.count(element) == 0:
print element
reducer_friend1to2.py
from operator import itemgetter
import sys
list_friend = {}
for line in sys.stdin:
line = line.strip()
base, friend = line.split('-')
try:
list_friend[base] = list_friend.get(base, '') + '|' + friend
list_friend[friend] = list_friend.get(friend,'') + '|' + base
except valueerror:
pass
sorted_list_friend = sorted(list_friend.items(),key=itemgetter(0))
for base, friends in sorted_list_friend:
print "%s\t%s" % (base, friends[1:])
執行結果:
a c|g|i
b h|i|d|f
c a|e|g|h
d b|i|g
e c|g
f b|i|h
g c|d|e|a
h b|f|c
i b|d|f|a
Hadoop例項 二度人脈與好友推薦
其實,社交 上的各個使用者以及使用者之間的相互關注可以抽象為乙個圖。以下圖為例 頂點a b c到i分別是社交 的使用者,兩頂點之間的邊表示兩頂點代表的使用者之間相互關注。那麼如何根據使用者之間相互關注所構成的圖,來向每個使用者推薦好友呢?可能大家都聽說過六度人脈的說法,所謂六度人脈是指 地球上所有的...
Hadoop例項 二度人脈與好友推薦
頂點a b c到i分別是社交 的使用者,兩頂點之間的邊表示兩頂點代表的使用者之間相互關注。那麼如何根據使用者之間相互關注所構成的圖,來向每個使用者推薦好友呢?可能大家都聽說過六度人脈的說法,所謂六度人脈是指 地球上所有的人都可以通過五層以內的熟人鏈和任何其他人聯絡起來。通俗地講 你和任何乙個陌生人之...
依據二度人脈推薦好友sql
friend表結構 drop table if exists friend create table friend uid bigint not null comment 使用者標識 friend uid bigint not null comment 申 為好友的使用者標識 sys create ...