Python中的快速逆和转置矩阵

时间:2014-02-17 11:44:23

标签: python numpy transpose matrix-inverse

我有一个形状为A的大型(n, n, 3, 3)矩阵n约为5000。现在我想找到矩阵A的反转和转置:

import numpy as np
A = np.random.rand(1000, 1000, 3, 3)
identity = np.identity(3, dtype=A.dtype)
Ainv = np.zeros_like(A)
Atrans = np.zeros_like(A)
for i in range(1000):
    for j in range(1000):
        Ainv[i, j] = np.linalg.solve(A[i, j], identity)
        Atrans[i, j] = np.transpose(A[i, j])

有更快,更有效的方法吗?

5 个答案:

答案 0 :(得分:7)

这取自我的一个项目,我也在许多3x3矩阵上进行矢量化线性代数。

请注意,只有一个超过3的循环;不是n上的循环,因此代码在重要维度中被矢量化。我不想保证这与C / numba扩展相比如何做同样的事情,性能明智。这可能会大大加快,但至少这会将环路吹过水中。

def adjoint(A):
    """compute inverse without division by det; ...xv3xc3 input, or array of matrices assumed"""
    AI = np.empty_like(A)
    for i in xrange(3):
        AI[...,i,:] = np.cross(A[...,i-2,:], A[...,i-1,:])
    return AI

def inverse_transpose(A):
    """
    efficiently compute the inverse-transpose for stack of 3x3 matrices
    """
    I = adjoint(A)
    det = dot(I, A).mean(axis=-1)
    return I / det[...,None,None]

def inverse(A):
    """inverse of a stack of 3x3 matrices"""
    return np.swapaxes( inverse_transpose(A), -1,-2)
def dot(A, B):
    """dot arrays of vecs; contract over last indices"""
    return np.einsum('...i,...i->...', A, B)


A = np.random.rand(2,2,3,3)
I = inverse(A)
print np.einsum('...ij,...jk',A,I)

答案 1 :(得分:3)

转置的

在ipython中测试了一下:

In [1]: import numpy
In [2]: x = numpy.ones((5,6,3,4))
In [3]: numpy.transpose(x,(0,1,3,2)).shape
Out[3]: (5, 6, 4, 3)

所以你可以做到

Atrans = numpy.transpose(A,(0,1,3,2))

转换第二维和第三维(同时保留第0和第1维)

反转的

http://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.inv.html#numpy.linalg.inv

的最后一个例子

可以一次计算几个矩阵的逆:

from numpy.linalg import inv
a = np.array([[[1., 2.], [3., 4.]], [[1, 3], [3, 5]]])
>>> inv(a)
array([[[-2. ,  1. ],
        [ 1.5, -0.5]],
       [[-5. ,  2. ],
        [ 3. , -1. ]]])

所以我想在你的情况下,可以用

完成反演
Ainv = inv(A)

并且它将知道最后两个维度是它应该反转的维度,并且第一个维度就是您堆叠数据的方式。这应该快得多

速度差异

转置:你的方法需要3.77557015419秒,我的需要2.86102294922e-06秒(加速超过100万次)

对于反转:我猜我的numpy版本不够高,无法尝试使用(n,n,3,3)形状的numpy.linalg.inv技巧,看看那里的加速(我的版本是1.6.2,我基于我的解决方案的文档是1.8,但它应该工作在1.8,如果其他人可以测试吗?)

答案 2 :(得分:2)

Numpy拥有array.T属性,这是transpose的快捷方式。

对于反转,您使用np.linalg.inv(A)

答案 3 :(得分:0)

由wim A.发布。我也在矩阵上工作。 e.g。

print(A.I)

答案 4 :(得分:-1)

对于numpy-matrix对象,使用matrix.getI。 例如

Data Type = grid
Dimensions = 0 1
I Dimension = 1 to 73 Linear 0 5
J Dimension = 1 to 46 Linear -90 4
Sizes = 73 46 3358
Undef value = -2.56e+33
Undef count = 1763  Valid count = 1595
Min, Max = 243.008 302.818
Cmin, cmax, cint = 245 300 5
Stats[sum,sumsqr,root(sumsqr),n]:     452778 1.29046e+08 11359.8 1595
Stats[(sum,sumsqr,root(sumsqr))/n]:     283.874 80906.7 284.441
Stats[(sum,sumsqr,root(sumsqr))/(n-1)]: 284.052 80957.4 284.53
Stats[(sigma,var)(n)]:     17.9565 322.437
Stats[(sigma,var)(n-1)]:   17.9622 322.64
Contouring: 245 to 300 interval 5