import numpy as np
a = np.array([[1,2,3], [3,4,5]])
b = np.array([[1,2,3], [1,2,3]])
result = np.array([])
for row1, row2 in a, b:
result = np.append(result, np.dot(row1, row2))
print result
import numpy as np
a=np.array([[1,2,3],[3,4,5]])
b=np.array([[1,2,3],[1,2,3]])
np.sum(a*b, axis=1)
这避免了Python循环并且在以下情况下更快:
def npsumdot(x, y):
return np.sum(x*y, axis=1)
def loopdot(x, y):
result = np.empty((x.shape[0]))
for i in range(x.shape[0]):
result[i] = np.dot(x[i], y[i])
return result
timeit npsumdot(np.random.rand(500000,50),np.random.rand(500000,50))
# 1 loops, best of 3: 861 ms per loop
timeit loopdot(np.random.rand(500000,50),np.random.rand(500000,50))
# 1 loops, best of 3: 1.58 s per loop
In [52]: a
Out[52]:
array([[1, 2, 3],
[3, 4, 5]])
In [53]: b
Out[53]:
array([[1, 2, 3],
[1, 2, 3]])
In [54]: einsum('ij,ij->i', a, b)
Out[54]: array([14, 26])
einsum似乎比inner1d快一些:
In [94]: %timeit inner1d(a,b)
1000000 loops, best of 3: 1.8 us per loop
In [95]: %timeit einsum('ij,ij->i', a, b)
1000000 loops, best of 3: 1.6 us per loop
In [96]: a = random.randn(10, 100)
In [97]: b = random.randn(10, 100)
In [98]: %timeit inner1d(a,b)
100000 loops, best of 3: 2.89 us per loop
In [99]: %timeit einsum('ij,ij->i', a, b)
100000 loops, best of 3: 2.03 us per loop
import numpy as np
a=np.array([[1,2,3],[3,4,5]])
b=np.array([[1,2,3],[1,2,3]])
result=np.empty((2,))
for i in range(2):
result[i] = np.dot(a[i],b[i]))
print result
import numpy as np
from numpy.core.umath_tests import inner1d
a = np.random.randn(100, 1000000) # 800 MB each
b = np.random.randn(100, 1000000) # pretty big.
def loop_dot(a, b):
result = np.empty((a.shape[1],))
for i, (row1, row2) in enumerate(zip(a, b)):
result[i] = np.dot(row1, row2)
%timeit inner1d(a, b)
# 128 ms ± 523 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit np.einsum('ij,ij->i', a, b)
# 121 ms ± 402 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit np.sum(a*b, axis=1)
# 411 ms ± 1.99 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit loop_dot(a, b) # note the function call took negligible time
# 123 ms ± 342 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
5条答案
按热度按时间ie3xauqp1#
简单明了的方法是:
这避免了Python循环并且在以下情况下更快:
vuv7lop32#
查看numpy.einsum了解另一种方法:
einsum
似乎比inner1d
快一些:注:NumPy是不断发展和完善的;上面所示的函数的相对性能可能在过去的几年中发生了变化。2如果性能对你来说很重要,请用你将要使用的NumPy版本运行你自己的测试。
5m1hhzi43#
我尝试了一下,发现
inner1d
是最快的,但是这个函数是内部的,所以更健壮的方法是使用更好的方法是调整你的记忆,使求和发生在第一维,例如,
对于
10 ** 3 <= n <= 10 ** 6
,这是最快的方法,比非转置的方法快两倍,最大值出现在2级缓存达到最大值时,大约为2 * 10 ** 4
。还应注意,转置的
sum
移动比未转置的移动快得多。该地块是用perfplot(我的一个小项目)创建的
lrl1mhuk4#
你最好避免
append
,但是我想不出一个方法来避免python循环。也许是一个自定义的Ufunc?我不认为numpy.vectorize会在这里帮助你。编辑
基于this answer,如果实际问题中的向量是1D,
inner1d
似乎可以工作。xxe27gdn5#
我偶然发现了这个答案,并使用运行在Python 3.5中的Numpy 1.14.3重新验证了结果。尽管我发现对于非常大的矩阵(见下面的例子),除了一个方法之外,所有方法都非常接近,以至于性能差异没有意义,但在我的系统上,上述答案大部分都成立。
对于较小的矩阵,我发现
einsum
是最快的,而且速度快得多,在某些情况下甚至是两倍。我的大型矩阵示例:
所以
einsum
在非常大的矩阵上仍然是最快的,但是快了一点,虽然这看起来是一个统计上显著的(微小的)量!