用Spark创建一个邻居矩阵[`cartesian()`issue]

时间:2015-02-25 19:24:27

标签: java hadoop apache-spark bigdata cartesian-product

我是Spark初学者,我面临以下问题:我有一个项目集合(假设它们是笛卡尔坐标或2D点)我希望得到每个项目的近元素。确定一个项目是否接近另一个项目取决于一个函数(假设我们想要所有那些欧几里德距离小于给定值的点)。

当然,获得一个点的邻居是微不足道的,我已经做到了。只需filter项目即可。我不能做的就是让他们获得集合中的所有要点,我不知道如何有效地做到这一点。

我在这里写了一个我希望从一个小数据集中得到的结果的例子,以便更清楚地了解我的需求:

sourceData = [ (0,1) , (1,1), (0,0), (50,10), (51,11)  ]
result = [  
            (0,1) => [(1,1), (0,0)], 
            (1,1) => [(0,1), (0,0)],
            (0,0) => [(0,1), (1,1)],
            (50,10) => [(51,11)],
            (51,11) => [(50,10)]
 ]

您是否知道如何以有效的方式做到这一点?

到现在为止,我试过这个:

return sourceData.cartesian(sourceData)
            .filter(new PairNeighborFilter<T>())
            .groupByKey();

 public class PairNeighborFilter<T extends DbScanPoint> implements Function<Tuple2<T, T>, Boolean> {

/**
 * 
 */
private static final long serialVersionUID = 1L;
public static double eps;


@Override
    public Boolean call(Tuple2<T, T> v1) throws Exception {
        return v1._1().distanceTo(v1._2()) <= eps && !v1._1().equals(v1._2());
    }


}

但我相信这是一种非常低效的方法。此外,稍后我需要计算每个键的元素,这可以只迭代所有元素并计算它们,这是性能的另一个耻辱。 我希望JavaRDD类的值为JavaPairRDD而不是Iterable,这可能吗?

感谢。

1 个答案:

答案 0 :(得分:0)

为了有效地找到邻居,你可能想避免做一个完整的笛卡尔积,因为它是一个O(n ^ 2)运算。一种替代方案是使用局部敏感散列来识别较小的候选点对集合,然后计算候选对之间的精确距离。 (这是&#34;近似&#34;最近邻居的方法,因为任何特定点的一些真正的最近邻居可能不会与相关点散列到同一个桶中。 )

a few ANN/LSH Spark packages可用于此。