我使用scipy 的 k-means已经有一段时间了,我对它在可用性和效率方面的工作方式感到非常满意。但是,现在我想探索不同的 k-means 变体,更具体地说,我想在我的一些问题中应用球形 k-means。
你知道球面 k-means 的任何好的 Python 实现(即类似于 scipy 的 k-means)吗?如果不是,那么修改 scipy 的源代码以使其 k-means 算法适应球形有多难?
谢谢你。
我使用scipy 的 k-means已经有一段时间了,我对它在可用性和效率方面的工作方式感到非常满意。但是,现在我想探索不同的 k-means 变体,更具体地说,我想在我的一些问题中应用球形 k-means。
你知道球面 k-means 的任何好的 Python 实现(即类似于 scipy 的 k-means)吗?如果不是,那么修改 scipy 的源代码以使其 k-means 算法适应球形有多难?
谢谢你。
在球面 k-means 中,您的目标是保证中心在球面上,因此您可以调整算法以使用余弦距离,并且还应该对最终结果的质心进行归一化。
当使用欧几里得距离时,我更喜欢将算法视为在每次迭代中将聚类中心投影到单位球面上,即在每个最大化步骤之后应该对中心进行归一化。
实际上,当中心和数据点都归一化时,余弦距离和欧几里得距离之间存在一对一的关系
|a - b|_2 = 2 * (1 - cos(a,b))
jasonlaska/spherecluster包将 scikit- learns 修改k-means
为spherical k-means
,还提供了另一种球体聚类算法。
看起来球形 k-means 中的显着特征是使用余弦距离,而不是标准的欧几里得度量。话虽如此,在另一个答案中,这里有一个很好的纯 numpy/scipy 改编:
是否可以使用 Scikits.Learn K-Means Clustering 指定您自己的距离函数?
如果这不符合您正在寻找的内容,您可能想尝试一下sklearn.cluster
。
如果您在 3D 球体上有极坐标,例如 ( lat
, lon
) 对,则执行以下操作:
如果您的坐标是以度为单位测量的 ( 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 行。
spherecluster
使用 pip安装软件包。如果以 ( 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)