我有一段基于大型numpy数组的代码,然后操作另一个数组。由于这是一个非常大的阵列,请您让我知道是否有一种有效的方法可以实现我的目标? (我认为应该通过直接在数组上而不是通过for循环来实现有效的方法。)
谢谢,请在下面找到我的代码:
N = 1000000000
rand = np.random.rand(N)
beta = np.zeros(N)
for i in range(0, N):
if rand[i] < 0.5:
beta[i] = 2.0*rand[i]
else:
beta[i] = 1.0/(2.0*(1.0-rand[i]))
答案 0 :(得分:2)
通过使用Python执行处理,您在这里基本上失去了numpy的效率。 numpy的想法是处理 bulk 中的项目,因为它在C ++中具有执行实际处理工作的高效算法。您可以将numpy的Python结尾更多地视为“接口”。
现在要回答您的问题,我们基本上可以首先将0到2之间的随机数数组乘以2来构成它:
rand = 2.0 * np.random.rand(N)
接下来,我们可以使用类似于条件选择器的np.where(..)
[numpy-doc]:我们在这里传递三个“数组”:第一个是布尔数组,用于编码“条件”的真实性,第二个是在相关条件为true时要填充的值数组,第三个值是在条件为false时要插入的值数组,因此我们可以这样写:
N = 1000000000
rand = 2 * np.random.rand(N)
beta = np.where(rand < 1.0, rand, 1.0 / (2.0 - rand))
答案 1 :(得分:2)
N = 1000000000对我造成了MemoryError
。最小化为100。
您可以使用np.where routine。
在两种情况下,从根本上来说,您都在遍历数组并应用函数。 但是,np.where
使用了一种更快的循环方式(基本上是编译后的代码),而您的“ python”循环被解释了,因此对于大的N来说确实很慢。
这是一个实现示例。
N = 100
rand = np.random.rand(N)
beta = np.where(rand < 0.5, 2.0 * rand, 1.0/(2.0*(1.0-rand))
答案 2 :(得分:1)
正如其他答案所指出的那样,应该(而且可以)几乎总是避免在Python循环中迭代numpy
数组的元素。在大多数情况下,从Python循环到数组操作可以使速度提高约100倍。
但是,如果性能绝对至关重要,那么您通常可以使用Cython来压缩另一个2倍至10倍的因素(以我的经验)。 这是一个示例:
%%cython
cimport numpy as np
import numpy as np
cimport cython
from cython cimport floating
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cpdef np.ndarray[floating, ndim=1] beta(np.ndarray[floating, ndim=1] arr):
cdef:
Py_ssize_t i
Py_ssize_t N = arr.shape[0]
np.ndarray[floating, ndim=1] result = np.zeros(N)
for i in range(N):
if arr[i] < 0.5:
result[i] = 2.0*arr[i]
else:
result[i] = 1.0/(2.0*(1.0-arr[i]))
return result
然后您将其称为beta(rand)
。
如您所见,这使您可以使用原始的循环结构,但现在可以使用有效的类型化本机代码。与np.where
相比,我的速度提高了约2.5倍。
应该注意,在许多情况下,与numpy
中的单行代码相比,这不值得付出额外的精力—但这很可能对性能至关重要。