【问题标题】:How to set k-Means clustering labels from highest to lowest with Python?如何使用 Python 从最高到最低设置 k-Means 聚类标签?
【发布时间】:2017-12-06 21:22:04
【问题描述】:

我有一个包含 38 套公寓及其早上、下午和晚上用电量的数据集。我正在尝试使用 scikit-learn 中的 k-Means 实现对这个数据集进行聚类,并且得到了一些有趣的结果。

第一个聚类结果:

这一切都很好,对于 4 个集群,我显然得到了与每个公寓相关联的 4 个标签 - 0、1、2 和 3。使用 KMeans 方法的 random_state 参数,我可以修复其中的种子质心是随机初始化的,因此我始终会得到归属于相同公寓的相同标签。

但是,由于此特定情况与能源消耗有关,因此可以在最高和最低消费者之间进行可衡量的分类。因此,我想将标签 0 分配给消费水平最低的公寓,将标签 1 分配给消费更多的公寓,依此类推。

到目前为止,我的标签是 [2 1 3 0] 或 ["black", "green", "blue", "red"];我希望它们是 [0 1 2 3] 或 ["red"、"green"、"black"、"blue"]。我应该如何继续这样做,同时仍然保持质心初始化随机(具有固定种子)?

非常感谢您的帮助!

【问题讨论】:

  • 我认为最好的办法是在标签之后添加注释。

标签: python sorting numpy scikit-learn k-means


【解决方案1】:

也许根据质心的矢量幅度对质心进行排序会更好,因为您可以使用它来预测使用相同模型的其他数据。这是我在my repo中的实现

from sklearn.cluster import KMeans

def sorted_cluster(x, model=None):
    if model == None:
        model = KMeans()
    model = sorted_cluster_centers_(model, x)
    model = sorted_labels_(model, x)
    return model

def sorted_cluster_centers_(model, x):
    model.fit(x)
    new_centroids = []
    magnitude = []
    for center in model.cluster_centers_:
        magnitude.append(np.sqrt(center.dot(center)))
    idx_argsort = np.argsort(magnitude)
    model.cluster_centers_ = model.cluster_centers_[idx_argsort]
    return model

def sorted_labels_(sorted_model, x):
    sorted_model.labels_ = sorted_model.predict(x)
    return sorted_model

例子:

import numpy as np
arr = np.vstack([
    100 + np.random.random((2,3)),
    np.random.random((2,3)),
    5 + np.random.random((3,3)),
    10 + np.random.random((2,3))
])
print('Data:')
print(arr)

cluster = KMeans(n_clusters=4)

print('\n Without sort:')
cluster.fit(arr)
print(cluster.cluster_centers_)
print(cluster.labels_)
print(cluster.predict([[5,5,5],[1,1,1]]))

print('\n With sort:')
cluster = sorted_cluster(arr, cluster)
print(cluster.cluster_centers_)
print(cluster.labels_)
print(cluster.predict([[5,5,5],[1,1,1]]))

输出:

Data:
[[100.52656263 100.57376566 100.63087757]
 [100.70144046 100.94095196 100.57095386]
 [  0.21284187   0.75623797   0.77349013]
 [  0.28241023   0.89878796   0.27965047]
 [  5.14328748   5.37025887   5.26064209]
 [  5.21030632   5.09597417   5.29507699]
 [  5.81531591   5.11629056   5.78542656]
 [ 10.25686526  10.64181304  10.45651994]
 [ 10.14153211  10.28765705  10.20653228]]

 Without sort:
[[ 10.19919868  10.46473505  10.33152611]
 [100.61400155 100.75735881 100.60091572]
 [  0.24762605   0.82751296   0.5265703 ]
 [  5.38963657   5.19417453   5.44704855]]
[1 1 2 2 3 3 3 0 0]
[3 2]

 With sort:
[[  0.24762605   0.82751296   0.5265703 ]
 [  5.38963657   5.19417453   5.44704855]
 [ 10.19919868  10.46473505  10.33152611]
 [100.61400155 100.75735881 100.60091572]]
[3 3 0 0 1 1 1 2 2]
[1 0]

【讨论】:

    【解决方案2】:

    通过查找表转换标签是实现您想要的直接方法。

    首先我生成一些模拟数据:

    import numpy as np
    
    np.random.seed(1000)
    
    n = 38
    X_morning = np.random.uniform(low=.02, high=.18, size=38)
    X_afternoon = np.random.uniform(low=.05, high=.20, size=38)
    X_night = np.random.uniform(low=.025, high=.175, size=38)
    X = np.vstack([X_morning, X_afternoon, X_night]).T
    

    然后我对数据进行聚类:

    from sklearn.cluster import KMeans
    k = 4
    kmeans = KMeans(n_clusters=k, random_state=0).fit(X)
    

    最后我使用 NumPy 的 argsort 来创建一个像这样的查找表:

    idx = np.argsort(kmeans.cluster_centers_.sum(axis=1))
    lut = np.zeros_like(idx)
    lut[idx] = np.arange(k)
    

    示例运行:

    In [70]: kmeans.cluster_centers_.sum(axis=1)
    Out[70]: array([ 0.3214523 ,  0.40877735,  0.26911353,  0.25234873])
    
    In [71]: idx
    Out[71]: array([3, 2, 0, 1], dtype=int64)
    
    In [72]: lut
    Out[72]: array([2, 3, 1, 0], dtype=int64)
    
    In [73]: kmeans.labels_
    Out[73]: array([1, 3, 1, ..., 0, 1, 0])
    
    In [74]: lut[kmeans.labels_]
    Out[74]: array([3, 0, 3, ..., 2, 3, 2], dtype=int64)
    

    idx 显示从最低到最高消费级别排序的集群中心标签。 lut[kmeans.labels_]0 / 3 的公寓属于消费水平最低/最高的集群。

    【讨论】:

    • 我正在寻找 scikit learn 包中内置的东西,想知道它是否已经在集群方法中实现。没有那个,您的解决方案完美运行 - 谢谢。
    猜你喜欢
    • 2021-10-11
    • 2019-06-01
    • 2019-09-19
    • 1970-01-01
    • 2020-10-08
    • 2012-07-22
    • 2016-08-27
    • 2019-09-22
    相关资源
    最近更新 更多