Scala 使用平方距离的两点之间的Apache Spark距离

Scala 使用平方距离的两点之间的Apache Spark距离,scala,apache-spark,dbscan,rdd,Scala,Apache Spark,Dbscan,Rdd,我有一个RDD向量集合,其中每个向量代表一个具有x和y坐标的点。例如,文件如下所示: 1.1 1.2 6.1 4.8 0.1 0.1 9.0 9.0 9.1 9.1 0.4 2.1 我正在读: def parseVector(line: String): Vector[Double] = { DenseVector(line.split(' ')).map(_.toDouble) } val lines = sc.textFile(inputFile) val poi

我有一个RDD向量集合,其中每个向量代表一个具有x和y坐标的点。例如,文件如下所示:

1.1 1.2
6.1 4.8
0.1 0.1
9.0 9.0
9.1 9.1
0.4 2.1
我正在读:

  def parseVector(line: String): Vector[Double] = {
    DenseVector(line.split(' ')).map(_.toDouble)
  }

  val lines = sc.textFile(inputFile)
  val points = lines.map(parseVector).cache()
此外,我还有一个ε:

  val eps = 2.0
对于每个点,我想找到它的邻居,他们在ε距离内。我有:

points.foreach(point =>
  // squaredDistance(point, ?) what should I write here?
)

如何循环所有点并为每个点找到其邻居?可能使用映射功能?

您可以执行以下操作:

val distanceBetweenPoints = points.cartesian(points)
    .filter{case (x,y) => (x!=y)} // remove the (x,x) diagonal
    .map{case (x,y) => ((x,y),distance(x,y))}
val pointsWithinEps = distanceBetweenPoints.filter{case ((x,y),distance) => distance <= eps)}

如果不关心点之间的距离,也可以在过滤器中组合距离计算。

可以执行以下操作:

val distanceBetweenPoints = points.cartesian(points)
    .filter{case (x,y) => (x!=y)} // remove the (x,x) diagonal
    .map{case (x,y) => ((x,y),distance(x,y))}
val pointsWithinEps = distanceBetweenPoints.filter{case ((x,y),distance) => distance <= eps)}
如果不关心点之间的距离,也可以在过滤器中组合距离计算。

可以使用a并执行以下操作:

val distanceBetweenPoints = points.cartesian(points)
    .filter{case (x,y) => (x!=y)} // remove the (x,x) diagonal
    .map{case (x,y) => ((x,y),distance(x,y))}
val pointsWithinEps = distanceBetweenPoints.filter{case ((x,y),distance) => distance <= eps)}
导入org.aizook.scala.clustering.Spark\u DBSCAN.DBSCAN val集群:Dbscan=新的Dbscan3,5,数据 聚类预测2000,48.3,33.1

您可以使用a并执行以下操作:

val distanceBetweenPoints = points.cartesian(points)
    .filter{case (x,y) => (x!=y)} // remove the (x,x) diagonal
    .map{case (x,y) => ((x,y),distance(x,y))}
val pointsWithinEps = distanceBetweenPoints.filter{case ((x,y),distance) => distance <= eps)}
导入org.aizook.scala.clustering.Spark\u DBSCAN.DBSCAN val集群:Dbscan=新的Dbscan3,5,数据 聚类预测2000,48.3,33.1


@Bob,这是因为48.3,33.1不适合集群,应归类为噪声。 我向提交了一个更新,并且它应该在预测符合噪声的任何时候返回-1

import org.aizook.scala.clustering.Spark_DBSCAN.Dbscan
val eps = 2
val minPts = 2
val data = sc.textFile("data.txt").map(_.split(" ")).map(p => (p(0).trim.toDouble, p(1).trim.toDouble)).zipWithUniqueId().map(x => (x._2,x._1)).cache;
val cluster:Dbscan = new Dbscan(eps,minPts,data)
cluster.predict((data.count+1,(9.0,10.0)))  // Should return 1 for cluster 1
cluster.predict((data.count+2,(2.0,2.0)))   // Should return 0 for cluster 0
cluster.predict((data.count+3,(15.0,23.0))) // Should return -1 for noise
对于包含您提交的数据示例的data.txt:

1.1 1.2
6.1 4.8
0.1 0.1
9.0 9.0
9.1 9.1
0.4 2.1

@Bob,这是因为48.3,33.1不适合集群,应归类为噪声。 我向提交了一个更新,并且它应该在预测符合噪声的任何时候返回-1

import org.aizook.scala.clustering.Spark_DBSCAN.Dbscan
val eps = 2
val minPts = 2
val data = sc.textFile("data.txt").map(_.split(" ")).map(p => (p(0).trim.toDouble, p(1).trim.toDouble)).zipWithUniqueId().map(x => (x._2,x._1)).cache;
val cluster:Dbscan = new Dbscan(eps,minPts,data)
cluster.predict((data.count+1,(9.0,10.0)))  // Should return 1 for cluster 1
cluster.predict((data.count+2,(2.0,2.0)))   // Should return 0 for cluster 0
cluster.predict((data.count+3,(15.0,23.0))) // Should return -1 for noise
对于包含您提交的数据示例的data.txt:

1.1 1.2
6.1 4.8
0.1 0.1
9.0 9.0
9.1 9.1
0.4 2.1

即使这个答案已经被接受,我还是在这里提醒大家,被接受的解决方案与github回购协议中提出的基本相同,但由于笛卡尔操作的复杂性和巨大的数据集,它实际上是不可扩展的,这肯定是个问题

还有另一种解决方案,即DBSCAN算法在Spark上的另一种实现,可在此处找到。该解决方案提出了一种不同的方法,将RDD数据集划分为多个框。通过这种方式,近点只能是所考虑点的同一框中的点,以及距离相邻分区边界小于ε的点。这样,复杂性下降到Om^2,其中m是n/k,k是分区数。此外,如果您需要更多详细信息,还可以执行其他优化。您可以阅读代码,与作者联系或询问我


以前的实现有一些局限性:只支持欧几里德和曼哈顿度量,并且只能成功处理维度很少的数据集。为了克服这些问题,我创建了这个分支,旨在消除所有这些问题:。现在,它似乎工作得很好,所有问题都解决了,尽管我正在继续测试它,以确保它在发出拉请求之前没有缺陷。

即使这个答案已经被接受,我在这里指出,公认的解决方案基本上与github repo中提出的解决方案相同,但由于笛卡尔操作的复杂性和庞大的数据集,该解决方案实际上不具有可扩展性,这肯定是一个问题

还有另一种解决方案,即DBSCAN算法在Spark上的另一种实现,可在此处找到。该解决方案提出了一种不同的方法,将RDD数据集划分为多个框。通过这种方式,近点只能是所考虑点的同一框中的点,以及距离相邻分区边界小于ε的点。这样,复杂性下降到Om^2,其中m是n/k,k是分区数。此外,如果您需要更多详细信息,还可以执行其他优化。您可以阅读代码,与作者联系或询问我


以前的实现有一些局限性:只支持欧几里德和曼哈顿度量,并且只能成功处理维度很少的数据集。为了克服这些问题,我创建了这个分支,旨在消除所有这些问题:。现在,它似乎工作得很好,所有问题都解决了,不过我正在继续测试它,以确保在发出拉取请求之前它没有缺陷。

非常感谢!我是Spark的新手,尝试使用Spark实现DBSCAN聚类算法。这是第一步。下一步是循环所有点,即循环所有点,并对所有点执行上述步骤。在算法中,我必须存储访问的点-我应该将它们存储在单独的数组中,还是使用元组中的某个指针来确定它是否被访问?此外,关于实现,我还有其他问题。我可以向你咨询一下,在那里我还可以问其他问题。例如,通过Skype
可以私下咨询一下吗?我想向您展示代码并了解您的想法。@Bob如果您在这里提问,每个人都会从中受益,您可能会对您的方法有多个意见/看法。好的。谢谢然后我会发布另一个问题。非常感谢!我是Spark的新手,尝试使用Spark实现DBSCAN聚类算法。这是第一步。下一步是循环所有点,即循环所有点,并对所有点执行上述步骤。在算法中,我必须存储访问的点-我应该将它们存储在单独的数组中,还是使用元组中的某个指针来确定它是否被访问?此外,关于实现,我还有其他问题。我可以向你咨询一下,在那里我还可以问其他问题。例如,通过Skype。是否可以进行私人咨询?我想向您展示代码并了解您的想法。@Bob如果您在这里提问,每个人都会从中受益,您可能会对您的方法有多个意见/看法。好的。谢谢然后我会发布另一个问题。你能举一个输入文件的例子吗?我在主线程java.lang.UnsupportedOperationException:空集合异常中遇到异常。@Bob这是因为48.3,33.1不适合群集,应归类为noise。我在这里提供了一些额外的信息。你能举一个输入文件的例子吗?我在主线程java.lang.UnsupportedOperationException:空集合异常中遇到异常。@Bob这是因为48.3,33.1不适合群集,应归类为noise。我在下文中提供了一些补充信息