Python 如何在numpy中沿特定维度获取点积?
我有两个数组。一个是n乘以p,另一个是d乘以p乘以r。我希望我的输出是d乘以n乘以r,这在我构造下面的张量B时很容易实现。但是,我希望在不使用循环的情况下执行此操作Python 如何在numpy中沿特定维度获取点积?,python,numpy,multidimensional-array,linear-algebra,numpy-ndarray,Python,Numpy,Multidimensional Array,Linear Algebra,Numpy Ndarray,我有两个数组。一个是n乘以p,另一个是d乘以p乘以r。我希望我的输出是d乘以n乘以r,这在我构造下面的张量B时很容易实现。但是,我希望在不使用循环的情况下执行此操作 import numpy X = numpy.array([[1,2,3],[3,4,5],[5,6,7],[7,8,9]]) # n x p betas = numpy.array([[[1,2],[1,2],[1,2]], [[5,6],[5,6],[5,6]]]) # d x p x r print X.shape pri
import numpy
X = numpy.array([[1,2,3],[3,4,5],[5,6,7],[7,8,9]]) # n x p
betas = numpy.array([[[1,2],[1,2],[1,2]], [[5,6],[5,6],[5,6]]]) # d x p x r
print X.shape
print betas.shape
B = numpy.zeros((betas.shape[0],X.shape[0],betas.shape[2]))
print B.shape
for i in range(B.shape[0]):
B[i,:,:] = numpy.dot(X, betas[i])
print "B",B
C = numpy.tensordot(X, betas, axes=([1],[0]))
print C.shape
我试过各种方法让C和B匹配,但到目前为止我都没有成功。有没有一种方法不需要调用重塑?我们可以使用,然后需要置换轴-
B = np.tensordot(betas, X, axes=(1,1)).swapaxes(1,2)
# Or np.tensordot(X, betas, axes=(1,1)).swapaxes(0,1)
.我们可以使用,然后需要排列轴-
B = np.tensordot(betas, X, axes=(1,1)).swapaxes(1,2)
# Or np.tensordot(X, betas, axes=(1,1)).swapaxes(0,1)
.由于点规则是“A的最后一个,B的第二个到最后一个”,您可以执行X.dotbetas并获得一个n、d、r数组,该数组在共享的p维度上求和。然后你只需要一个转置就可以得到d,n,r
In [200]: X.dot(betas).transpose(1,0,2)
Out[200]:
array([[[ 6, 12],
[ 12, 24],
[ 18, 36],
[ 24, 48]],
[[ 30, 36],
[ 60, 72],
[ 90, 108],
[120, 144]]])
我们也可以直接从尺寸规格中编写einsum版本:
np.einsum('np,dpr->dnr', X,betas)
matmul也是,这在最后两个轴上都有点,而d则在骑行时出现
X@betas
如果任一参数为N-D,N>2,则将其视为
位于最后两个索引中的矩阵,并相应地广播。
由于点规则是“A的最后一个,B的第二个到最后一个”,您可以执行X.dotbetas并获得一个n、d、r数组,该数组在共享p维度上求和。然后你只需要一个转置就可以得到d,n,r
In [200]: X.dot(betas).transpose(1,0,2)
Out[200]:
array([[[ 6, 12],
[ 12, 24],
[ 18, 36],
[ 24, 48]],
[[ 30, 36],
[ 60, 72],
[ 90, 108],
[120, 144]]])
我们也可以直接从尺寸规格中编写einsum版本:
np.einsum('np,dpr->dnr', X,betas)
matmul也是,这在最后两个轴上都有点,而d则在骑行时出现
X@betas
如果任一参数为N-D,N>2,则将其视为
位于最后两个索引中的矩阵,并相应地广播。
这里是另一种使用的方法,它还可以根据您的请求返回视图,最重要的是比这种方法快4倍多,特别是对于小型阵列。但是,对于相当大的阵列,它比普通阵列快得多。见下面的计时
In [108]: X.shape
Out[108]: (4, 3)
In [109]: betas.shape
Out[109]: (2, 3, 2)
# use `np.dot` and roll the second axis to first position
In [110]: dot_prod = np.rollaxis(np.dot(X, betas), 1)
In [111]: dot_prod.shape
Out[111]: (2, 4, 2)
# @Divakar's approach
In [113]: B = np.tensordot(betas, X, axes=(1,1)).swapaxes(1,2)
# sanity check :)
In [115]: np.all(np.equal(dot_prod, B))
Out[115]: True
现在,两种方法的性能:
对于小型阵列,其速度比
对于相当大的阵列,比
这里是另一种使用的方法,它还可以根据您的请求返回视图,最重要的是比这种方法快4倍多,特别是对于小型阵列。但是,对于相当大的阵列,它比普通阵列快得多。见下面的计时
In [108]: X.shape
Out[108]: (4, 3)
In [109]: betas.shape
Out[109]: (2, 3, 2)
# use `np.dot` and roll the second axis to first position
In [110]: dot_prod = np.rollaxis(np.dot(X, betas), 1)
In [111]: dot_prod.shape
Out[111]: (2, 4, 2)
# @Divakar's approach
In [113]: B = np.tensordot(betas, X, axes=(1,1)).swapaxes(1,2)
# sanity check :)
In [115]: np.all(np.equal(dot_prod, B))
Out[115]: True
现在,两种方法的性能:
对于小型阵列,其速度比
对于相当大的阵列,比
它返回一个视图,而不是一个新数组!太好了。对于较大的阵列,tensordot是超高速的。。但对于小型阵列,np.dot比tensordot快4倍。。不知道为什么会这样case@kmario23有关讨论,请参见此处,它将返回一个视图,而不是一个新数组!太好了。对于较大的阵列,tensordot是超高速的。。但对于小型阵列,np.dot比tensordot快4倍。。不知道为什么会这样case@kmario23有关讨论,请参见此处-参见我的时间安排。。np.dot对于小型阵列比tensordot更快,但对于大型阵列则相反。不知道为什么。有什么想法吗?Tensordot使用圆点,只是按摩输入和结果以适应重塑和转置。参见我的计时。。np.dot对于小型阵列比tensordot更快,但对于大型阵列则相反。不知道为什么。有什么想法吗?Tensordot使用点,只是通过调整输入和结果来适应重塑和转置。一旦使用Tensordot完成初始设置开销,它应该比np.dot版本-np.rollaxisnp.dotX,betas,1更快。所以,它不必是相当大的数组。因此,hpaulj认为np.tensordot使用np.dot。我想我必须检查一下代码才能很好地掌握发生了什么。。。我真的希望NumPy开发者尽早开始实施对GPU的支持一旦使用tensordot克服了初始设置开销,它应该比np.dot版本更快—np.rollaxisnp.dotX,betas,1。所以,它不必是相当大的数组。因此,hpaulj认为np.tensordot使用np.dot。我想我必须检查一下代码才能很好地掌握发生了什么。。。我真的希望NumPy开发者尽早开始实施对GPU的支持