使用mahout mapreduce计算用户相似度

fruv7luv  于 2021-06-03  发布在  Hadoop
关注(0)|答案(1)|浏览(408)

我使用mahout集群,我有大型集群,每个集群有大约10万个用户,每个用户有5个特性。在下一步中,我需要计算pearson相关性来发现集群用户之间的相似性。
目前我有一个python脚本,对我来说也是这样,但正如预期的那样,它需要很长的时间来进行计算,不再是一个可行的选择
我查看了mahout,因为它提供了使用pearson、tanimoto、loglikelyhood度量来查找用户相似性的功能,但我找不到开发这些相似性度量的mapreduce版本的方法。
有没有资源可以举一个例子,向我解释如何开发usersimilarity的mapreduce版本,或者使用hadoop流媒体和相同的java类是否有意义。
编辑
即使集群中有100k个用户,我也很少需要计算100k100k矩阵。大多数情况下,它将是一个10k100k矩阵。然而,我有大约500个这样的集群,所以计算500个10k*100k的集群所花费的时间相当长,这就是我寻找更好的方法并引发讨论的原因

w6lpcovy

w6lpcovy1#

mapreduce的局限性

成对用户相似性在mapreduce中是不可定义的。
如果你还记得什么 map 它读取一个键值对。它不是读取两个键值对。
根据定义 map ,则无法计算成对比较。
如果您意识到map和reduce是线性过程,那么这一点应该很明显。两两相似性是一个二次任务。它不能工作。
也就是说,除非你滥用mapreduce。您可以将数据空间分解为二次大小。如果首先生成所有n*n对,则可以再次使用mapreduce处理这些对。但这是一个坏的滥用它(尽管有些人似乎确实这样做)。

替代(滥用)mapreduce

首先,有时候你可以把问题改写成线性的,比如说,把数据倒过来。或者做一些巧妙的修剪,使它在实际中是二次的,而在实际数据中它通常保持线性(因为在生成过程中或生成之前,可以删除很多理论上的二次数据)。
第二,注意mahout构建在hadoop平台上,但并不能用mapreduce解决所有问题。很多hadoop的功能不仅仅是“map+reduce”。例如terasort—因为排序不是一个线性问题(它还涉及比较元素!),mapreduce无法解决这个问题。但是您可以将hadoop用于terasort,方法是编写一个分布式排序,它使用一个广义的中位数方法来估计分位数,根据这些分位数分布数据,然后对各个桶进行排序(在 O(n log n) )在各个节点上。复杂性仍然是超线性的,但是运行时间比单个节点上的运行时间要低得多。
我很确定hadoop除了mapreduce之外,还提供了一些选项。你可能想更仔细地看看mahout是如何解决这些非线性问题的。它并没有试图或假装缩小所有的Map。还有apachehama,它也超越了mapreduce,使用了一种称为“批量同步处理”的泛化方法。hadoop(和yarn)通常允许这样的事情。但是这个api显然比经典的mapper和reducer api困难得多。

对mapreduce的天真滥用

或者你去虐待的方式(这可能不是mahout做的)。这实际上是相当简单的滥用Map减少。因为输出大小没有限制。因此,如果您不关心内存,可以执行以下操作:
假设你知道所有的钥匙,例如,因为它们的编号从1到n。那你可以用

map(K, V) -> [ (1, (K, V)), (2, (K, V)),  (3, (K, V)), ..., (n, (K, V)) ]

(这显然创建了一个二次大小的数据集!)在reducer中,每个键现在都有一个完整的数据集副本和一个需要关注的id。
因此,对于每个对象,约简器再次读取完整的数据集,计算n个相似性,并输出它们。
砰,你把问题缩小了。这是愚蠢和低效的,但它的工作和它正在做。

利用辅助数据进行更聪明的滥用

更智能的版本将直接将数据集作为所谓的“辅助数据”加载到系统中。所以它是这样的:

map (K,V) -> [ (K_1, sim(V, aux_obj1)), (K_2, sim(V, aux_obj2)),
             (K_3, sim(V, aux_obj3)), ... (K_n, sim(V, aux_objn)) ]

这并不像mapreduce的滥用那样糟糕(它只是二次结果矩阵并行计算的标准方式),因为它至少诚实地说明了它的作用:使用大量辅助数据。它也会工作-只要辅助数据适合你的工人记忆。而且它不再是一个合适的mapreduce,因为它使用辅助数据,而这些数据实际上不能被看作是函数的参数化。
考虑到显然可以将数据加载到内存中(甚至在python中),最后一个选项可能是最简单的方法。您甚至可以将辅助内存分成块,并将数据库的这些部分作为单独的作业进行计算。
不过,它不是mapreduce。这是一个二次问题,从定义上讲,它不是mapreduce。这些问题可以在hadoop上解决(参见mahout),但是您需要的不仅仅是mapreduce。

对你实际任务的最后一句话

首先,请分享更多你真正打算做的事情。变快的关键是少做。如果你能节省计算,你总是更快。
10万用户和5个属性(双值?)并不多。所以也许你的python实现效率太低了。经过编译和优化的语言可能会使您的速度提高1-2个数量级。我在10分钟内用8个属性对110k个对象进行了两两相似;所以你的问题也应该在这个时候解决。10万用户和5个属性还不是真正的“hadoop大小的大数据”。与快速的低层实现相比,hadoop开销可能会比实际花费更多。
优化皮尔逊相关性:这里可以做几件事。注意你是如何重新计算标准差的?如果您对数据进行预处理,并将每个记录标准化为平均值0和标准偏差1,皮尔逊相关性将简化为协方差(因为stddev为1)。因为平均值是0,协方差变为 E(x*y) = 1/5 \sum x_i * y_i . 如果您感兴趣(例如仅对前10个相似对象感兴趣),可以使用空间索引来加速此功能。我想你可以很容易地把它添加到elki中并使用那里的空间索引结构。这通常会减少运行时间的另一个数量级,这意味着在单个cpu上,处理时间应该是1分钟。

相关问题