【问题标题】:Different silhouette scores when using sklearn and Spark使用 sklearn 和 Spark 时的不同轮廓分数
【发布时间】:2020-07-06 16:22:04
【问题描述】:

当我使用 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

这里是用于 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

如上所示,尽管输入相同,但得分却大不相同。这是为什么呢?

【问题讨论】:

    标签: python apache-spark machine-learning scikit-learn cluster-analysis


    【解决方案1】:

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

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

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


    证明:

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

    我们有集群 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

    【讨论】:

    • 感谢您的回答。我也看到了代码中包含的解释。但是我没有找到它说它是近似算法的地方。请您指出来吗?
    • @gwy1995:很抱歉这么晚才回复您。我仔细研究了 Spark 的实现,它实际上 不是 一个近似值。我已经更正了答案和解释。它现在应该对正在发生的事情给出完整的解释。
    猜你喜欢
    • 2018-12-10
    • 2014-01-06
    • 2014-07-04
    • 2013-12-20
    • 2022-01-19
    • 2015-05-07
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    相关资源
    最近更新 更多