4

我有一个 2D numpy 数组,大约有 12 列和 1000+ 行,每个单元格包含一个从 1 到 5 的数字。我正在根据我的点系统搜索最佳的六元组,其中 1 和 2 生成 -1 点和 4 5 给出 +1。

例如,如果某个六元组中的一行包含 [1, 4, 5, 3, 4, 3],则该行的点应该是 +2,因为 3*1 + 1*(-1) = 2。行可能是 [1, 2, 2, 3, 3, 3] 并且应该是 -3 点。

起初,我尝试了一个海峡正向循环解决方案,但我意识到有 665 280 个可能的列组合要比较,当我还需要搜索最佳的五元组、四元组等时,循环将永远持续下去。

是否有更聪明的 numpy 方式来解决我的问题?

4

3 回答 3

1
import numpy as np
import itertools

N_rows = 10
arr = np.random.random_integers(5, size=(N_rows,12))
x = np.array([0,-1,-1,0,1,1])
y = x[arr]

print(y)

score, best_sextuple = max((y[:,cols].sum(), cols)
                           for cols in itertools.combinations(range(12),6))
print('''\
score: {s}
sextuple: {c}
'''.format(s = score, c = best_sextuple))

产量,例如,

score: 6
sextuple: (0, 1, 5, 8, 10, 11)

说明

首先,让我们生成一个随机示例,有 12 列和 10 行:

N_rows = 10
arr = np.random.random_integers(5, size=(N_rows,12))

现在我们可以使用 numpy 索引将arr1,2,...,5 中的数字转换为值 -1,0,1(根据您的评分系统):

x = np.array([0,-1,-1,0,1,1])
y = x[arr]

接下来,让我们使用itertools.combinations来生成 6 列的所有可能组合:

for cols in itertools.combinations(range(12),6)

y[:,cols].sum()

然后给出 的分数cols,一个列的选择(六元组)。

最后,用于max挑选得分最高的六元组:

score, best_sextuple = max((y[:,cols].sum(), cols)
                           for cols in itertools.combinations(range(12),6))
于 2012-09-05T15:18:33.627 回答
1
import numpy

A = numpy.random.randint(1, 6, size=(1000, 12))
points = -1*(A == 1) + -1*(A == 2) + 1*(A == 4) + 1*(A == 5)
columnsums = numpy.sum(points, 0)

def best6(row):
    return numpy.argsort(row)[-6:]

bestcolumns = best6(columnsums)
allbestcolumns = map(best6, points)

bestcolumns现在将包含按升序排列的最佳 6 列。通过类似的逻辑,allbestcolumns每行将包含最好的六列。

于 2012-09-05T15:47:58.370 回答
0

扩展上面 unutbu 更长的答案,可以自动生成掩码的分数数组。由于您的值分数在每次循环中都是一致的,因此每个值的分数只需要计算一次。这是在应用分数之前和之后在示例 6x10 数组上执行此操作的稍微不优雅的方法。

>>> import numpy
>>> values = numpy.random.randint(6, size=(6,10))
>>> values
array([[4, 5, 1, 2, 1, 4, 0, 1, 0, 4],
       [2, 5, 2, 2, 3, 1, 3, 5, 3, 1],
       [3, 3, 5, 4, 2, 1, 4, 0, 0, 1],
       [2, 4, 0, 0, 4, 1, 4, 0, 1, 0],
       [0, 4, 1, 2, 0, 3, 3, 5, 0, 1],
       [2, 3, 3, 4, 0, 1, 1, 1, 3, 2]])
>>> b = values.copy()
>>> b[ b<3 ] = -1

>>> b[ b==3 ] = 0
>>> b[ b>3 ] = 1
>>> b
array([[ 1,  1, -1, -1, -1,  1, -1, -1, -1,  1],
       [-1,  1, -1, -1,  0, -1,  0,  1,  0, -1],
       [ 0,  0,  1,  1, -1, -1,  1, -1, -1, -1],
       [-1,  1, -1, -1,  1, -1,  1, -1, -1, -1],
       [-1,  1, -1, -1, -1,  0,  0,  1, -1, -1],
       [-1,  0,  0,  1, -1, -1, -1, -1,  0, -1]])

顺便说一句,这个线程声称直接在 numpy 中创建组合将产生比 itertools 快 5 倍的性能,尽管可能会牺牲一些可读性。

于 2012-09-05T15:25:54.497 回答