简体   繁体   English

使用numpy在3D网格上广播点产品

[英]Dot product broadcasting on a 3D grid with numpy

I am trying to get a clue on how to do broadcast a systematic dot product operation on a 10x10x10 3D grid. 我正在尝试获取有关如何在10x10x10 3D网格上广播系统的点积运算的线索。 I formulated the following arrays: 我制定了以下数组:

A.shape=(5,5,10,10,10)
b.shape=(5,10,10,10)

I want to obtain an array like the following 我想获得如下数组

c.shape=(5,10,10,10)

Which so far I obtained through the following code 到目前为止,我是通过以下代码获得的

c=np.sum(A*b,axis=1)

I believe, however, that I should be able to obtain the same result with np.dot or np.tensordot. 但是,我相信我应该能够使用np.dot或np.tensordot获得相同的结果。 I tried my hardest but I cannot manage to obtain an equivalent result. 我尽了最大的努力,但无法获得同等的结果。 Doing so would help me a lot to understand how np.tensordot works, as I will also need to use np.tensorsolve in my work further on. 这样做对我很有帮助,可以理解np.tensordot的工作原理,因为在以后的工作中我还需要使用np.tensorsolve。

We need to keep the last four axes aligned and have those in the output as well except the second axis (axis=1), which is to be sum-reduced. 我们需要保持最后四个轴对齐,并且在输出中也要使它们保持对齐,除了第二个轴(axis = 1)外,第二个轴将被求和。 For such a case np.einsum is the way to go, apart from np.matmul . 对于这样的情况下np.einsum是去除了的方式np.matmul With np.einsum , it would be easier/intuitive like so - 使用np.einsum ,这样会更容易/直观-

c = np.einsum('ijklm,jklm->iklm',A,b)

If the 'dot' dimensions are at the end, matmul will work 如果“点”尺寸在末尾,则matmul将起作用

Comparing 3 methods: 比较3种方法:

In [252]: A=np.arange(5*5*10*10*10).reshape((5,5,10,10,10))
In [253]: B=np.arange(5*10*10*10).reshape((5,10,10,10))

In [254]: C=np.sum(A*B, axis=1)
In [255]: D=np.einsum('ijklm,jklm->iklm',A,B)
In [256]: E = (A.transpose(2,3,4,0,1)@B.transpose(1,2,3,0)[...,None])[...,0].transpose(3,0,1,2)

All the transposes make the arrays into into (....,5,5) and (...,5,1) . 所有的转置使数组变成(....,5,5)(...,5,1)

In [257]: np.allclose(C,D)
Out[257]: True
In [258]: np.allclose(C,E)
Out[258]: True

In [259]: timeit C=np.sum(A*B, axis=1)
124 µs ± 4 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [260]: timeit D=np.einsum('ijklm,jklm->iklm',A,B)
66 µs ± 18.7 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [261]: timeit E = (A.transpose(2,3,4,0,1)@B.transpose(1,2,3,0)[...,None])[...
     ...: ,0].transpose(3,0,1,2)
68.6 µs ± 973 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

tensordot reshapes and transposes the arrays so it can do a simple 2d dot - and then converts back. tensordot重塑并转置数组,以便它可以做一个简单的2d dot -然后转换回去。 The last 3 dimensions are effectively a single 1000 dimension. 最后3个维度实际上是一个1000维度。

In [262]: np.tensordot(A,B,(1,0)).shape
Out[262]: (5, 10, 10, 10, 10, 10, 10)
In [263]: timeit np.tensordot(A,B,(1,0)).shape
74 ms ± 70.1 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

The result is much bigger - a kind of outer product on the non-summing dimensions. 结果要大得多-一种非求和维的外部乘积。 The result is in there, buried as a multidimansional diagonal. 结果在其中,以多维对角线的形式埋藏。

tensordot is effectively: 张量点实际上是:

In [264]: X=(B.reshape(5,1000).T).dot(A.reshape(5,5,1000))
In [265]: X.shape
Out[265]: (1000, 5, 1000)
In [266]: timeit X=(B.reshape(5,1000).T).dot(A.reshape(5,5,1000))
78.9 ms ± 82.6 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM