如果我改变你的a
,b
那么 numpy 会创建一个二维数组,而不是数组数组:
In [5]: am=np.asarray([np.asarray([1,2,3,0]),np.asarray([2,3,4,5])])
#array([[1, 2, 3, 0],
# [2, 3, 4, 5]])
In [7]: bm=np.asarray([np.asarray([1,2,3,0]),np.asarray([2,3,4,5])])
并做计时:
In [10]: timeit np.multiply(a,b)
100000 loops, best of 3: 7.94 us per loop
In [11]: timeit np.multiply(am,bm)
100000 loops, best of 3: 1.89 us per loop
纯ndarray乘法要快得多。在一种情况下,它可以直接跳到逐元素乘法(在快速C
代码级别);另一方面,它进行通用迭代,使用对象而不是简单的数字。它正在做一些接近 Python 迭代的事情。
事实上,如果我明确地执行那个循环,我会得到接近那个更长的时间
al,bl=a.tolist(), b.tolist()
In [21]: timeit np.array([np.multiply(x,y) for x,y in zip(al,bl)])
100000 loops, best of 3: 8.99 us per loop
现在让我们看看你的“最后一个维度的总和”问题。首先请注意,sum
(or add.reduce
) 尚未扩展为使用这种类型的数组。
In [37]: timeit am.sum(axis=1)
100000 loops, best of 3: 11.5 us per loop
In [38]: timeit [x.sum() for x in a]
10000 loops, best of 3: 21.5 us per loop
的速度优势ndarray sum
没有那么大。 可以通过将其编码为产品(使用or )sum
来加速:dot
np.dot
einsum
In [42]: timeit np.einsum('ij->i',am)
100000 loops, best of 3: 4.79 us per loop
In [50]: ones=np.array([1,1,1,1])
In [51]: timeit np.dot(am,ones)
100000 loops, best of 3: 2.37 us per loop
In [55]: timeit [np.einsum('j->',x) for x in a]
100000 loops, best of 3: 12.3 us per loop
In [64]: c=np.asarray([np.asarray([1,1,1]),np.asarray([1,1,1,1])])
In [65]: timeit [np.dot(x,y) for x,y in zip(a,c)]
100000 loops, best of 3: 8.12 us per loop
因此,虽然可以构造不规则数组(或数组数组),但它们与数组列表相比并没有显着的速度优势。通常,快速numpy
数组操作不适用于作为通用 Python 对象 ( dtype=object
) 的元素。