I have a matrix shaped (4000, 4000) and I would like to take the inverse. (My intuition of the inverting matrices breaks down with such large matrices.)
The beginning matrix has values of the magnitude e-10, with the following values: print matrix gives an output
[[ 2.19885119e-10 2.16462810e-10 2.13062782e-10 ..., -2.16462810e-10
-2.19885119e-10 -2.16462810e-10]
[ 2.16462810e-10 2.19885119e-10 2.16462810e-10 ..., -2.13062782e-10
-2.16462810e-10 -2.19885119e-10]
[ 2.13062782e-10 2.16462810e-10 2.19885119e-10 ..., -2.16462810e-10
-2.13062782e-10 -2.16462810e-10]
...,
[ -2.16462810e-10 -2.13062782e-10 -2.16462810e-10 ..., 2.19885119e-10
2.16462810e-10 2.13062782e-10]
[ -2.19885119e-10 -2.16462810e-10 -2.13062782e-10 ..., 2.16462810e-10
2.19885119e-10 2.16462810e-10]
[ -2.16462810e-10 -2.19885119e-10 -2.16462810e-10 ..., 2.13062782e-10
2.16462810e-10 2.19885119e-10]]
I then use NumPy's numpy.linalg.inv() to invert the matrix.
import numpy as np
new_matrix = np.linalg.inv(matrix)
print new_matrix
This is the output I get in return:
[[ 1.95176541e+25 9.66643852e+23 -1.22660930e+25 ..., -1.96621184e+25
-9.41413909e+24 1.33500310e+25]
[ 2.01500967e+25 1.08946558e+24 -1.25813014e+25 ..., -2.07717912e+25
-9.86804459e+24 1.42950556e+25]
[ 3.55575106e+25 2.11333704e+24 -2.25333936e+25 ..., -3.68616202e+25
-1.72651875e+25 2.51239524e+25]
...,
[ 3.07255588e+25 1.61759838e+24 -1.95678425e+25 ..., -3.15440712e+25
-1.47472306e+25 2.13570651e+25]
[ -7.24380790e+24 -8.63730581e+23 4.90519245e+24 ..., 8.30663797e+24
3.70858694e+24 -5.32291734e+24]
[ -1.95760004e+25 -1.12341031e+24 1.23820305e+25 ..., 2.01608416e+25
9.40221886e+24 -1.37605863e+25]]
That's a huge difference! How could that be? A matrix of magnitude e-10 is inverted to a matrix of magnitude e+25?
Is this mathematically correct, or are the IEEE floating point values breaking down?
If this is mathematically correct, could someone explain to me the mathematical intuition behind this?
EDIT:
Following the comments below, I decided to test.
np.dot(matrix, new_matrix) should give the identity matrix, A * A^T = Identity.
This is my output:
[[ 0. -3. -16. ..., 16. 8. 12. ]
[-24. -1.5 -8. ..., 32. -4. 36. ]
[ 40. 1. -64. ..., 24. 20. 24. ]
...,
[ 32. -0.5 48. ..., -16. -20. 16. ]
[ 40. 7. 16. ..., -48. -36. -28. ]
[ 16. 3. 12. ..., -80. 16. 0. ]]
Why does numpy.linalg.inv() result in numerical errors?
np.allclose( np.dot(matrix, new_matrix), np.identity(4000) )
gives False.
We use numpy. linalg. inv() function to calculate the inverse of a matrix. The inverse of a matrix is such that if it is multiplied by the original matrix, it results in identity matrix.
Inverse of a Matrix using NumPy Python provides a very easy method to calculate the inverse of a matrix. The function numpy. linalg. inv() which is available in the python NumPy module is used to compute the inverse of a matrix.
In NumPy, we can compute the determinant of the given square array with the help of numpy. linalg. det(). It will take the given square array as a parameter and return the determinant of that. Syntax: numpy.linalg.det()
Your matrix is ill-conditionned, since
np.linalg.cond(matrix) > np.finfo(matrix.dtype).eps
According to this answer you could consider using Singular Value Decomposition to inverse such matrices.
For the determinant of the 2 matrices, you have that
det(A) * det(A^{-1}) = 1
so that if det(A) is big, then det(A^{-1}) is small. For the norm of the 2 matrices, (if you pick a sub-multiplicative norm), you have:
1 = |A*A^{-1}| >= |A| |A^-1|
where || is a reasonable choice of a norm that is sub-multiplicative. Here you have the intuition of what you are observing numerically: if the >= sign is actually a ~=, you recover the same observation that is strictly true for the determinant.
The same reasoning applies if you consider the product
A * A^{-1} = 1
for a matrix A with all positive elements. For the elements on the diagonal of 1 at the RHS, you need very small numbers from A^{-1} if the elements of A are very big.
PS: Notice however that this does not PROVE that this trend always holds. This just provides mathematical intuition of why you observe this scaling.
EDIT, in reply to the comments:
Originally the question was "If this is mathematically correct, could someone explain to me the mathematical intuition behind this?". And indeed, it is mathematically correct and sound that given a matrix with small numbers, the inverse will have large numbers. Above I explain why this is the case.
To answer the other question that came up in the OP's edit, which is why inv() results in numerical errors: inverting matrices is a HARD problem. That is why every time we can, we avoid inverting them. For example, for the problem
A x = b
we do not calculate the inverse of A, but use other algorithms (in practise, you'd call scipy.linalg.solve in python for example).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With