如何在python中执行权重/密度的集群?像重量的kmeans?

时间:2017-07-11 03:51:12

标签: python algorithm scipy scikit-learn cluster-analysis

我的数据是这样的:

Duration

我希望能够将数据聚类为N个聚类(比如3)。通常我会使用kmeans:

Moment.plus

这个问题是它没有考虑任何加权(在这种情况下,我的powergenerated值)我想要理想地让我的集群考虑“powergenerated”的值,试图保持集群不仅在空间上接近,但也有接近相对相等的总发电量。

我应该用kmeans(或其他方法)这样做吗?或者我还应该使用其他什么来解决这个问题呢?

2 个答案:

答案 0 :(得分:7)

  

或者我还应该使用其他更好的问题吗?

为了同时考虑中心之间的地理距离和产生的功率,您应该定义适当的指标。下面的函数计算地球表面上两个点之间的距离,从纬度和经度到haversine formula,并将生成的功率差的绝对值乘以加权因子。权重值决定了聚类过程中距离和功率差异的相对影响。

import numpy as np

def custom_metric(central_1, central_2, weight=1):
    lat1, lng1, pow1 = central_1
    lat2, lng2, pow2 = central_2

    lat1, lat2, lng1, lng2 = np.deg2rad(np.asarray([lat1, lat2, lng1, lng2]))

    dlat = lat2 - lat1
    dlng = lng2 - lng1

    h = (1 - np.cos(dlat))/2. + np.cos(lat1)*np.cos(lat2)*(1 - np.cos(dlng))/2.
    km = 2*6371*np.arcsin(np.sqrt(h))

    MW = np.abs(pow2 - pow1)

    return km + weight*MW
  

我应该用kmeans(或其他方法)这样做吗?

不幸的是,SciPy的kmeans2和scikit-learn的KMeans的当前实现仅支持欧几里德距离。另一种方法是通过SciPy的聚类包执行hierarchical clustering,根据刚刚定义的度量对中心进行分组。

演示

让我们首先生成模拟数据,即具有随机值的8个中心的特征向量:

N = 8
np.random.seed(0)
lat = np.random.uniform(low=-90, high=90, size=N)
lng = np.random.uniform(low=-180, high=180, size=N)
power = np.random.randint(low=5, high=50, size=N)
data = np.vstack([lat, lng, power]).T

上面代码段产生的变量data的内容如下所示:

array([[   8.7864,  166.9186,   21.    ],
       [  38.7341,  -41.9611,   10.    ],
       [  18.4974,  105.021 ,   20.    ],
       [   8.079 ,   10.4022,    5.    ],
       [ -13.7421,   24.496 ,   23.    ],
       [  26.2609,  153.2148,   40.    ],
       [ -11.2343, -154.427 ,   29.    ],
       [  70.5191, -148.6335,   34.    ]])

要将这些数据划分为三个不同的组,我们必须将datacustom_metric传递给linkage函数(查看docs以了解有关参数{{的更多信息1}}),然后将返回的链接矩阵传递给method函数cut_tree

n_clusters=3

结果我们获得了每个中心的组成员资格(数组from scipy.cluster.hierarchy import linkage, cut_tree Z = linkage(data, method='average', metric=custom_metric) y = cut_tree(Z, 3).flatten() ):

y

上述结果取决于array([0, 1, 0, 2, 2, 0, 0, 1]) 的值。如果您希望使用与weight不同的值(例如1),则可以更改默认值,如下所示:

250

或者,您可以将def custom_metric(central_1, central_2, weight=250): 调用中的参数metric设置为linkage表达式,如下所示:lambda

最后,为了深入了解分层/凝聚聚类,您可以将其绘制为树状图:

metric=lambda x, y: custom_metric(x, y, 250)

dendrogram

答案 1 :(得分:0)

如果您正在寻找一种基于坐标和权重对这些坐标进行权重来形成聚类的解决方案,则可以添加sample_weight = power。这将为您提供基于坐标的聚类,质心将倾向于聚类中权重更高的观测