Python中的球形k-means实现

时间:2013-10-07 14:03:13

标签: python scipy k-means

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

你知道球形k均值的任何好的Python实现(即类似于scipy的k-means)吗?如果没有,修改scipy的源代码以使其k-means算法适应球形有多难?

谢谢。

3 个答案:

答案 0 :(得分:7)

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

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

实际上,当中心和数据点都被归一化时,余弦距离与欧几里德距离之间存在一对一的关系

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

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

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:1)

如果你在3D球体上有极坐标,,如(latlon)对:< / p>

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

    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包。如果您将(latlon)对的行提供的极坐标数据称为X,并且您希望在其中找到10个群集,则KMeans群集的最终代码将是:

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