我有用户购买产品的数据。我想创建一个大小为 |users|
十 |products|
使元素 (i,j)
在矩阵中是1 user_i
已购买 product_j
,否则该值为0。
现在,我的数据看起来像
userA, productX
userB, productY
userA, productZ
...
userid和productid都是字符串。我的问题是,如何将这些idMap到矩阵中的行索引(对于用户)和列索引(对于产品)。
有超过一百万个独特的用户ID和大约三百万个产品ID。
使问题明确:给定 user1, product1
像上面的输入一样,如何将其转换为
1,1
2,2
1,3
哪里 userA
Map到矩阵的第0行, userB
Map到第1行, productX
Map到列0,依此类推。
考虑到数据的大小,我不得不使用hadoop map reduce,但无法想出一种简单有效的方法来实现这一点。
如果我们能做到以下几点,就可以解决这个问题:
转储唯一用户ID。
转储唯一的ProductID。
将(1)中的每个唯一用户标识Map到行索引。
将(2)中每个唯一的productidMap到列索引。
我可以很容易地做(1)和(2),但很难想出一个有效的方法来解决(3)(4将解决,如果我们解决3)。
我有一些解决方案,但它们不是万无一失的。
上述步骤3的解决方案1(简单)
Map所有用户ID并为所有Map任务发出相同的键(比如“1”)。
有一个 long
中的计数器初始化为0 setup()
减速器总成。
在 reduce()
,将计数器值与输入的userid一起发出,并将计数器递增1。
这将是非常低效的,因为所有1亿个用户id都将由一个reducer处理。
上述步骤3的解决方案2
在Mapuserid时,根据一个键发出每个userid,该键是从1,2,3….n中均匀采样的整数(其中n是可配置的)。n=100(例如)。在某种程度上,我们是在划分输入集。
在mapper中,使用hadoop计数器计算分配给每个随机分区的用户id的数量。
在reducer设置中,首先访问Map阶段中的计数器,以确定为每个分区分配了多少id。使用这些计数器确定 start
以及 end
该分区的值。
对中的每个用户标识进行迭代(计数时) reduce
并将矩阵rowid生成为 start_of_partition
+ counter
.
context.write(用户id,矩阵行id)
这种方法应该有效,但我不知道如何处理reducer任务失败/终止的情况。
我相信应该有一些我不知道的方法。我们可以使用哈希/模来实现这一点吗?我们如何处理大规模的碰撞?
暂无答案!
目前还没有任何答案,快来回答吧!