SparkMLlib - KMeans性能测试

大家好,我是一拳就能打爆A柱的猛男

前面两篇写了逻辑回归和线性回归的测试方法,这回来说无监督算法KMeans的测试,接下来的讲解顺序是:1、评价指标介绍,2、具体案例。

注:

对数据集有疑问的同学可以看《SparkMLlib-LogisticRegression性能测试》,对KMeans算法有疑问的同学可以看《K-Means算法及相关案例》。

1、 评价指标介绍

聚类算法评价标准需要考虑簇内相似度以及簇间相似度,簇内相似度越高越好,簇间相似度越低越好。聚类算法的评价指标分为两大部分:内部评价指标 和 外部评价指标。

  • 内部评价指标:CH指标、轮廓系数 Silhouette 、 DB指数。
  • 外部评价指标: RI、ARI、AMI。

具体的评价指标公式可以参考:《聚类算法的评价指标》

2、 具体案例

之前我在《SparkMLlib-LinearRegression性能测试》 里说过我已经有点感觉SparkMLlib的继承树,或者说整个库的设计有点乱了,这回大家可以看到在线性回归中他提供了相关的指标计算,而这次KMeans里却没有,而是提供了一个第三方的包ClusteringEvaluator来做指标测试:

在org.apache.spark.ml.evaluation.ClusteringEvaluator下给的评价指标是轮廓系数 Silhouette(有且只有这一个指标):

/**
 * Evaluator for clustering results.
 * The metric computes the Silhouette measure using the specified distance measure.
 *
 * The Silhouette is a measure for the validation of the consistency within clusters. It ranges
 * between 1 and -1, where a value close to 1 means that the points in a cluster are close to the
 * other points in the same cluster and far from the points of the other clusters.
 */
@Since("2.3.0")
class ClusteringEvaluator @Since("2.3.0") (@Since("2.3.0") override val uid: String)
  extends Evaluator with HasPredictionCol with HasFeaturesCol with DefaultParamsWritable {

轮廓系数的取值范围在[-1,1]之间,并且Silhouette越接近1则表示该样本点距离本簇内的其他点越近,距离其他簇的样本点越远。

数据集:sample_kmeans_data.txt

观察内部指标Sihouette:

import org.apache.spark.ml.clustering.{KMeans, KMeansModel}
import org.apache.spark.ml.evaluation.ClusteringEvaluator
import org.apache.spark.sql.{DataFrame, SparkSession}


object KmeansClusteringDemo {

  def main(args: Array[String]): Unit = {
    val spark: SparkSession = SparkSession.builder.appName("KmeansClusteringDemo").getOrCreate()
    val training: DataFrame = spark.read.format("libsvm").load("path\\sample_kmeans_data.txt")

    val kmeans: KMeans = new KMeans().setK(2).setSeed(1L)
    val kmeansModel: KMeansModel = kmeans.fit(training)

    val predictions: DataFrame = kmeansModel.transform(training)

    val evaluator = new ClusteringEvaluator()

    val silhouette: Double = evaluator.evaluate(predictions)
    println(s"Silhouette with squared euclidean distance = $silhouette")

  }
}

控制台输出为:

Silhouette with squared euclidean distance = 0.9997530305375207

可以看到非常接近1,所以说拟合的很好,可是这是在官方提供的数据集中测试,并且只有这一个指标。