2

做这个的最好方式是什么?

a = 3x3 array
b = 20x3 array
c = 20x3 array = some_dot_function(a, b) where:
c[0] = np.dot(a, b[0])
c[1] = np.dot(a, b[1])
c[2] = np.dot(a, b[2])
...etc...

我知道这可以通过一个简单的 python 循环或使用 numpy 的 apply_along_axis 来完成,但我想知道是否有任何好的方法可以完全在 numpy 的底层 C 代码中完成这项工作。我查看了 tensordot 和其他一些功能,但没有任何运气。我还尝试了以下方法:

c = np.dot(a, b[:, :, np.newaxis]
#c.shape = (3, 59, 1)

这实际上运行并给出了看起来大致正确的结果,除了结果数组不是 20x3。我可能能够找到一种方法将其重塑为我想要的数组,但我认为必须有一个更简单/更清洁/更清晰的内置方法,我错过了?

4

2 回答 2

7

这给出了(在我看来是什么)正确的结果:

numpy.dot(b, a.T)

这是一些示例输出:

>>> a = numpy.arange(9).reshape(3, 3)
>>> b = numpy.arange(60).reshape(20, 3)
>>> numpy.dot(b, a.T)
array([[   5,   14,   23],
       [  14,   50,   86],
       [  23,   86,  149],
       [  32,  122,  212],
       ....
于 2014-01-31T00:48:18.180 回答
2
import numpy
a = numpy.arange(9).reshape(3,3)
b = numpy.arange(60).reshape(20,3)
c1 = numpy.dot(b, a.T) # as in the answer of senderle
c2 = numpy.einsum('ji,ki->kj',a,b)

并且生成的 c1 和 c2 都与您希望的相同(使用您的 验证c[i] = np.dot(a, b[i])

的优点numpy.einsum是这个技巧'ji,ki->kj'告诉在什么维度上必须做什么也适用于更大的维度。

关于 einsum 的更多解释

例如,如果要执行以下操作:

a = numpy.arange(60.).reshape(3,4,5)
b = numpy.arange(24.).reshape(4,3,2)
d1 = numpy.zeros((5,2))

for i in range(5):
    for j in range(2):
        for k in range(3):
            for n in range(4):
                d1[i,j] += a[k,n,i] * b[n,k,j]

您可以通过以下方式更快地完成相同的操作:

d2 = numpy.einsum('kni,nkj->ij', a, b) 
# the 'kni,nkj->ij' is what you otherwise do with the indices as in 
# d1[i,j] += a[k,n,i] * b[n,k,j]

或者如果您不喜欢这种指定必须发生的事情的方式,您也可以使用 numpy.tensordot代替numpy.einsum,并按如下方式指定轴:

d3 = numpy.tensordot(a,b, axes=([1,0],[0,1])) 

所以这个 einsum 方法非常通用,可用于缩短 for 循环(否则会很慢,如果你在 python 中执行它们),并且对于时髦的张量材料非常有趣

有关更多信息,请参阅http://docs.scipy.org/doc/numpy/reference/generated/numpy.tensordot.htmlhttp://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum .html

于 2014-01-31T10:40:48.557 回答