2

我准备了一个随机数矩阵,计算它的逆矩阵并将其与原始矩阵相乘。这在理论上给出了单位矩阵。我怎么能让我numpy这样做?

import numpy

A = numpy.zeros((100,100))
E = numpy.zeros((100,100))

size = 100

for i in range(size):
    for j in range(size):
        A[i][j]+=numpy.random.randint(10)
        if i == j:
            E[i][j]+=1

A_inv = numpy.linalg.linalg.inv(A)
print numpy.dot(A, A_inv)

运行代码产生

[me]machine @ numeric $ python rand_diag.py 
[[  1.00000000e+00  -7.99360578e-15  -1.14491749e-16 ...,   3.81639165e-17
   -4.42701431e-15   1.17961196e-15]
[ -5.55111512e-16   1.00000000e+00  -2.22044605e-16 ...,  -3.88578059e-16
    1.33226763e-15  -8.32667268e-16]

很明显,结果是一个单位矩阵,但不精确,所以print numpy.dot(A, A_inv) == E显然给出了False. 我这样做是为了练习线性代数并试图找到我的机器达到其极限的矩阵大小。获得一个True将具有教学吸引力。

编辑:

设置size=10000,我内存不足

[me]machine @ numeric $ Python(794) malloc:
***mmap(size=800002048) failed (error code=12)
*** error: can\'t allocate region
*** set a breakpoint in malloc_error_break to debug
Traceback (most recent call last):
File "rand_diag.py", line 14, in <module>     A_inv = numpy.linalg.linalg.inv(A)
File "/Library/Frameworks/Python.framework/Versions/7.2/lib/python2.7/site-packages/numpy/linalg/linalg.py", line 445, in inv
return wrap(solve(a, identity(a.shape[0], dtype=a.dtype)))
File "/Library/Frameworks/Python.framework/Versions/7.2/lib/python2.7/site-packages/numpy/linalg/linalg.py", line 323, in solve
a, b = _fastCopyAndTranspose(t, a, b)
File "/Library/Frameworks/Python.framework/Versions/7.2/lib/python2.7/site-packages/numpy/linalg/linalg.py", line 143, in _fastCopyAndTranspose
cast_arrays = cast_arrays + (_fastCT(a),)
MemoryError

[1]+  Exit 1                  python rand_diag.py

如何分配更多内存以及如何并行运行(我有 4 个内核)?

4

4 回答 4

8

虽然 getTrue在教学上很有吸引力,但它也会脱离浮点计算的现实。

在处理浮点数时,不仅要为不精确的结果做好准备,还要为出现的各种其他数值问题做好准备。

我强烈推荐阅读每个计算机科学家应该知道的关于浮点运算的知识

在您的特定情况下,为确保它A * inv(A)足够接近单位矩阵,您可以计算矩阵范数numpy.dot(A, A_inv) - E确保它足够小。

作为旁注,您不必使用循环来填充AE. 相反,您可以使用

A = numpy.random.randint(0, 10, (size,size))
E = numpy.eye(size)
于 2013-03-29T16:28:02.480 回答
4

同意已经提出的大部分观点。但是,我建议不要查看单个非对角线元素,而是取它们的 rms 总和;这在某种意义上反映了由于计算不完善而泄漏到非对角项中的“能量”。然后,如果您将此 RMS 数除以对角项的总和,您将获得逆运算效果的指标。例如,下面的代码:

import numpy
import matplotlib.pyplot as plt
from numpy import mean, sqrt
N = 1000
R = numpy.zeros(N)

for size in range(50,N,50):

  A = numpy.zeros((size, size))
  E = numpy.zeros((size, size))

  for i in range(size):
      for j in range(size):
          A[i][j]+=numpy.random.randint(10)
          if i == j:
              E[i][j]=1

  A_inv = numpy.linalg.linalg.inv(A)
  D = numpy.dot(A, A_inv) - E
  S = sqrt(mean(D**2))
  R[size] = S/size
  print "size: ", size, "; rms is ",  S/size

plt.plot(range(50,N,50), R[range(50, N, 50)])
plt.ylabel('RMS fraction')
plt.show()

表明 rms 误差非常稳定,数组的大小一直到 950x950 的大小(它确实减慢了一点......)。然而,它从来都不是“精确的”,并且存在一些异常值(大概当矩阵更接近奇异时 - 这可能发生在随机矩阵中。)

示例图(每次运行时,它看起来都会有所不同):

在此处输入图像描述

于 2013-03-29T16:55:47.827 回答
2

最后,您可以使用

m = np.round(m, decimals=10)

或检查它们是否有很大不同:

np.abs(A*A.I - i).mean() < 1e-10

如果你想杀死微小的数字。


我会在numpy.matrix课堂上实现这一点。

import numpy

size = 100
A = numpy.matrix(numpy.random.randint(0,10,(size,)*2))
E = numpy.eye(size)

print A * A.I
print np.abs(A * A.I - E).mean() < 1e-10
于 2013-03-29T16:27:12.470 回答
0

您的问题可以简化为常见的浮点比较问题。比较此类数组的正确方法是:

EPS = 1e-8  # for example
(np.abs(numpy.dot(A, A_inv) - E) < EPS).all()
于 2013-03-29T16:29:02.600 回答