我正在与PySpark合作,我需要根据他们的兴趣对人进行分组。我们说我有 n 人:
person1, movies, sports, dramas
person2, sports, trekking, reading, sleeping, movies, dramas
person3, movies, trekking
person4, reading, trekking, sports
person5, movies, sports, dramas
.
.
.
现在我想根据他们的兴趣对人进行分组。
至少 m 共同兴趣的群组人士( m 是用户输入,可能是2,3,4 ......)
Let's assume m=3
Then the groups are:
(person1, person2, person5)
(person2, person4)
属于 x 组的用户( x 是用户输入)
Let's assume x=2
Then
person2 is in two groups
答案 0 :(得分:1)
我的回答是代数而不是特定于Spark / Python,但可以在Spark中实现。
我们如何在您的问题中表达数据? 我将使用矩阵 - 每行代表一个人,每列代表兴趣。所以按照你的例子:
movies,sports,trekking,reading,sleeping,dramas
P1: 1 1 0 0 0 1
P2: 1 1 1 1 1 1
P3: 1 0 1 0 0 0
P4: 0 0 1 1 0 1
P5: 1 1 0 0 0 1
如果我们想调查P2和P3的相似性怎么办 - 检查他们分享了多少兴趣 - 我们可以使用以下公式:
(movies)+(sports)+(trekking)+(reading)+(sleeping)+(dramas)
1*1 + 1*0 + 1*1 + 1*0 + 1*0 + 1*0 = 2
您可能看起来很熟悉 - 它看起来像矩阵乘法计算的一部分。
为了充分利用我们观察到的事实,我们必须转置矩阵 - 它看起来像这样:
P1,P2,P3,P4,P5
movies 1 1 1 0 1
sports 1 1 0 0 1
trekking 0 1 1 1 0
reading 0 1 0 1 0
sleeping 0 1 0 0 0
dramas 1 1 0 1 1
现在,如果我们将矩阵(原始矩阵和转置矩阵)相乘,您将得到新的矩阵:
P1 P2 P3 P4 P5
P1 3 3 1 1 3
P2 3 6 2 3 4
P3 1 2 2 1 1
P4 1 3 1 2 1
P5 3 3 1 1 3
您在此处看到的是您要查找的结果 - 检查行/列交叉处的值,您将获得共享兴趣的数量。
有关如何将此想法应用于Apache Spark的一些提示
编辑1:添加更实际的方法(在评论之后)
我们有一个表/ RDD /数据集" UserHobby":
movies,sports,trekking,reading,sleeping,dramas
P1: 1 1 0 0 0 1
P2: 1 1 1 1 1 1
P3: 1 0 1 0 0 0
P4: 0 0 1 1 0 1
P5: 1 1 0 0 0 1
现在要查找与P1共享2个组的所有人,您必须执行:
SELECT * FROM UserHobby
WHERE movies*1 + sports*1 + sports*0 +
trekking*0 + reading*0+ sleeping*0 + dramas*1 = 2
现在您必须为所有用户重复此查询(将0和1更改为实际值)。算法复杂度为O(n ^ 2 * m) - n个用户数,m个爱好数
这种方法的好处在于您不必生成子集。
答案 1 :(得分:0)
如果用户数量很大,则无法考虑采用任何User x User
方法。
步骤0.作为第一步,我们应该忽略不至少拥有m个兴趣的所有用户(因为他们不能与任何人至少有m
个共同兴趣)
步骤1.可能的方法:
i) 蛮力: 如果最大兴趣数量很小,比如10,您可以在HashMap
中生成所有可能的兴趣组合,并为每个人分配一个兴趣组ID。您只需要通过用户的兴趣集一次,就可以找出他们有资格获得哪些兴趣小组。这将一次性解决问题。
ii) 地区敏感哈希 :完成步骤0
后,我们知道我们的用户最少只有m
爱好。如果您对大致的答案感到满意,那么局部敏感的散列可以提供帮助。 How to understand Locality Sensitive Hashing?
<小时/> LSH方法草图:
a)首先将每个爱好映射到一个整数(如果数据集很大,你应该做任何事情)。我们有User -> Set of integers (hobbies)
b)获取每个用户的签名,方法是取最小哈希值(用k
对每个整数进行哈希,然后取最小值。这样就得到了User -> Signature
c)如果您愿意,可以更详细地探索具有相同签名的用户(或者您可以使用大致答案)。
答案 2 :(得分:0)
可能我的答案可能不是最好的,但会做的工作。如果您知道之前的爱好总列表,您可以编写一段代码,在进入spark部分之前可以计算组合。
如果爱好的总列表是 {a,b,c,d,e,f} 且input_number是2,则此情况下的组合列表将是
{(ab)(ac)(ad)(ae)(af)(bc)(bd)(be)(bf)(cd)(ce)(cf)(de)(df)(ef)}
因此需要为input_number