4

約12列と1000行以上の2D numpy配列があり、各セルには1から5までの数字が含まれています.1と2が-1ポイントと4を生成するポイントシステムに従って、列の最適な6倍を探しています5 は +1 を与えます。

たとえば、特定の 6 組の行に [1, 4, 5, 3, 4, 3] が含まれる場合、3*1 + 1*(-1) = 2 であるため、この行のポイントは +2 になります。行は [1, 2, 2, 3, 3, 3] で、-3 ポイントである必要があります。

最初はストレート フォワード ループ ソリューションを試しましたが、比較する列の組み合わせが 665 280 通りあり、最適な 5 倍、4 倍などを検索する必要がある場合、ループが永遠に続くことに気付きました。

私の問題を解決するためのよりスマートな方法はありますか?

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次に、列の選択 (6 倍)のスコアを示します。

最後にmax、最高のスコアを持つ 6 つ組を選択するために使用します。

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各行に最適な 6 つの列が含まれます。

于 2012-09-05T15:47:58.370 に答える
0

上記の unutbu の長い回答を拡張すると、マスクされたスコアの配列を自動的に生成することができます。値のスコアはループを通過するたびに一貫しているため、各値のスコアは 1 回だけ計算する必要があります。スコアが適用される前と後に、例の 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 に答える