mpmath矩阵求逆的替代或加速

时间:2013-03-10 13:21:45

标签: python python-3.x matrix inversion mpmath

我在python中编写了一些代码,需要经常反转大方块矩阵(100-200行/列)。

我达到了机器精度的极限,所以我们开始尝试使用mpmath来进行任意精度矩阵求逆,但即使使用gmpy它也很慢。

以精度30(十进制)反转大小为20,30,60的随机矩阵需要~0.19,0.60和4.61秒,而mathematica中的相同操作需要0.0084,0.015和0.055秒。

这是在arch linux机器上使用python3mpmath 0.17(不确定gmpy版本)。我不确定为什么mpmath这么慢,但是有没有任何开源库接近mathematica为此管理的速度(即便1/2也会很快)?

我不需要任意精度 - 128位可能就足够了。我也只是不明白mpmath怎么会这么慢。它必须使用非常不同的矩阵求逆算法。具体来说我正在使用M**-1

有没有办法让它使用更快的算法或加快速度。

3 个答案:

答案 0 :(得分:2)

不幸的是,mpmath中的Linera代数相当慢。有许多库可以更好地解决这个问题(例如Sage)。也就是说,作为Stuart建议的后续内容,在Python中进行合理快速的高精度矩阵乘法相当容易,而无需使用定点算法安装任何库。这是一个使用mpmath矩阵进行输入和输出的版本:

def fixmul(A, B, prec):
    m = A.rows; p = B.rows; n = B.cols;
    A = [[A[i,j].to_fixed(prec) for j in range(p)] for i in range(m)]
    B = [[B[i,j].to_fixed(prec) for j in range(n)] for i in range(p)]
    C = [([0] * n) for r in range(m)]
    for i in range(m):
        for j in range(n):
            s = 0
            for k in range(p):
                s += A[i][k] * B[k][j]
            C[i][j] = s
    return mp.matrix(C) * mpf(2)**(-2*prec)

在256位精度下,对于我来说,这两个200x200矩阵的乘法速度比mpmath快16倍。以这种方式直接编写矩阵求逆程序也不难。当然,如果矩阵条目非常大或非常小,您需要先重新缩放它们。一个更可靠的解决方案是使用gmpy中的浮点类型编写自己的矩阵函数,这应该基本上一样快。

答案 1 :(得分:1)

我假设双精度对于最终结果的精度不是问题,但是对于某些矩阵而言,它在反向的中间结果中引起问题。在这种情况下,让我们将正常numpy(双精度)逆的结果视为一个很好的近似,然后用它作为牛顿方法的几次迭代的起点来求解逆。

A 成为我们试图反转的矩阵, X 是我们对逆的估计。牛顿方法的迭代只包括:

X = X*(2I - AX)

对于大型矩阵,计算上述几次迭代的努力与找到逆的算法相比几乎无关紧要,并且可以极大地提高最终结果的准确性。试一试。

BTW, I 是上述等式中的单位矩阵。

编辑以添加代码以测试浮动类型的精度。

使用此代码测试浮点类型的精度。

x = float128('1.0')
wun = x
two = wun + wun
cnt = 1
while True:
   x = x/two
   y = wun + x
   if y<=wun: break
   cnt +=1

print 'The effective number of mantissa bits is', cnt

答案 2 :(得分:0)

Multiprecision toolbox for MATLAB使用128位精度(Core i7 930)提供以下时序:

20x20 - 0.007秒

30x30 - 0.019秒

60x60 - 0.117秒

200x200 - 3.2秒

请注意,现代CPU的这些数字要低得多。