Python numpy:广播到多个内积和反转

Python numpy:广播到多个内积和反转,python,numpy,matrix-inverse,broadcasting,inner-product,Python,Numpy,Matrix Inverse,Broadcasting,Inner Product,我有数组e,(shapeqbyl)f(shapenbyl)和w(shapenbyl),我想创建一个数组MwhereM[s,I,j]=np.sum(w[s,:]e[I:]e[I:]*e[j],),和一个数组[s,j]=np.sum(w[s,:]*f[s,:]*e[j,:]) 例如,通过在M的元素中循环,这两种方法都很容易做到,但我希望更有效(我的真实数据有大约1M个长度为5k的条目)。对于F,我可以使用F=np.inner(w*F,e)(我验证了它会产生与循环相同的答案).M更难,因此第一步是使用

我有数组
e
,(shape
q
by
l
f
(shape
n
by
l
)和
w
(shape
n
by
l
),我想创建一个数组
M
where
M[s,I,j]=np.sum(w[s,:]e[I:]e[I:]*e[j],
),和一个数组
[s,j]=np.sum(w[s,:]*f[s,:]*e[j,:])

例如,通过在
M
的元素中循环,这两种方法都很容易做到,但我希望更有效(我的真实数据有大约1M个长度为5k的条目)。对于
F
,我可以使用
F=np.inner(w*F,e)
(我验证了它会产生与循环相同的答案).
M
更难,因此第一步是使用列表理解循环通过的维度0,表示
M=np.stack([np.inner(r[:]*e,e)表示r in w])
(我已经验证了这与循环的工作原理相同)。
np.inner()
不接受任何轴参数,因此我不清楚如何告诉数组只在
w
的所有行上广播

最后,我需要使用
M
F
的元素来创建一个矩阵
a
,其中
a[s,I]=np.sum(np.linalg.inv(M[s,:,:,:])[I,:]*F[I,:])
。这看起来也是内积,但进行大量的单个逆运算非常耗时,所以有没有方法计算切片的逆,没有循环

我的阵列中的一些测试值如下所示:

e = array([[-0.9840087 , -0.17812043],
           [ 0.17812043, -0.9840087 ]])

w = array([[  1.12545297e+01,   1.48690140e+02],
           [  7.30718244e+00,   4.07840612e+02],
           [  2.62753065e+02,   2.27085711e+02],
           [  1.53045364e+01,   5.63025281e+02],
           [  8.00555079e+00,   2.16207407e+02],
           [  1.54070190e+01,   1.87213209e+06],
           [  2.71802081e+01,   1.06392902e+02],
           [  3.46300255e+01,   1.29404438e+03],
           [  7.77638140e+00,   4.18759293e+03],
           [  1.12874849e+01,   5.75023379e+02]])

f = array([[ 0.48907404,  0.06111084],
           [-0.21899297, -0.02207311],
           [ 0.58688524,  0.05156326],
           [ 0.57407751,  0.10004592],
           [ 0.94172351,  0.03895357],
           [-0.7489003 , -0.08911183],
           [-0.7043736 , -0.19014227],
           [ 0.58950925,  0.16587887],
           [-0.35557142, -0.14530267],
           [ 0.24548714,  0.03221844]])
转化为

M = np.einsum('sk,ik,jk->sij',w,e,e)

我没有用你的样品测试过这些,但是翻译很简单

对于真正的大型数组,您可能需要将表达式拆分为多个部分。对于4个迭代变量,整个迭代空间可能非常大。但首先看看这些表达式是否适用于中等大小的数组

至于

A[s,i] = np.sum(np.linalg.inv(M[s, :, :])[i, :] * F[i, :])
我看起来像是
np.linalg.inv(M)
工作,执行
s
I x I反转

如果是,那么

 IM = np.linalg.inv(M)
 A = np.einsum('skm,ik,im->si', IM, F)
我猜的更多

同样,维度可能变得太大,但请先尝试将其缩小

通常,建议使用线性方程解决方案,而不是直接求逆,例如

  A = F/M
  A = np.linalg.solve(M, F)

因为你可能想要一个
M@A=F
(@matrix乘积)。但我对这些问题有点生疏。还要检查
tensorsolve
tensorinv
In
m[s,I,j]=np.sum(w[s]*e[I]*e[j])
我看到两边都是
I,j,s
。是
(w[s,k]*e[j,k]*e[j,k]).sum(轴=k)
np.einsum
是一个快速简便的工具,用于做这种乘积之和。
s,i,j
方程几乎是自己写的。
w
f
e
的行是长度
l
向量,因此三者的元素乘积在其唯一的轴上求和有时写起来更清晰
e[j,:]
不仅仅是
e[j]
,即使解释器对待两者都是一样的。
A=np.einsum('skm,ik,im->si',im,F)
有太多索引,但
A=np.linalg.solve(M,F)
生成具有正确尺寸的数组,这是成功的一半。“sij,ij->si”更好吗?不,索引调整会导致操作数再次广播出错
[原始->重新映射]:(50,2,2)->(50,2,2)(50,2)->(50,2)
。但是,对于
np.linalg.solve()
implementation,当
w
无处不在时,该方法产生与
f.dot(e.T)
相同的答案。这是预期的行为,因此我非常确定它是有效的。
 IM = np.linalg.inv(M)
 A = np.einsum('skm,ik,im->si', IM, F)
  A = F/M
  A = np.linalg.solve(M, F)