正如工作笔记一样,这3个计算也可以写成:
np.einsum(A,[0,1,2],B,[0,2,3],[0,1,3])
np.einsum(M,[0,1,2],v,[0,2],[0,1])
np.einsum(w,[0,1],v,[0,1],[0])
“或者使用Ophion的泛化理论”
np.einsum(A,[Ellipsis,1,2], B, ...)
这应该不难根据输入数组的维度生成
[0,1,..]
列表。
通过将重点放在泛化`einsum`表达式上,我忽略了您试图复制的事实,即`N`个小点积。
np.array([np.dot(i,j) for i,j in zip(a,b)])
值得注意的是,
np.dot
使用快速编译代码,并专注于在数组较大时进行计算。而您的问题是计算许多小的点积之一。
而如果没有定义轴的额外参数,
np.dot
只执行可能的组合中的两个,可以表示为:
np.einsum('i,i', v1, v2)
np.einsum('...ij,...jk->...ik', m1, m2)
“dot”的操作版本将面临相同的限制-没有额外的参数来指定如何组合轴。
还值得注意的是,
tensordot
是如何推广
dot
的:
def tensordot(a, b, axes=2):
....
newshape_a = (-1, N2)
...
newshape_b = (N2, -1)
....
at = a.transpose(newaxes_a).reshape(newshape_a)
bt = b.transpose(newaxes_b).reshape(newshape_b)
res = dot(at, bt)
return res.reshape(olda + oldb)
它可以在多个轴上执行带求和的“点乘”运算。但在转置和重塑完成后,计算就变成了标准的二维数组“点乘”。
这可能被标记为重复问题。人们一直在询问如何进行多个点积。
沿数组轴进行矩阵向量乘法建议使用
numpy.core.umath_tests.matrix_multiply
https://stackoverflow.com/a/24174347/901925中等于:
matrix_multiply(matrices, vectors[..., None])
np.einsum('ijk,ik->ij', matrices, vectors)
< p >
matrix_multiply
的
C
文档注释:
* This implements the function
* out[k, m, p] = sum_n { in1[k, m, n] * in2[k, n, p] }.
来自同一目录下的
inner1d
函数对于
(N,n)
向量执行相同的操作。
inner1d(vector, vector)
np.einsum('ij,ij->i', vector, vector)
两者都是 UFunc,并且可以处理最右边维度的广播。在 numpy/core/test/test_ufunc.py 中,这些函数被用来测试 UFunc 机制。
matrix_multiply(np.ones((4,5,6,2,3)),np.ones((3,2)))
这句话的意思是:“
https://dev59.com/rXLYa4cB1Zd3GeqPXnD6#16704079 表示,这种计算可以使用
*
和 sum 函数来完成,例如:”
(w*v).sum(-1)
(M*v[...,None]).sum(-1)
(A*B.swapaxes(...)).sum(-1)
经过进一步测试,我认为
inner1d
和
matrix_multiply
与您的
dot
和
matrix-matrix
乘积情况相匹配,并且如果添加
[...,None]
到
matrix-vector
情况中,则也匹配。看起来它们比
einsum
版本快2倍(在我的机器和测试数组上)。
https://github.com/numpy/numpy/blob/master/doc/neps/return-of-revenge-of-matmul-pep.rst是关于
numpy
中
@
中缀运算符的讨论。我认为
numpy
开发人员对这个PEP的热情不如Python开发人员高。
'ij,ij...'
字符串不应该很难。还有一种子列表方法可以指定这些索引。 - hpauljN=3
,规则是什么?即两个(3,3)的数组。是'ij,ij->i'还是'jk,ik->ij'还是'jk,kl->jl'? - hpaulj