根据他们在Spark中的爱好对人们进行分组

时间:2016-09-14 07:51:55

标签: apache-spark pyspark

我正在与PySpark合作,我需要根据他们的兴趣对人进行分组。我们说我有 n 人:

person1, movies, sports, dramas
person2, sports, trekking, reading, sleeping, movies, dramas
person3, movies, trekking
person4, reading, trekking, sports
person5, movies, sports, dramas
.
.
.

现在我想根据他们的兴趣对人进行分组。

  1. 至少 m 共同兴趣的群组人士( m 是用户输入,可能是2,3,4 ......)

    Let's assume m=3  
    Then the groups are:
          (person1, person2, person5)
          (person2, person4)
    
  2. 属于 x 组的用户( x 是用户输入)

    Let's assume x=2
    Then
      person2 is in two groups
    

3 个答案:

答案 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

您在此处看到的是您要查找的结果 - 检查行/列交叉处的值,您将获得共享兴趣的数量。

  • P2与P4共享多少兴趣?答案:3
  • 谁与P1有3个兴趣?答案:P2和P5
  • 谁与P3分享2个利益?答案:P2

有关如何将此想法应用于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部分之前可以计算组合。

例如:

  • 过滤掉hobbies_count&lt; input_number在最开始废弃不需要的记录。
  • 如果爱好的总列表是 {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

  • 生成先前的可能组合
  • 稍后,为每个组合执行过滤并跟踪记录计数。