数字聚类/分区算法

时间:2011-11-15 16:54:07

标签: algorithm cluster-analysis partitioning

我有一个有序的1-D数字数组。数组长度和数组中数字的值都是任意的。我想根据数值将数组划分为k个分区,例如:假设我想要4个分区,分配为30%/ 30%/ 20%/ 20%,即前30%的值,之后的30%等等。我可以选择k和分布的百分比。此外,如果相同的数字在数组中出现多次,则不应包含在两个不同的分区中。这意味着上面的分配百分比并不严格,而是“目标”或“起点”,如果你愿意的话。

例如,假设我的数组为ar = [1, 5, 5, 6, 7, 8, 8, 8, 8, 8]

我选择k = 4,数字应按百分比pA = pB = pC = pD = 25%分配到分区A,B,C和D中。

鉴于我上面给出的限制,结果分区应为:

A = [1] B = [5, 5] C = [6, 7] D = [8, 8, 8, 8, 8]

得出(达到/更正)百分比pcA = 10%, pcB = 20%, pcC = 20%, pcD = 50%

在我看来,我需要一个改进的k-means算法,因为标准算法不能保证尊重我的百分比和/或要求相同的值不能在多个集群/分区中。

那么,有这种聚类的算法吗?

3 个答案:

答案 0 :(得分:1)

聚类算法用于多维数据。对于一维数据,您应该只使用排序算法。

对数据进行排序。然后根据您的示例将数据集从数组底部线性分区到顶部。

答案 1 :(得分:1)

这是一个动态编程解决方案,它找到一个分区,可以最大限度地减少部件大小中错误的平方和。所以在[1,5,5,6,7,8,8,8,8,8]的例子中,你需要大小的部分(2.5,2.5,2.5,2.5),这个代码给出的结果是( 9.0,(1,2,2,5))。这意味着所选分区的大小为1,2,2和5,总误差为9 =(2.5-1)^ 2 +(2.5-2)^ 2 +(2.5-2)^ 2 +(2.5- 5)^ 2。

def partitions(a, i, sizes, cache):
    """Find a least-cost partition of a[i:].

    The ideal sizes of the partitions are stored in the tuple 'sizes'
    and cache is used to memoize previously calculated results.
    """
    key = (i, sizes)
    if key in cache: return cache[key]
    if len(sizes) == 1:
        segment = len(a) - i
        result = (segment - sizes[0]) ** 2, (segment,)
        cache[key] = result
        return result
    best_cost, best_partition = None, None
    for j in xrange(len(a) - i + 1):
        if 0 < j < len(a) - i and a[i + j - 1] == a[i + j]:
            # Avoid breaking a run of one number.
            continue
        bc, bp = partitions(a, i + j, sizes[1:], cache)
        c = (j - sizes[0]) ** 2 + bc
        if best_cost is None or c < best_cost:
            best_cost = c
            best_partition = (j,) + bp
    cache[key] = (best_cost, best_partition)
    return cache[key]


ar = [1, 5, 5, 6, 7, 8, 8, 8, 8, 8]
sizes = (len(ar) * 0.25,) * 4
print partitions(ar, 0, (2.5, 2.5, 2.5, 2.5), {})

答案 2 :(得分:0)

天真的做法会是这样的:

假设p1 ... pk是分区的百分比(p1 + ... + pk = 1)

假设你在数组中有N个元素

初始边界(其中有k + 1个,包括数组结束,因为你有k个分区)是: 0,p1 * N,(p1 + p2)* N,...,N(有一些舍入要做)。

要移动边界,可以查看边界两侧的两个数组元素(对于可以移动的k-1边界)。如果两个元素相等,则需要移动到右边的边界,至少在满足约束之前。一种天真的方法是从左侧开始并进行最小的调整(只需将约束调整到导致移动最少的一侧,并且不再进一步移动边界)。

此算法不会覆盖整个分区空间。它只是给你一个解决方案。要找到最佳解决方案,您需要对整个分区空间进行强力搜索,并进行某种修剪(例如动态编程,您可以记住初始数组的子阵列的最佳分区)。