使用mapreduce查找用户之间的公共项

使用mapreduce查找用户之间的公共项,mapreduce,Mapreduce,假设我有以下用户/项目集,其中项目也可以为每个用户复制(如user1) 我想找到一个map reduce算法,它可以计算每对用户之间的公共项的数量,就像这样 { "u1_u2", "common_items" : 1 } { "u1_u3", "common_items" : 2 } { "u2_u3", "common_items" : 2 } 它基本上为每对找到项目集的交点,并将复制视为新项目。我是mapreduce的新手,我如何才能为此执行mapreduce?这对您有用吗 from i

假设我有以下用户/项目集,其中项目也可以为每个用户复制(如user1)

我想找到一个map reduce算法,它可以计算每对用户之间的公共项的数量,就像这样

{ "u1_u2", "common_items" : 1 }
{ "u1_u3", "common_items" : 2  }
{ "u2_u3", "common_items" : 2 }

它基本上为每对找到项目集的交点,并将复制视为新项目。我是mapreduce的新手,我如何才能为此执行mapreduce?

这对您有用吗

from itertools import combinations

user_sets = [
    { 'u1': [ 'a', 'a', 'c', 'h' ] },
    { 'u2': [ 'b', 'a', 'f' ] },
    { 'u3': [ 'a', 'a', 'f' ] },
]

def compare_sets(set1, set2):
    sum = 0
    for n, item in enumerate(set1):
        if item in set2:
            sum += 1
            del set2[set2.index(item)]
    return sum

for set in combinations(user_sets, 2): 
    comp1, comp2 = set[0], set[1]
    print 'Common items bwteen %s and %s: %s' % (
        comp1.keys()[0], comp2.keys()[0], 
        compare_sets(comp1.values()[0], comp2.values()[0])
    )
以下是输出:

Common items bwteen u1 and u2: 1 Common items bwteen u1 and u3: 2 Common items bwteen u2 and u3: 1 u1和u2的共同项目:1 u1和u3的共同项目:2 u2和u3的共同项目:1
您希望一个步骤能够发出用户拥有的所有信息,例如:

{ 'a': "u1" }
{ 'a': "u1" }
{ 'c': "u1" }
{ 'h': "u1" }
{ 'b': "u2" }
{ 'a': "u2" }
{ 'f': "u2" }
{ 'a': "u1" }
{ 'a': "u3" }
{ 'f': "u3" }
然后按如下键减少它们:

{ 'a': ["u1", "u1", "u2", "u3"] }
{ 'b': ["u2"] }
{ 'c': ["u1"] }
{ 'f': ["u2", "u3"] }
{ 'h': ["u1"] }
在这种情况下,reducer在每个值中发出每个用户的排列,如:

{ 'u1_u2': 'a' }
{ 'u2_u3': 'a' }
{ 'u1_u3': 'a' }
{ 'u2_u3': 'f' }
请注意,您需要确保在像
k1_k2
这样的键中
k1
,以便它们在任何进一步的mapreduce步骤中匹配

然后,如果您需要像您的示例一样对它们进行分组,则需要另一个mapreduce阶段按键组合它们,它们最终将如下所示:

{ 'u1_u2': ['a'] }
{ 'u1_u3': ['a'] }
{ 'u2_u3': ['a', 'f'] }
{ 'u2_u3': ['f'] }

对于这些类型的问题,您需要了解一些算法比其他算法的伸缩性更好,任何一种算法的性能都取决于数据的“形状”和大小

将每个用户的项目集与每个其他用户的项目集进行比较可能适用于小型域数据集(比如1000个或用户,甚至10000个,项目数量相似),但这是一个“n平方”问题(或者大约一个数量级,至少可以说我的大O生锈了!):

因此,100000个用户域将产生4999950000个集合比较

解决此问题的另一种方法是反向关系,因此运行Map Reduce作业以生成项目到用户的映射:

'a' : [ 'u1', 'u2', 'u3' ],
'b' : [ 'u2' ],
'c' : [ 'u1' ],
'f' : [ 'u2', 'u3' ],
'h' : [ 'u1' ],
从那里,您可以迭代每个项目的用户并输出用户对(计数为1):

然后最终为每个用户配对生成总和:

[ 'u1_u2' : 1, 'u1_u3' : 1, 'u2_u3' : 2 ]
这不会产生您感兴趣的行为(u1和u3项目集中的双a),但会详细说明初始实现

如果您知道域集中的用户通常没有共同的项,每个用户有少量的项,或者一个具有大量不同值的项域,那么此算法将更加有效(以前您将每个用户与另一个用户进行比较,两个集之间的交集概率较低)。我相信数学家可以为你证明这一点,但我不是


这也和以前一样存在潜在的扩展问题——如果你有一个100000个用户都有共同点的项目,你仍然需要生成40亿个用户对。这就是为什么在盲目地对数据应用算法之前了解数据很重要的原因。

谢谢,但这不是map reduce。这是计算两个集合之间公共元素数量的例行程序。我正在寻找解决此问题的map reduce方法抱歉,我以前从未听说过
map reduce
'a' : [ 'u1', 'u2', 'u3' ],
'b' : [ 'u2' ],
'c' : [ 'u1' ],
'f' : [ 'u2', 'u3' ],
'h' : [ 'u1' ],
'a' would produce: [ 'u1_u2' : 1, 'u1_u3' : 1, 'u2_u3' : 1 ]
'f' would produce: [ 'u2_u3' : 1 ]
[ 'u1_u2' : 1, 'u1_u3' : 1, 'u2_u3' : 2 ]