[英]Take dot product of first and middle entry, second and middle+1 entries until middle-1 and last entry python/numpy
Sorry for the vague sounding question, I really couldn't think of a better way to describe what I am trying to do 对于模糊的声音问题我很抱歉,我真的想不出更好的方式来描述我想要做的事情
I have a 81x990000x3 array and for each of the 81 entries; 我有一个81x990000x3阵列和81个条目中的每一个; I need to sum the dot product of the first entry with the 495000th entry (the middle), the second with the 495001st entry and so on until the 494999th entry with the last entry. 我需要将第一个条目的点积与第495000个条目(中间)相加,第二个条目与495001条目相加,依此类推,直到最后一个条目的494999条目。
Right now I have it being done in a loop like this: 现在我在这样的循环中完成它:
import numpy as np
summed = 0
Nt = 990000
i = Nt/2
for k in xrange(81):
for j in xrange(Nt-i-1):
vec1 = array[k][j]
vec2 = array[k][j+i]
summed += np.dot(vec1,vec2)
This is obviously quite slow, however, since it is going through 81x990000 = 80190000 entries. 然而,这显然是非常缓慢的,因为它经历了81x990000 = 80190000个条目。
Is there a more numpythonic way to do this? 是否有更多的numpythonic方式来做到这一点?
NB reading your question, I think you want your second nested loop to be for j in xrange(Nt-i):
since xrange
excludes the upper limit. NB读你的问题,我想你希望你的第二个嵌套循环是for j in xrange(Nt-i):
因为xrange
排除了上限。
I think you can what you want with einsum
: 我想你可以用einsum
你想要的einsum
:
import numpy as np
summed = 0
dim1 = 2 # this is 81 in your case
dim2 = 4 # this is 990000 in your case
array = np.random.random(size=(dim1, dim2, 3))
Nt = dim2
i = Nt // 2
for k in xrange(dim1):
summed = 0
for j in xrange(dim2-i):
vec1 = array[k][j]
vec2 = array[k][j+i]
summed += np.dot(vec1,vec2)
print summed
print '='*70
for k in xrange(dim1):
summed = np.einsum('ij,ij', array[k][:Nt//2], array[k][Nt//2:])
print summed
eg 例如
2.0480375425
1.89065215839
======================================================================
2.0480375425
1.89065215839
Doubtless you can even remove the outer loop as well (though in your case it probably won't speed things up much): 毫无疑问,你甚至可以删除外部循环(虽然在你的情况下,它可能不会加快速度):
np.einsum('kij,kij->k', array[:,:Nt//2,:], array[:,Nt//2:,:])
gives 给
[ 2.0480375425 1.89065215839]
Since you want to go from 0
until the 494999th
entry, I think the code needs a slight edit for the jth
iterations and has to be for j in xrange(Nt-i)
instead. 由于你想要从0
到494999th
条目,我认为代码需要对jth
次迭代进行轻微编辑,而必须for j in xrange(Nt-i)
。 Now, back to the problem at hand, you are basically cutting each 3D slice
into two halves and doing elementwise multiplication between them and thereafter summing all elements. 现在,回到手头的问题,你基本上将每个3D slice
成两半,然后在它们之间进行元素乘法,然后对所有元素求和。 Here, by slice I mean a 2D array formed by axis =(1,2)
. 这里,切片I是指由axis =(1,2)
形成的2D阵列。
To solve our case, you can simulate - 要解决我们的情况,你可以模拟 -
.reshape()
. 切入两半: .reshape()
。 .prod()
. 元素乘法在相应的元素之间: .prod()
。 .sum()
. 用以下内容对所有元素求和: .sum()
。 Thus, the implementation would look something like this - 因此,实现看起来像这样 -
m,n,r = array.shape
out = array.reshape(m,2,-1,r).prod(1).sum()
Runtime tests and verify output - 运行时测试并验证输出 -
Define functions : 定义功能:
def vectorized_app(array):
m,n,r = array.shape
return array.reshape(m,2,-1,r).prod(1).sum()
def org_app(array):
m,n,r = array.shape
Nt = n
i = Nt/2
summed = 0
for k in xrange(m):
for j in xrange(Nt-i):
vec1 = array[k][j]
vec2 = array[k][j+i]
summed += np.dot(vec1,vec2)
return summed
Runtimes : 运行时:
In [94]: array = np.random.rand(81,9900,3)
In [95]: org_app(array)
Out[95]: 300450.24128635536
In [96]: vectorized_app(array)
Out[96]: 300450.24128635362
In [97]: %timeit org_app(array)
1 loops, best of 3: 1.29 s per loop
In [98]: %timeit vectorized_app(array)
100 loops, best of 3: 16.1 ms per loop
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.