9

サイズのnumpy配列があります

arr.size = (200, 600, 20). 

scipy.stats.kendalltau最後の 2 つの次元のすべてのペアごとの組み合わせを計算したいと思います。例えば:

kendalltau(arr[:, 0, 0], arr[:, 1, 0])
kendalltau(arr[:, 0, 0], arr[:, 1, 1])
kendalltau(arr[:, 0, 0], arr[:, 1, 2])
...
kendalltau(arr[:, 0, 0], arr[:, 2, 0])
kendalltau(arr[:, 0, 0], arr[:, 2, 1])
kendalltau(arr[:, 0, 0], arr[:, 2, 2])
...
...
kendalltau(arr[:, 598, 20], arr[:, 599, 20])

arr[:, i, xi]arr[:, j, xj]i < j、のすべての組み合わせをカバーするようにxi in [0,20)xj in [0, 20)ます。これは(600 choose 2) * 400個別の計算ですが、0.002 s私のマシンではそれぞれに時間がかかるため、マルチプロセッシング モジュールでは 1 日以上かかることはありません。

i<jこれらの列を (で)反復処理する最良の方法は何ですか? 私は次のようなことを避けるべきだと思います

for i in range(600):
    for j in range(i+1, 600):
        for xi in range(20):
            for xj in range(20):

これを行う最もnumpythonicな方法は何ですか?

編集: Kendall Tauは質問にとってそれほど重要ではないため、タイトルを変更しました. 次のようなこともできることに気づきました

import itertools as it
for i, j in it.combinations(xrange(600), 2):
    for xi, xj in product(xrange(20), xrange(20)):

しかし、numpy を使用した、より優れた、よりベクトル化された方法が必要です。

4

2 に答える 2

14

このようなものをベクトル化する一般的な方法は、ブロードキャストを使用して、集合とそれ自体のデカルト積を作成することです。あなたの場合arr、 shape の配列がある(200, 600, 20)ので、それから 2 つのビューを取得します。

arr_x = arr[:, :, np.newaxis, np.newaxis, :] # shape (200, 600, 1, 1, 20)
arr_y = arr[np.newaxis, np.newaxis, :, :, :] # shape (1, 1, 200, 600, 20)

上記の 2 行はわかりやすくするために展開されていますが、通常は次のように記述します。

arr_x = arr[:, :, None, None]
arr_y = arr

最後の次元以外のすべてでブロードキャストを行ったベクトル化された関数 がある場合f、次のようにすることができます。

out = f(arr[:, :, None, None], arr)

そして、値を保持するoutshape の配列になります。たとえば、ペアワイズ内積をすべて計算したい場合は、次のようにします。(200, 600, 200, 600)out[i, j, k, l]f(arr[i, j], arr[k, l])

from numpy.core.umath_tests import inner1d

out = inner1d(arr[:, :, None, None], arr)

残念ながらscipy.stats.kendalltau、このようにベクトル化されていません。ドキュメントによると

「配列が 1 次元でない場合は、1 次元にフラット化されます。」

したがって、このように進めることはできず、Python のネストされたループを実行することになります。明示的に書き出すitertoolsか、np.vectorize. Python 変数の反復と、反復ステップごとに Python 関数があるため、どちらもコストのかかるアクションであるため、これは遅くなります。

ベクトル化された方法を使用できる場合、明らかな欠点があることに注意してください。関数が可換である場合、つまり の場合f(a, b) == f(b, a)、必要な計算が 2 倍になります。実際の計算のコストにもよりますが、Python ループや関数呼び出しがないことによる速度の向上によって相殺されることがよくあります。

于 2013-08-09T21:18:08.357 に答える
0

再帰を使用したくない場合は、通常、itertools.combinations を使用する必要があります。 これによりコードの実行が遅くなる特定の理由 (afaik) はありません。計算集約的な部分は、まだ numpy によって処理されています。Itertools には読みやすさという利点もあります。

于 2013-08-09T20:39:21.030 に答える