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
,(shapeq
byl
)f
(shapen
byl
)和w
(shapen
byl
),我想创建一个数组M
whereM[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
Inm[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)