为什么numpy.random.choice如此缓慢?

2024-06-14 02:53:33 发布

您现在位置:Python中文网/ 问答频道 /正文

在编写脚本时,我发现了numpy.random.choice函数。我实现它是因为它比等价的if语句干净得多。但是,在运行脚本之后,我意识到它比if语句慢得多。

以下是MWE。第一种方法需要0.0秒,而第二种方法需要7.2秒。如果放大i循环,您将看到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))

Tags: inimportnumpyforiftimevaras
3条回答

我花了很长时间才发现,由于通过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倍

我怀疑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倍,但是对于较大的载体,差异开始消失。

你用错了。使操作矢量化,否则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

相关问题 更多 >