【问题标题】:Spherical k-means implementation in PythonPython中的球形k-means实现
【发布时间】:2013-10-14 03:35:25
【问题描述】:

我使用scipy's k-means 已经有一段时间了,我对它在可用性和效率方面的工作方式感到非常满意。但是,现在我想探索不同的 k-means 变体,更具体地说,我想在我的一些问题中应用spherical k-means

您知道球面 k-means 的任何好的 Python 实现(即类似于 scipy 的 k-means)吗?如果不是,修改 scipy 的源代码以使其 k-means 算法成为球形有多难?

谢谢。

【问题讨论】:

    标签: python scipy k-means


    【解决方案1】:

    在球面 k 均值中,您的目标是保证中心在球面上,因此您可以调整算法以使用余弦距离,并且还应该对最终结果的质心进行归一化。

    当使用欧几里得距离时,我更喜欢将算法视为在每次迭代中将聚类中心投影到单位球体上,即,在每个最大化步骤之后应该对中心进行归一化。

    确实,当中心和数据点都归一化时,余弦距离和欧几里得距离是一一对应的关系

    |a - b|_2 = 2 * (1 - cos(a,b))
    

    jasonlaska/spherecluster 包将 scikit-learns 的 k-means 修改为 spherical k-means,还提供了另一种球体聚类算法。

    【讨论】:

    • 我认为这个答案应该被接受,@oriol-nieto
    • 表达式中不应该有sqrt吗? |a - b|_2 = sqrt(2 * (1 - cos(a, b))) 这不会改变指出的一对一关系。
    【解决方案2】:

    操作方法如下,如果您在 3D 球体上有极坐标,例如(lat, lon)对

    1. 如果您的坐标是以度为单位的 (lat, lon) 坐标,您可以编写一个函数将这些点转换为笛卡尔坐标,例如:

      def cartesian_encoder(coord, r_E=6371):
          """Convert lat/lon to cartesian points on Earth's surface.
      
          Input
          -----
              coord : numpy 2darray (size=(N, 2))
              r_E : radius of Earth
      
          Output
          ------
              out : numpy 2darray (size=(N, 3))
          """
          def _to_rad(deg):
              return deg * np.pi / 180.
      
          theta = _to_rad(coord[:, 0])  # lat [radians]
          phi = _to_rad(coord[:, 1])    # lon [radians]
      
          x = r_E * np.cos(phi) * np.cos(theta)
          y = r_E * np.sin(phi) * np.cos(theta)
          z = r_E * np.sin(theta)
      
          return np.concatenate([x.reshape(-1, 1), y.reshape(-1, 1), z.reshape(-1, 1)], axis=1)
      

      如果您的坐标已经是弧度,只需删除该函数中的前 5 行。

    2. 使用 pip 安装 spherecluster 包。如果以 (lat, lon) 对的行形式给出的极坐标数据称为 X,并且您想在其中找到 10 个簇,则 KMeans-clustering 球形的最终代码将是:

      import numpy as np
      import spherecluster
      
      X_cart = cartesian_encoder(X)
      kmeans_labels = SphericalKMeans(10).fit_predict(X_cart)
      

    【讨论】:

    • 不过,我应该补充一点,使用来自sklearn 的常规 KMeans 可能会在 99% 的情况下为您提供相同的结果。所以只需转换为笛卡尔坐标并将它们聚类。
    【解决方案3】:

    看起来球形 k-means 的显着特征是使用余弦距离,而不是标准的欧几里得度量。话虽如此,在另一个答案中,这里有一个很好的纯 numpy/scipy 改编:

    Is it possible to specify your own distance function using Scikits.Learn K-Means Clustering?

    如果这不符合您的要求,您可能想试试sklearn.cluster

    【讨论】:

    • 我可能是错的,但我理解球面 k 均值的方式是学习的质心位于由数据的标准差定义的超球面的表面。您应该能够使用您喜欢的距离度量来学习这些质心(然后对新数据进行聚类),而不仅仅是余弦。无论如何,谢谢你的回答。这个链接其实很有趣。
    • @urinieto 你可能是对的,我对球形 K-means 没有经验。我只是假设它来自一个余弦度量,它通过浏览链接的论文 OP 发布。我也对纠正这个问题的答案感兴趣。
    猜你喜欢
    • 2021-05-04
    • 2016-10-11
    • 2020-06-21
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2013-07-24
    • 2012-11-06
    • 2011-07-24
    相关资源
    最近更新 更多