我有一个项目的RDD,以及一个计算两个项目之间距离的函数d: (Item, Item) => Double
。我试图计算从RDD随机抽取的项目之间的平均距离。 RDD相当大(100万),因此计算精确平均值是不可能的。
因此,我想获得一组采样项目的RDD(我将从中计算距离)。例如,我想得到100米对的样本。 鉴于采样对的RDD,我会计算平均值,直方图等,以便了解距离分布。
以下是所有失败的初步尝试:
使用.sample
生成两个RDD,压缩它们并计算项目之间的距离。这失败,因为.zip
要求两个RDD每个分区具有完全相同的项目数。
使用RDD自己的.cartesian
,然后使用.sample
。这会失败(内存不足),因为显然cartesian
并不意味着以这种方式使用。
收集RDD的两个小样本,并.zip
两个数组。这样可以正常工作,但不能扩展。
有什么想法吗?
谢谢!
编辑:这里是如何压缩每个分区具有不同数量项目的两个样本:
val r = ... // RDD[Item]
val s1 = r.sample(true, 0.1, 123)
val s2 = r.sample(true, 0.1, 456)
val zipper = (i1: Iterator[Item], i2: Iterator[Item]) => i1.zip(i2)
val pairs = r1.zipPartitions(r2)(zipper) // zip the RDDs and explicitly define how to zip the partitions
关键是,虽然RDD的.zip方法不接受大小不等的分区,但迭代器的.zip方法会做(并丢弃较长迭代器的剩余部分)。
答案 0 :(得分:1)
回答我自己的问题:
.sliding(2)
获取连续的样本对。代码:
import org.apache.spark.mllib.rdd.RDDFunctions._ // for .sliding
val x = ... // RDD[Item]
val xSize = x.count
val n = 1000000.0 // (approximate) desired sample size
val pairs = x.sample(true, n/xSize).sliding(2)
val distances = pairs.map(arr => dist(arr(0), arr(1)))