我想用生成的值填充一个numpy数组。这些值由生成器函数生成。数组长度不是太长,通常小于100,但是此数组会生成很多次,因此我想知道是否可以通过使用一些numpy来优化它。
到目前为止,我已经可以使用香草python了:
def generate():
return generated_data
array = np.asarray([generate() for _ in range(array_length)])
我也尝试使用np.full(shape, fill_value)
:
np.full((array_length, generated_data_size), generate())
但这仅调用generate()
函数一次,而不是对数组中的每个索引调用一次。
我也尝试过np.vectorize()
,但是我无法使其生成适当形状的数组。
答案 0 :(得分:2)
另一种选择是通过ufunc
函数创建一个generate
:
gen_array = np.frompyfunc(generate, 0, 1) # takes 0 args, returns 1
array = gen_array(np.empty(array_length))
对我来说,这比Sigve's answer中的“需要速度”版本要快。
答案 1 :(得分:1)
List comprehension或map function可能都是适合您的解决方案:
from random import random
import numpy as np
np.array(list(map(lambda idx: random(), range(10))))
np.array([random() for idx in range(10)])
也许预先分配内存将节省一两秒钟(?)
array = np.empty(10)
for idx in range(10):
array[idx] = random()
有关更好的解决方案,请参见Nathan's answer。
可以使用numpy对函数进行“向量化”:
def rnd(x):
return random()
fun = np.vectorize(rnd)
array = fun(range(10))
答案 2 :(得分:1)
NumPy无法做任何事情来加快重复调用未设计为与NumPy进行交互的功能的过程。
“花哨的numpy用法”用于优化此方法是手动重写generate
函数以使用NumPy操作生成输出的整个数组,而不是仅支持单个值。这就是NumPy的工作方式,以及NumPy 必须的工作方式。任何涉及为每个数组单元反复调用Python函数的解决方案都将受到Python开销的限制。 NumPy只能加速NumPy中实际发生的工作。
如果NumPy提供的操作过于局限,无法根据其重写generate
,则可以使用Cython重写generate
或在其上使用@numba.jit
。这些主要用于涉及从一个循环迭代到下一个循环的复杂依赖关系的计算。它们无法帮助您解决无法重写的外部依赖项。
如果您不能重写generate
,则您可以做的就是尝试优化将返回值放入数组的过程。根据数组大小,您可以通过重用单个数组对象来节省一些时间:
In [32]: %timeit x = numpy.array([random.random() for _ in range(10)])
The slowest run took 5.13 times longer than the fastest. This could mean that an
intermediate result is being cached.
100000 loops, best of 5: 5.44 µs per loop
In [33]: %%timeit x = numpy.empty(10)
....: for i in range(10):
....: x[i] = random.random()
....:
The slowest run took 4.26 times longer than the fastest. This could mean that an
intermediate result is being cached.
100000 loops, best of 5: 2.88 µs per loop
但是对于更大的阵列,好处就消失了:
In [34]: %timeit x = numpy.array([random.random() for _ in range(100)])
10000 loops, best of 5: 21.9 µs per loop
In [35]: %%timeit x = numpy.empty(100)
....: for i in range(100):
....: x[i] = random.random()
....:
10000 loops, best of 5: 22.8 µs per loop