在编写脚本时,我发现了numpy.random.choice函数。我实现它是因为它比等效的if语句更清晰。但是,在运行脚本后,我意识到它比if语句显着慢。
以下是MWE。第一种方法需要0.0秒,而第二种方法需要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))
答案 0 :(得分:15)
你错了。矢量化操作,或者numpy将不会带来任何好处:
var = numpy.random.choice([-1, 0, 1], size=1000, p=[0.25, 0.5, 0.25])
计时数据:
>>> timeit.timeit('''numpy.random.choice([-1, 0, 1],
... size=1000,
... p=[0.25, 0.5, 0.25])''',
... 'import numpy', number=10000)
2.380380242513752
>>> timeit.timeit('''
... var = []
... for i in xrange(1000):
... tmp = rand.rand()
... if tmp < 0.25:
... var.append(1)
... elif tmp < 0.5:
... var.append(-1)
... else:
... var.append(0)''',
... setup='import numpy.random as rand', number=10000)
5.673041396894519
答案 1 :(得分:1)
我怀疑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
大小,choice
的速度要慢3-4倍,但是如果矢量较大,差异就会消失。
答案 2 :(得分:1)
我花了很长时间才发现由于通过np.random.choice
进行随机密钥采样,我的数据生成器非常慢。
如果需要非均匀分布不需要,那么这是我发现的可行解决方案:
替换
def get_random_key( a_huge_key_list ) :
return np.random.choice( a_huge_key_list )
与
def get_random_key( a_huge_key_list ) :
L = len(a_huge_key_list)
i = np.random.randint(0, L)
return a_huge_key_list[i]
这大大提高了我的速度60倍。
答案 3 :(得分:0)
此解决方案的累积分数提高了约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