我想用n维m*m矩阵堆栈乘以n维向量堆栈(长度m),这样得到的m*n数组包含第n项中矩阵和向量的点乘结果:
vec1=np.array([0,0.5,1,0.5]); vec2=np.array([2,0.5,1,0.5])
vec=np.transpose(n.stack((vec1,vec2)))
mat = np.moveaxis(n.array([[[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3]],[[-1,2.,0,1.],[0,0,-1,2.],[0,1,-1,2.],[1,0.1,1,1]]]),0,2)
outvec=np.zeros((4,2))
for i in range(2):
outvec[:,i]=np.dot(mat[:,:,i],vec[:,i])
受这篇文章Element wise dot product of matrices and vectors的启发,我尝试了einsum中所有不同的索引组合扰动,并发现
^{pr2}$给出正确的结果。在
不幸的是,我真的不明白这一点-我假设我重复'ijk,jk'部分中的条目k意味着我乘以k并求和。我试图阅读文档https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.einsum.html,但我仍然不明白。在
(我之前的尝试包括
np.einsum('ijk,il->ik', mat, vec)
我甚至不知道这意味着什么。当我放弃索引l时,它会发生什么变化?)在
提前谢谢!在
einsum
很简单(当你玩了一段时间的索引排列时,就是…)。在让我们来做一些简单的事情,一个三层的2×2矩阵和一个2×,数组的三层堆栈
我们需要知道我们要用
^{pr2}$einsum
来计算什么我们做了什么?我们有一个索引
i
,当我们在其中一个堆叠矩阵与其中一个堆叠向量(两者都以i
为索引)之间执行点积时,该索引是固定的,并且单个输出行表示对堆叠矩阵的最后一个索引和堆叠向量的唯一索引的求和。在这很容易在
einsum
指令中编码i
索引来指定矩阵、向量和输出k
j
因此
我希望我关于如何正确执行指令的讨论是清楚、正确和有用的。在
阅读Einstein summation notation。在
基本上,规则是:
没有
->
使用
->
例如,对于形状相同的矩阵}:
A
和{
^{pr2}$stack
函数的一个优点是我们可以指定一个轴,跳过转置:为什么}的混合?
np.
和{NameError: name 'n' is not defined
。那种事差点把我送走。在在循环中,}。在
i
轴(大小2)的位置在所有3个数组中都是最后一个。只留下一个轴给vec
,我们将其称为j
。它与最后一个(紧挨着i
的mat
)配对。k
从mat
转移到{通常,}被描述为(n,k),结果是(m,k)
einsum
字符串会自己写入。例如,mat
被描述为(m,n,k),而{在本例中,只有
j
维被求和-它出现在左边,但在右边。最后一个维度,i
在我的符号中,没有求和,因为if出现在两边,就像在迭代中一样。我认为这是“顺其自然”。它不是dot
产品的积极组成部分。在实际上,你是在最后一个维度上堆积,尺寸2。通常我们把第一个放在第一个上,但是你把两者都换过来放最后一个。在
您的“失败”尝试运行,并且可以复制为:
j
和l
维度没有出现在右侧,因此它们被相加。它们可以在相乘之前求和,因为它们只出现在一个项中。我添加了None
以启用广播(将ik
与i
相乘)。在如果在第一个上堆叠,并为
vec
(2,4,1)添加一个维度,那么它将使用一个(2,4,4)matmatmul
。mat @ vec[...,None]
。在相关问题 更多 >
编程相关推荐