11

スクリプトを書いているときに、numpy.random.choice 関数を発見しました。同等の if ステートメントよりもはるかにクリーンだったので、実装しました。ただし、スクリプトを実行した後、if ステートメントよりも大幅に遅いことに気付きました。

以下は MWE です。最初の方法は 0.0 秒、2 番目の方法は 7.2 秒かかります。iループをスケールアップすると、random.choice がどれだけ速く減速するかがわかります。

random.choice が非常に遅い理由について誰かコメントできますか?

import numpy as np
import numpy.random as rand
import time as tm

#-------------------------------------------------------------------------------

tStart = tm.time()
for i in xrange(100):
    for j in xrange(1000):
        tmp = rand.rand()
        if tmp < 0.25:
            var = 1
        elif tmp < 0.5:
            var = -1
print('Time: %.1f s' %(tm.time() - tStart))

#-------------------------------------------------------------------------------

tStart = tm.time()
for i in xrange(100):
    for j in xrange(1000):
        var = rand.choice([-1, 0, 1], p = [0.25, 0.5, 0.25])
print('Time: %.1f s' %(tm.time() - tStart))
4

5 に答える 5

4

累積スコアを使用したこのソリューションは、約 25 倍高速です。

def choice(options,probs):
    x = np.random.rand()
    cum = 0
    for i,p in enumerate(probs):
        cum += p
        if x < cum:
            break
    return options[i]


options = ['a','b','c','d']
probs = [0.2,0.6,0.15,0.05]
runs = 100000


now = time.time()
temp = []
for i in range(runs):
    op = choice(options,probs)
    temp.append(op)
temp = Counter(temp)
for op,x in temp.items():
    print(op,x/runs)
print(time.time()-now)

print("")
now = time.time()
temp = []
for i in range(runs):
    op = np.random.choice(options,p = probs)
    temp.append(op)
temp = Counter(temp)
for op,x in temp.items():
    print(op,x/runs)
print(time.time()-now)

それを実行すると、次のようになります。

b 0.59891
a 0.20121
c 0.15007
d 0.04981
0.16232800483703613

b 0.5996
a 0.20138
c 0.14856
d 0.05046
3.8451428413391113
于 2019-09-25T15:34:38.263 に答える
2

の一般性np.random.choiceが速度を低下させていると思われます。大きなサンプルよりも小さなサンプルの場合はさらに遅くなります。

ifバージョンの大まかなベクトル化は次のとおりです。

def foo(n):
    x = np.random.rand(n)
    var = np.zeros(n)
    var[x<.25] = -1
    var[x>.75] = 1
    return var

実行すると、次のipythonようになります。

timeit np.random.choice([-1,0,1],size=1000,p=[.25,.5,.25])
1000 loops, best of 3: 293 us per loop

timeit foo(1000)
10000 loops, best of 3: 83.4 us per loop

timeit np.random.choice([-1,0,1],size=100000,p=[.25,.5,.25])
100 loops, best of 3: 11 ms per loop

timeit foo(100000)
100 loops, best of 3: 8.12 ms per loop

そのため、1000サイズについては 3 ~ 4 倍choice遅くなりますが、ベクトルが大きくなると、差がなくなり始めます。

于 2013-09-05T06:45:42.033 に答える