Python序列聚类练习

时间:2019-03-15 21:34:32

标签: python algorithm cluster-analysis dynamic-programming

我正在完成教科书中的练习,并在Python中实现代码以练习动态编程。我觉得自己马上就可以解决这个问题,但是几个小时后,我来到这里寻求帮助。

基本上,我的代码将遍历值列表x,并给定k,然后根据计算出的最小平方误差(SSE)将列表分成k个簇用于特定群集。

如果我们要在list[0:1],{{1}内将值的所有变化都放在圆括号内,代码将创建一个表,计算1个群集,2个群集,...,k个群集的SSE },list[0:2],...,list[0:3],然后为表格中的特定步骤选择最低SSE。

例如:给定list[0:n]x= [7,6,9,15,18,17,30,28,29],我们将返回聚类k=3,这将转换为每个聚类等于(7,6,9)(15,18,17)(30,28,29)的平方误差总和。因此,该列表上的该群集的最大SSE为(4.666)(4.666)(2)

现在,当我在第二个列表4.666上尝试使用该方法时,我应该得到群集x = [52, 101, 103, 101, 6, 5, 7],该群集应该得到(52)(101, 103, 101)(6, 5, 7)或最多(0)(2.666)(2),但没有得到那。我相信第二个return语句的错误{@ 1}}中存在,以及我如何递增2.666def f(s, j_down, t)。希望我没有犯一个愚蠢的错误!

非常感谢您的帮助,谢谢。

s

编辑:问题布局

给出序列t和整数def mean(numbers): return float(sum(numbers)) / max(len(numbers), 1) def sum_square(x): if isinstance(x, (int,)): return 0 w = 0 for i in x: w += (i - mean(x))**2 return w def f(s, j_down, t): if not r[s][j_down] and r[s][j_down] != 0: return sum_square(x[:t - s]) return max(r[s][j_down], sum_square(x[:t-s])) def get_min_f_and_s(j_down, t): """ range s from 1 to t-1 and set s to minimize f(s) """ items = [(s, f(s, j_down, t)) for s in range(t)] s, min_f = min(items, key=lambda x:x[1]) return s, min_f def seq_out(n,k): for j in range(k): if j == 0: for t in range(n): r[t][j] = sum_square(x[:t+1]) c[t][j] = x[:t+1] else: for t in range(1, n): s, min_f = get_min_f_and_s(j - 1, t) r[t][j] = min_f c[t][j] = [c[s][j - 1]] + x[s+1:t+1] print('the max SSE is: {}'.format(r[-1][-1])) print('the cluster centers are: {}'.format(c[-1][-1])) #x = [7,6,9,15,18,17,30,28,29] x = [52, 101, 103, 101, 6, 5, 7] k = 3 n = len(x) r = [[[] for _ in range(k)] for _ in range(n)] c = [[[] for _ in range(k)] for _ in range(n)] print(seq_out(n,k)) print(r) print(c) ,将X = [x_1, x_2, ... x_n]划分为大小为k > 1的簇X,以使平方误差之和最小。

1 个答案:

答案 0 :(得分:0)

我无法追踪您认为代码应如何工作,因此无法告诉您您犯了什么错误。另外,由于您正在尝试学习,因此我将为您提供思考的方法,而不仅仅是思考魔术出现的代码。

假设您想采用一种自下而上的方法,一种方法是填写下表(最好将其作为数组的数组来完成,但我将其作为字典的词典来使阅读更容易):

best_cluster_by_pos_by_clusters = {
    0: {
        1: {'start': 0, 'error': 0.0, 'max_error': 0.0}
        },
    1: {
        1: {'start': 0, 'error': 1200.5, 'max_error': 1200.5},
        2: {'start': 1, 'error': 0.0, 'max_error': 0.0},
        }, 
    2: {
        1: {'start': 0, 'error': 1668.6666666666667, 'max_error': 1668.6666666666667},
        2: {'start': 1, 'error': 2.0, 'max_error': 2.0},
        3: {'start': 2, 'error': 0.0, 'max_error': 0.0},
        },
    3: {
        1: {'start': 0, 'error': 1852.75, 'max_error': 1852.75},
        2: {'start': 1, 'error': 2.666666666666667, 'max_error': 2.666666666666667},
        3: {'start': 3, 'error': 0.0, 'max_error': 2.0},
        },
    4: {
        1: {'start': 0, 'error': 7397.2, 'max_error': 7397.2},
        2: {'start': 4, 'error': 0.0, 'max_error': 1852.75},
        3: {'start': 4, 'error': 0.0, 'max_error': 2.666666666666667},
        },
    5: {
        1: {'start': 0, 'error': 11205.333333333334, 'max_error': 11205.333333333334},
        2: {'start': 4, 'error': 0.5, 'max_error': 1852.75},
        3: {'start': 4, 'error': 0.5, 'max_error': 2.666666666666667},
        },
    6: {
        1: {'start': 0, 'error': 13735.714285714286, 'max_error': 13735.714285714286},
        2: {'start': 4, 'error': 2.0, 'max_error': 1852.75},
        3: {'start': 4, 'error': 2.0, 'max_error': 2.666666666666667},
        },
}

这是解释该表的方法。

best_cluster_by_pos_by_clusters[6][3]{'start': 4, 'error': 2.0, 'max_error': 2.666666666666667}的事实意味着从位置0-6的数字的最佳除法是使第三个簇具有在位置4、5、6的数字。平方误差为2.0,最大值为2.666666666666666667。这给了您群集[6, 5, 7],并找到了剩下的部分,我们去了best_cluster_by_pos_by_clusters[3][2](即最好地划分为2个群集,位置3结束),我们同样找到了群集[101, 103, 101]。然后我们剩下的是best_cluster_by_pos_by_clusters[0][1](最佳的1个簇在位置0处结束),它为我们提供了[52]的最后一个簇。

因此,弄清楚如何编写代码以填充该表,然后编写代码以从该表中提取答案,您将拥有一个自底向上的动态编程解决方案。

举例来说,要填写best_cluster_by_pos_by_clusters[3][1],我要做的就是查看best_cluster_by_pos_by_clusters[i][0]的{​​{1}},以查看上一个集群与一个集群的每个划分。当前版本。