我正在完成教科书中的练习,并在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.666
和def 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
,以使平方误差之和最小。
答案 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}},以查看上一个集群与一个集群的每个划分。当前版本。