使用 sklearn 和 Spark 时的轮廓分数不同

gwy*_*995 4 python cluster-analysis machine-learning scikit-learn apache-spark

当我使用 Spark 和 sklearn 计算具有相同数据和相同预测值的轮廓分数时,我得到了不同的结果。

这是用于 Spark 的代码:

>>> prediction.show()
+---+---+---------+----------+
|  a|  b| features|prediction|
+---+---+---------+----------+
|  1|  1|[1.0,1.0]|         1|
|  2|  2|[2.0,2.0]|         1|
|  3|  3|[3.0,3.0]|         0|
|  4|  4|[4.0,4.0]|         0|
+---+---+---------+----------+

>>> from pyspark.ml.evaluation import ClusteringEvaluator
>>> evaluator = ClusteringEvaluator()
>>> silhouette = evaluator.evaluate(prediction)
>>> silhouette
0.7230769230769223
Run Code Online (Sandbox Code Playgroud)

这是用于 sklearn 的代码:

>>> from sklearn.cluster import KMeans
>>> from sklearn import metrics
>>> x=[[1,1],[2,2],[3,3],[4,4]]
>>> prediction = KMeans(n_clusters=2,max_iter=1000,random_state=123).fit_predict(x)
>>> prediction
array([1, 1, 0, 0], dtype=int32)
>>> silhouette = metrics.silhouette_score(x, prediction)
>>> silhouette
0.46666666666666673
Run Code Online (Sandbox Code Playgroud)

如上所示,虽然输入相同,但分数却大不相同。这是为什么?

Sha*_*ica 6

主要区别在于使用了不同的距离度量

与默认使用正常欧几里德距离的 sklearn 相比,Spark 使用平方欧几里德作为距离度量。

在 Spark 中选择这种距离度量的原因是为了更高效和并行计算。方程的一部分可以预先计算,从而将计算复杂度从O(N^2^*D),其中N是点的数量D及其维度,到O(C*D*N/W)哪里W是工作人员C的数量和集群的数量(假设非常低)。轮廓分数的 Spark 数学推导和实现记录在 github 上(这里)。


证明:

我们可以分析问题中的示例,并使用欧氏距离和平方欧氏距离手动计算轮廓分数。

我们与分簇1 (1,1)(2,2)并以聚类中心(1.5,1.5)与第2组(3,3)(4,4)并在集群中心(3.5,3.5)

最终的轮廓分数是所有样本的轮廓分数的平均值。由于问题中的四个点完全镜像并且只有两个集群,因此计算其中一个集群的分数就足够了(这里我选择了集群 1)。

下面a是平均簇内距离(到同一簇中所有点的平均距离)和b平均簇间距离(到该点不属于的最近簇中所有点的平均距离)。分数计算如下(b-a) / max(b,a)

欧几里得距离:

  • (1,1)

    • a = sqrt((2-1)^2 + (2-1)^2) = sqrt(2)
    • b = (sqrt((3-1)^2 + (3-1)^2) + sqrt((4-1)^2 + (4-1)^2))) / 2 = (sqrt(8) + sqrt(18)) / 2 = 3.5355
    • 分数 = (3.5355 - sqrt(2)) / 3.5355 = 0.6
  • (2,2)

    • a = sqrt((2-1)^2 + (2-1)^2) = sqrt(2)
    • b = (sqrt((3-2)^2 + (3-2)^2) + sqrt((4-2)^2 + (4-2)^2))) / 2 = (sqrt(2) + sqrt(8)) / 2 = 2.1213
    • 分数 = (2.1213 - sqrt(2)) / 2.1213 = 0.33333

剪影分数 = (0.6 + 0.33333) / 2 = 0.4666667

平方欧几里德距离:

  • (1,1)

    • a = (2-1)^2 + (2-1)^2 = 2
    • b = ((3-1)^2 + (3-1)^2 + (4-1)^2 + (4-1)^2) / 2 = (8 + 18) / 2 = 13
    • 分数 = (13 - 2) / 13 = 0.84615
  • (2,2)

    • a = (2-1)^2 + (2-1)^2 = 2
    • b = ((3-2)^2 + (3-2)^2 + (4-2)^2 + (4-2)^2) / 2 = (2 + 8) / 2 = 5
    • 分数 = (5 - 2) / 5 = 0.6

剪影分数 = (0.84615 + 0.6) / 2 = 0.723075