【问题标题】:Computing distance of a vector from the center of K-means cluster计算向量到 K-means 簇中心的距离
【发布时间】:2018-04-06 00:32:38
【问题描述】:

我有训练数据集,我在 K=4 的情况下对其运行 K-means,得到了四个聚类中心。对于新数据点,我不仅想知道预测的集群,还想知道与该集群中心的距离。是否有一个 API 可以计算到中心的欧几里得距离?如果需要,我可以进行 2 个 API 调用。我正在使用 Scala,但在任何地方都找不到任何示例。

【问题讨论】:

    标签: scala apache-spark spark-dataframe rdd apache-spark-mllib


    【解决方案1】:

    由于 Spark 2.0 Vectors.sqdist 可用于计算两个向量之间的平方距离。

    您可以使用 UDF 计算每个点到其中心的距离,如下所示:

    import org.apache.spark.ml.linalg.{Vectors, Vector}
    import org.apache.spark.ml.clustering.KMeans
    import org.apache.spark.sql.functions.udf
    
    // Sample points
    val points = Seq(Vectors.dense(1,0), Vectors.dense(2,-3), Vectors.dense(0.5, -1), Vectors.dense(1.5, -1.5))    
    val df = points.map(Tuple1.apply).toDF("features")
    
    // K-means
    val kmeans = new KMeans()
      .setFeaturesCol("features")
      .setK(2)
    val kmeansModel = kmeans.fit(df)
    
    val predictedDF = kmeansModel.transform(df)
    // predictedDF.schema = (features: Vector, prediction: Int)
    
    // Cluster Centers
    kmeansModel.clusterCenters foreach println
    /*
    [1.75,-2.25]
    [0.75,-0.5]
    */
    
    // UDF that calculates for each point distance from each cluster center
    val distFromCenter = udf((features: Vector, c: Int) => Vectors.sqdist(features, kmeansModel.clusterCenters(c)))
    
    val distancesDF = predictedDF.withColumn("distanceFromCenter", distFromCenter($"features", $"prediction"))
    distancesDF.show(false)
    /*
    +----------+----------+------------------+
    |features  |prediction|distanceFromCenter|
    +----------+----------+------------------+
    |[1.0,0.0] |1         |0.3125            |
    |[2.0,-3.0]|0         |0.625             |
    |[0.5,-1.0]|1         |0.3125            |
    |[1.5,-1.5]|0         |0.625             |
    +----------+----------+------------------+
    */
    

    注意:Vectors.sqdist 计算 2 个向量之间的平方距离(没有平方根)。如果你需要欧几里得距离,你可以使用Math.sqrt(Vectors.sqdist(...))

    【讨论】:

      【解决方案2】:

      以下内容对我有用...

      def EuclideanDistance(x: Array[Double], y: Array[Double]) = {
        scala.math.sqrt((xs zip ys).map { case (x,y) => scala.math.pow(y - x, 2.0) }.sum)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-12
        • 2013-02-02
        • 2018-09-30
        • 2017-05-01
        • 2017-03-13
        • 2013-04-22
        • 2016-12-18
        • 2016-04-14
        相关资源
        最近更新 更多