我试图找到由特定类(decimal.Decimal
)组成的矩阵的逆矩阵,并在整个过程中将值保持为Decimal对象(以保持整个计算的准确性)。
我的问题是numpy.linalg.inverse
总是将矩阵值作为浮点数返回。我已经计算出一个解决方法,通过在计算逆数后将类型从浮点数更改为十进制对象,但我更喜欢保持整个矩阵的类(我担心我可能会当数字转换成浮点数时失去准确性)?
所以我想我有几个问题:(1)当矩阵的值转换为浮点类型时,我会失去准确性/准确性(I' m处理11乘11矩阵);如果是这样,(2)无论如何都要使用decimal.Decimal
在整个计算过程中将值保持为numpy
;如果没有,(3)是否有另一个模块/方法我应该考虑这种类型的计算?
以下是我的代码的示例:
import numpy as np
from decimal import Decimal as D
a = np.array( [ [D('1'), D('2'), D('3')],
[D('4'), D('5'), D('6')],
[D('7'), D('8'), D('9')] ] )
print type(a[0,0])
# <class 'decimal.Decimal'>
inverse_a = np.linalg.inv(a)
print type(inverse_a[0,0])
# <type 'numpy.float64'>
inverse_a_Decimal_flat = [D(str(i)) for i in inverse_a.flat] # change all values to decimal.Decimal
inverse_a_Decimal = np.reshape(inverse_a_Decimal_flat, [3, 3]) # reshape to 3x3
print type(inverse_a_Decimal[0,0]), d.shape
# <class 'decimal.Decimal'> (3,3)
答案 0 :(得分:1)
您的a
是一个对象数组:
In [255]: a
Out[255]:
array([[Decimal('1'), Decimal('2'), Decimal('3')],
[Decimal('4'), Decimal('5'), Decimal('6')],
[Decimal('7'), Decimal('8'), Decimal('9')]], dtype=object)
在我新近更新的numpy
中,我在尝试执行反向时遇到错误。
In [257]: np.linalg.inv(a)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-257-5c2063aa5f16> in <module>()
----> 1 np.linalg.inv(a)
/usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py in inv(a)
524 signature = 'D->D' if isComplexType(t) else 'd->d'
525 extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
--> 526 ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
527 return wrap(ainv.astype(result_t, copy=False))
528
TypeError: No loop matching the specified signature and casting
was found for ufunc inv
In [258]: np.__version__
Out[258]: '1.11.2'
inv
可能正在使用编译代码(_umath_linalg.inv
),它将被编码为使用标准c
浮点数(浮点数或双精度数)。
您询问了longdouble
:
In [266]: a1=np.arange(1,10,dtype=np.longdouble).reshape(3,3)
In [267]: a1
Out[267]:
array([[ 1.0, 2.0, 3.0],
[ 4.0, 5.0, 6.0],
[ 7.0, 8.0, 9.0]], dtype=float96)
In [268]: np.linalg.inv(a1)
...
TypeError: array type float96 is unsupported in linalg
同样,这是一个如何编译linalg
的问题。
In [269]: a1=np.arange(1,10,dtype=np.double).reshape(3,3)
In [270]: np.linalg.inv(a1)
Out[270]:
array([[ 3.15221191e+15, -6.30442381e+15, 3.15221191e+15],
[ -6.30442381e+15, 1.26088476e+16, -6.30442381e+15],
[ 3.15221191e+15, -6.30442381e+15, 3.15221191e+15]])
我尝试dot
这个并没有获得预期的np.eye
数组。但这是一个几乎奇异的数组(行列式是0,或几乎是这样)。
In [274]: np.linalg.det(a1)
Out[274]: -9.5171266700777698e-16
所以这是一个糟糕的例子。
对数组的混洗值不再是单数
In [288]: a1=np.array([[3,1,2],[4,6,5],[8,9,7]],np.float)
In [289]: a1.dot(np.linalg.inv(a1))
Out[289]:
array([[ 1.00000000e+00, 0.00000000e+00, 2.22044605e-16],
[ -4.44089210e-16, 1.00000000e+00, 4.44089210e-16],
[ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]])
如果a1
为np.int
,我会得到同样的信息,因为np.int
已转发为float64
。我可以使用np.float32
进行测试,以查看较低精度的效果。如上所述,我无法前往longfloat
。
inv
通常计算为I/a1
线性方程解决方案:
In [297]: np.linalg.solve(a1,np.eye(3))
Out[297]:
array([[ 0.14285714, -0.52380952, 0.33333333],
[-0.57142857, -0.23809524, 0.33333333],
[ 0.57142857, 0.9047619 , -0.66666667]])
In [298]: np.linalg.inv(a1)
Out[298]:
array([[ 0.14285714, -0.52380952, 0.33333333],
[-0.57142857, -0.23809524, 0.33333333],
[ 0.57142857, 0.9047619 , -0.66666667]])
答案 1 :(得分:0)
使用sympy.Matrix
是否可以接受?
如果我们使用它:
>>> import sympy as sy
>>> a = sy.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> a.inv()
ValueError: Matrix det == 0; not invertible.
我们意识到反转这个矩阵甚至没有意义!
尝试再次使用10交换9,给出
Matrix([
[-2/3, -4/3, 1],
[-2/3, 11/3, -2],
[ 1, -2, 1]])
这是所需的无限精度结果。