【问题标题】:Scikit-learn: How to run KMeans on a one-dimensional array?Scikit-learn:如何在一维数组上运行 KMeans?
【发布时间】:2015-04-09 14:01:29
【问题描述】:

我有一个介于 0 和 1 之间的 13.876(13,876) 个值的数组。我想仅将 sklearn.cluster.KMeans 应用于此向量,以查找对这些值进行分组的不同集群。但是,KMeans 似乎适用于多维数组而不是一维数组。我想有一个技巧可以让它工作,但我不知道如何。我看到 KMeans.fit() 接受 "X : array-like or sparse matrix, shape=(n_samples, n_features)",但它希望 n_samples 大于一

我尝试将我的数组放在 np.zeros() 矩阵上并运行 KMeans,但随后将所有非空值放在类 1 上,其余的放在类 0 上。

谁能帮助在一维数组上运行这个算法?

【问题讨论】:

    标签: python scikit-learn data-mining k-means


    【解决方案1】:

    您有许多 1 个特征的样本,因此您可以使用 numpy 的 reshape 将数组重塑为 (13,876, 1):

    from sklearn.cluster import KMeans
    import numpy as np
    x = np.random.random(13876)
    
    km = KMeans()
    km.fit(x.reshape(-1,1))  # -1 will be calculated to be 13876 here
    

    【讨论】:

    • 如果对这种形状的数据使用 MiniBatchKmeans,会得到非常不同的结果。这是预期的行为吗??
    • 这与随机状态有关。如果一个人修复它,一个人会得到相同的结果。
    • 谁能帮我画出上面代码形成的集群。
    【解决方案2】:

    了解Jenks Natural Breaks。 Python中的函数从文章中找到了链接:

    def get_jenks_breaks(data_list, number_class):
        data_list.sort()
        mat1 = []
        for i in range(len(data_list) + 1):
            temp = []
            for j in range(number_class + 1):
                temp.append(0)
            mat1.append(temp)
        mat2 = []
        for i in range(len(data_list) + 1):
            temp = []
            for j in range(number_class + 1):
                temp.append(0)
            mat2.append(temp)
        for i in range(1, number_class + 1):
            mat1[1][i] = 1
            mat2[1][i] = 0
            for j in range(2, len(data_list) + 1):
                mat2[j][i] = float('inf')
        v = 0.0
        for l in range(2, len(data_list) + 1):
            s1 = 0.0
            s2 = 0.0
            w = 0.0
            for m in range(1, l + 1):
                i3 = l - m + 1
                val = float(data_list[i3 - 1])
                s2 += val * val
                s1 += val
                w += 1
                v = s2 - (s1 * s1) / w
                i4 = i3 - 1
                if i4 != 0:
                    for j in range(2, number_class + 1):
                        if mat2[l][j] >= (v + mat2[i4][j - 1]):
                            mat1[l][j] = i3
                            mat2[l][j] = v + mat2[i4][j - 1]
            mat1[l][1] = 1
            mat2[l][1] = v
        k = len(data_list)
        kclass = []
        for i in range(number_class + 1):
            kclass.append(min(data_list))
        kclass[number_class] = float(data_list[len(data_list) - 1])
        count_num = number_class
        while count_num >= 2:  # print "rank = " + str(mat1[k][count_num])
            idx = int((mat1[k][count_num]) - 2)
            # print "val = " + str(data_list[idx])
            kclass[count_num - 1] = data_list[idx]
            k = int((mat1[k][count_num] - 1))
            count_num -= 1
        return kclass
    

    使用和可视化:

    import numpy as np
    import matplotlib.pyplot as plt
    
    def get_jenks_breaks(...):...
    
    x = np.random.random(30)
    breaks = get_jenks_breaks(x, 5)
    
    for line in breaks:
        plt.plot([line for _ in range(len(x))], 'k--')
    
    plt.plot(x)
    plt.grid(True)
    plt.show()
    

    结果:

    【讨论】:

      猜你喜欢
      • 2020-02-13
      • 2017-04-15
      • 2014-05-11
      • 2015-02-20
      • 2016-12-16
      • 2015-11-28
      • 2015-04-05
      • 2019-11-29
      • 1970-01-01
      相关资源
      最近更新 更多