Python 多维数组的一维向量点积

Python 多维数组的一维向量点积,python,numpy,multidimensional-array,linear-algebra,theano,Python,Numpy,Multidimensional Array,Linear Algebra,Theano,我想计算两个多维数组沿一个维的和积,使用 首先,我将使用numpy精确描述我想要做什么numpy.tensordot和numpy.dot似乎总是做矩阵积,而我实际上是在寻找向量积的成批等价物。给定x和y,我想这样计算z: x = np.random.normal(size=(200, 2, 2, 1000)) y = np.random.normal(size=(200, 2, 2)) # this is how I now approach it: z = np.sum(y[:,:,:,np

我想计算两个多维数组沿一个维的和积,使用

首先,我将使用
numpy
精确描述我想要做什么
numpy.tensordot
numpy.dot
似乎总是做矩阵积,而我实际上是在寻找向量积的成批等价物。给定
x
y
,我想这样计算
z

x = np.random.normal(size=(200, 2, 2, 1000))
y = np.random.normal(size=(200, 2, 2))

# this is how I now approach it:
z = np.sum(y[:,:,:,np.newaxis] * x, axis=1)

# z is of shape (200, 2, 1000)
现在我知道,
numpy.einsum
可能会在这里帮助我,但是我想在Theano中做这个特殊的计算,它没有一个
einsum
等价物。我需要使用
dot
tensordot
,或Theano的专用einsum子集函数
batched\u dot
batched\u tensordot


我希望改变这种做法的原因是绩效;我怀疑使用内置(CUDA)点积比依赖广播、元素积和和更快。

在Theano中,三维和四维张量的维度都不可广播。您必须显式地设置它们。那么Numpy原则就可以很好地发挥作用了。一种方法是使用。要了解有关广播的更多信息,请参阅

其中一个张量有三个维度。因此,首先需要在末尾附加一个单例维度,然后使该维度可广播。这两件事可以通过一个命令来实现-。整个代码如下:

import theano
from theano import tensor as T
import numpy as np

X = T.ftensor4('X')
Y = T.ftensor3('Y')
Y_broadcast = T.shape_padaxis(Y, axis=-1)  # appending extra dimension and making it 
                                           # broadcastable
Z = T.sum((X*Y_broadcast), axis=1)  # element-wise multiplication
f = theano.function([X, Y], Z, allow_input_downcast=True)

# Making sure that it works and gives correct results

x = np.random.normal(size=(3, 2, 2, 4))
y = np.random.normal(size=(3, 2, 2))

theano_result = f(x,y)
numpy_result = np.sum(y[:,:,:,np.newaxis] * x, axis=1)
print np.amax(theano_result - numpy_result)  # prints 2.7e-7 on my system, close enough!

我希望这会有所帮助。

我认为,由于沿第一条轴的轴对齐要求,您可能需要扩展维度和求和,就像您在这里所做的那样。为了完整性起见,einsum解决方案看起来像
z2=numpy.einsum('ijkl,ijk->ikl',x,y);numpy.allclose(z,z2)#正确
。请注意,输出索引中没有
j
(轴1),这是
einsum
的隐式总和。实际上,我发布的示例与Theano中的工作原理几乎完全相同。由于Theano的相对较新版本,可以像在Numpy中一样添加可广播轴:
x[:,:,np.newaxis]
将创建具有第三维可广播轴的NxMx1张量。