是否有一种使用numpy计算kxnxn矩阵的逆的快速方法(在每个k切片计算逆值)?换句话说,有没有办法矢量化以下代码:
>>>from numpy.linalg import inv
>>>a-random(4*2*2).reshape(4,2,2)
>>>b=a.copy()
>>>for k in range(len(a)):
>>> b[k,:,:] = inv(a[k,:,:])
答案 0 :(得分:3)
首先要做的是反过来。我查看了np.linalg.tensorinv
和np.linalg.tensorsolve
。
我认为遗憾的是tensorinv
不会给你你想要的东西。它需要数组为“方形”。这排除了你想要做的事情,因为它们对square的定义是np.prod(a[:i]) == np.prod(a[i:])
,其中i
是0,1或2(一般是数组的一个轴);这可以作为ind
的第三个参数tensorinv
给出。这意味着如果你有一个长度为M的NxN矩阵的一般数组,你需要有例如(对于i = 1)NxN == NxM,这在一般情况下是不正确的(在您的示例中它实际上是正确的,但无论如何它都没有给出正确答案)。
现在,tensorsolve
可能会有所作为。然而,这将涉及a
矩阵数组的一些繁重的构造工作,然后作为tensorsolve
的第一个参数传递。因为我们希望b
成为“矩阵阵列方程”a*b = 1
的解决方案(其中1
是一个标识矩阵数组),而1
将具有相同的形状为a
和b
,我们不能简单地将您在上面定义的a
作为tensorsolve
的第一个参数。相反,它需要是一个形状(M,N,N,M,N,N)或(M,N,N,N,M,N)或(M,N,N,N,N,M)的阵列)。这是必要的,因为tensorsolve
将在最后三个轴上乘以b
并对它们求和,以便结果(函数的第二个参数)再次成形(M,N,N) )。
其次,关于点积(你的标题表明这也是你问题的一部分)。这是非常可行的。两个选项。
首先:this blog post by James Hensman提供了一些很好的建议。
第二:我个人更喜欢更清楚地使用np.einsum
。 E.g:
a=np.random.random((7,2,2))
b=np.random.random((7,2,2))
np.einsum('ijk,ikl->ijl', a,b)
这将矩阵乘以数组a
和b
中的所有7个“矩阵”。它似乎比上面的博客文章中的数组方法慢了约2倍,但它仍然比使用for循环快70倍,就像在你的例子中一样。事实上,对于较大的数组(例如10000 5x5矩阵),einsum
方法似乎稍微快一点(不确定原因)。
希望有所帮助。