火花中的嵌套循环(Scoring Matrix Factorisation),如何高效地完成?

时间:2017-09-15 20:29:38

标签: scala apache-spark dataframe

我一直在尝试为spark中的某些选定用户生成推荐内容。这是通过使用每个乘积因子(n个浮点数的向量)生成用户因子(n个浮点数的向量),然后按顺序排序来完成的。

所以,假设我的客户因素为(customerId, Array[Float]),我的产品系数为(productId, Array[Float])。我必须为每个客户创建每个产品的分数,并生成(customerId, productId, score),其中保留每个客户的前N个结果。所以我这样做:

val customers = ... // (customerId, Array[Float])
val products = ... // (productId, Array[Float])
val combination = customers.cartesian(products)
val result = combination.map(x => (combination._1._1, combination._2._1, 
    dotProd(combination._1._2, combination._2._2))

... then filter top N for each customer using dataframe

但这需要很长时间,其中一个原因是笛卡尔结果使数据量变得庞大,为每个客户重复相同的产品因素。

spark

正如您可以看到这100 TB客户和300K产品的11 TB数据。这是创建的DAG(我选择并保留分数的前N个,因此分区):

enter image description here

你会建议什么?如何改进流程来绕过巨大的IO?

由于

更新

最后,在48个核心上运行它需要10个小时。 并拥有80TB的IO! enter image description here

更新2

我怀疑解决方案是收集然后广播两个RDD并仅在ID上创建笛卡尔,然后查找因子。这将大大减少IO。

我会试一试。

1 个答案:

答案 0 :(得分:0)

[注意: 我不会接受我自己的答案,因为这只是一项改进,并没有实质上更好]

正如我所描述的那样,我广播了客户和产品因素,并将流程加快了近3倍,并将IO降低到2.4TB。

可能会有更多改进的方法,但我想现在还可以。

enter image description here