Matrix inversion is a fundamental operation in linear algebra and shows up in many areas: solving linear systems, change of coordinates, control systems, optimization, computer graphics, and more. If you’ve ever solved a linear system
and written the formal solution , you used the idea of an inverse matrix — the “undo” for a linear transformation.
For engineers, data scientists, and ML practitioners, knowing how to compute a matrix inverse in code is essential. But it’s also important to understand the math behind it and the numerical caveats (e.g., when the matrix is nearly singular). This tutorial teaches the math short-hand, gives practical implementations for a 3×3 example, and explains every line of the code so you can copy, run, and adapt it safely.
.jpg)
Table of Contents
-
Introduction — Why matrix inversion matters (SEO-friendly)
-
Quick math recap: what is matrix inversion?
-
When a matrix is invertible — determinant, rank, and condition number
-
Why use libraries (NumPy / PyTorch / TensorFlow)?
-
Implementation 1 — NumPy: code + line-by-line explanation
-
Implementation 2 — PyTorch: code + line-by-line explanation
-
Implementation 3 — TensorFlow: code + line-by-line explanation
-
Verification and practical tip: prefer
solve
over explicit inverse for linear systems -
Numerical stability, condition number, and common errors
-
Example outputs (3×3 example) and interpretation
-
Conclusion & next steps
-
FAQ (short)
2. Quick math recap: what is matrix inversion?
For a square matrix , its inverse (if it exists) is the matrix such that
where is the identity matrix. Only square matrices can have two-sided inverses. A matrix is invertible (or nonsingular) iff . When , the matrix is singular and no inverse exists.
A small, concrete reminder for 2×2:
if . For higher dimensions we rely on Gaussian elimination, LU/QR factorizations, or library routines.
3. When a matrix is invertible — determinant, rank, and condition number
-
Determinant: → invertible. If → singular.
-
Rank: for invertibility.
-
Condition number : measures sensitivity. Large (>>1) → small perturbations in or may produce large changes in solutions. Even if a matrix is invertible, it may be ill-conditioned.
Numerically, even when is nonzero theoretically, floating point errors and a large condition number can make matrix inversion unstable.
4. Why use libraries (NumPy / PyTorch / TensorFlow)?
-
NumPy: the go-to for numerical linear algebra in Python. Efficient, simple API for small-to-medium matrices.
-
PyTorch: primary for ML researchers and GPU acceleration. Use it when your workflow involves tensors, GPUs, or autograd.
-
TensorFlow: similar story to PyTorch but with a different ecosystem; use it for TensorFlow-centric pipelines or when you want integration with TF graphs.
All three provide linalg.inv
(or equivalent) for direct inversion of square matrices. However, in practice for solving systems you should prefer specialized solvers (see section 8).
5. Implementation 1 — NumPy (3×3) — code + detailed explanation
Code (NumPy)
import numpy as np
# Define a 3x3 matrix
A = np.array([[4, 7, 2],
[3, 6, 1],
[2, 5, 3]], dtype=float)
# Compute inverse
A_inv = np.linalg.inv(A)
print("Original Matrix (A):\n", A)
print("\nInverse of A:\n", A_inv)
# Verify A * A_inv = Identity
identity_check = np.dot(A, A_inv)
print("\nVerification (A * A_inv):\n", identity_check)
Line-by-line explanation
-
import numpy as np
-
Imports NumPy and gives it the conventional alias
np
. NumPy provides arrays and linear algebra utilities.
-
-
A = np.array([[4, 7, 2], [3, 6, 1], [2, 5, 3]], dtype=float)
-
Creates a 3×3 NumPy array for matrix . We explicitly set
dtype=float
so arithmetic uses floating point (important for inversion). The shape is(3, 3)
.
-
-
A_inv = np.linalg.inv(A)
-
Calls NumPy’s linear algebra inverse function. Internally, NumPy uses LAPACK routines (e.g., LU factorization) for efficiency. If
A
is singular, NumPy raisesnp.linalg.LinAlgError
.
-
-
print("Original Matrix (A):\n", A)
-
Prints the original matrix. Useful to confirm the input.
-
-
print("\nInverse of A:\n", A_inv)
-
Prints the computed inverse matrix.
-
-
identity_check = np.dot(A, A_inv)
-
Multiplies
A
and its purported inverse; result should be the identity matrix (within floating point tolerances).
-
-
print("\nVerification (A * A_inv):\n", identity_check)
-
Prints the product to show verification.
-
Notes & best practices:
-
Use
dtype=float
orfloat64
to avoid integer division or unexpected rounding. -
Wrap
np.linalg.inv
in atry/except
to handle singular matrices gracefully:try: A_inv = np.linalg.inv(A) except np.linalg.LinAlgError: print("Matrix is singular and cannot be inverted.")
6. Implementation 2 — PyTorch (3×3) — code + detailed explanation
Code (PyTorch)
import torch
# Define a 3x3 tensor (matrix)
A = torch.tensor([[4., 7., 2.],
[3., 6., 1.],
[2., 5., 3.]])
# Compute inverse
A_inv = torch.linalg.inv(A)
print("Original Matrix (A):\n", A)
print("\nInverse of A:\n", A_inv)
# Verify A * A_inv = Identity
identity_check = torch.matmul(A, A_inv)
print("\nVerification (A * A_inv):\n", identity_check)
Line-by-line explanation
-
import torch
-
Imports PyTorch. PyTorch exposes tensor operations and linear algebra functions; many operations can run on GPU if tensors are moved to a CUDA device.
-
-
A = torch.tensor([[4., 7., 2.], [3., 6., 1.], [2., 5., 3.]])
-
Creates a 3×3
torch.Tensor
. Notice we put decimals like4.
to make PyTorch create floating-point tensor (dtype=torch.float32
by default). Using integers would produce an integer tensor andtorch.linalg.inv
requires floats.
-
-
A_inv = torch.linalg.inv(A)
-
Computes matrix inverse using PyTorch’s linear algebra (relies on underlying libraries). If
A
is singular, a runtime error is raised.
-
-
print("Original Matrix (A):\n", A)
-
Prints the original tensor.
-
-
print("\nInverse of A:\n", A_inv)
-
Prints the inverse tensor.
-
-
identity_check = torch.matmul(A, A_inv)
-
Matrix multiply (works for 2-D tensors).
torch.matmul
is the correct multiplication primitive in PyTorch.
-
-
print("\nVerification (A * A_inv):\n", identity_check)
-
Prints the product; close to identity within numerical tolerance.
-
PyTorch-specific notes:
-
To use double precision, create the tensor with
dtype=torch.float64
or call.double()
:A = torch.tensor(..., dtype=torch.float64)
-
To run on GPU:
device = torch.device('cuda') A = A.to(device) A_inv = torch.linalg.inv(A)
-
If you need gradients through inverse, ensure
A
is atorch.Tensor
withrequires_grad=True
(but be careful: inverse has nontrivial gradients).
7. Implementation 3 — TensorFlow (3×3) — code + detailed explanation
Code (TensorFlow)
import tensorflow as tf
# Define a 3x3 constant tensor
A = tf.constant([[4., 7., 2.],
[3., 6., 1.],
[2., 5., 3.]])
# Compute inverse
A_inv = tf.linalg.inv(A)
print("Original Matrix (A):\n", A.numpy())
print("\nInverse of A:\n", A_inv.numpy())
# Verify A * A_inv = Identity
identity_check = tf.matmul(A, A_inv)
print("\nVerification (A * A_inv):\n", identity_check.numpy())
Line-by-line explanation
-
import tensorflow as tf
-
Imports TensorFlow. If you use TF 2.x, eager execution is on by default and tensors behave similarly to NumPy arrays.
-
-
A = tf.constant([[4., 7., 2.], [3., 6., 1.], [2., 5., 3.]])
-
Creates a constant 3×3 tensor. Dtype defaults to
tf.float32
when floats are provided.
-
-
A_inv = tf.linalg.inv(A)
-
Computes inverse using TensorFlow’s linear algebra routines. If
A
is singular, TensorFlow raises an error.
-
-
print("Original Matrix (A):\n", A.numpy())
-
A.numpy()
converts the tensor to a NumPy array for readable printing in eager mode.
-
-
print("\nInverse of A:\n", A_inv.numpy())
-
Prints the inverse as a NumPy array.
-
-
identity_check = tf.matmul(A, A_inv)
-
Matrix multiplication in TensorFlow. Returns a TF tensor.
-
-
print("\nVerification (A * A_inv):\n", identity_check.numpy())
-
Prints the product converted to NumPy.
-
TensorFlow-specific notes:
-
If you plan to compute gradients with respect to
A
throughA_inv
, usetf.Variable
andtf.GradientTape
. Inverse is differentiable whereA
is invertible. -
For graph-mode usage or TF 1.x compatibility, wrap operations accordingly. With TF 2.x eager mode, the code above runs directly.
8. Verification and practical tip: prefer solve
over explicit inverse
Although mathematically , numerically computing A_inv
and then performing matrix multiplication is often less stable and slower than directly solving Ax = b
. Both NumPy and other libraries provide solvers:
NumPy prefered pattern:
# Given A and b:
x = np.linalg.solve(A, b)
np.linalg.solve
uses factorizations directly and avoids explicitly forming A_inv
. For repeated solves with same A but different b, factor once (e.g., LU) and reuse.
Demonstration (for the example matrix)
-
Let .
-
x_via_inv = A_inv.dot(b)
(explicit inverse then multiply). -
x_via_solve = np.linalg.solve(A, b)
(recommended).
Both give essentially the same result, but np.linalg.solve
is numerically preferred.
9. Numerical stability, condition number, and common errors
Condition number measures how “close to singular” a matrix is. A high condition number (e.g., or higher) indicates potential numerical trouble. You can compute it in NumPy:
np.linalg.cond(A)
Common errors:
-
np.linalg.LinAlgError: Singular matrix
→A
is singular or too ill-conditioned for inversion. -
In PyTorch, mismatched dtypes (e.g., integer tensor) will cause errors; cast to float.
-
Passing non-square matrices to
inv
— only square matrices can be inverted. -
Forgetting floating dtype (integers) leads to integer tensor and errors.
What to do if a matrix is singular or nearly singular:
-
Use the Moore–Penrose pseudoinverse (
np.linalg.pinv(A)
) for least-squares or pseudo-solutions. -
Use SVD-based solvers that manage rank deficiency gracefully.
10. Example outputs (3×3 example) and interpretation
Using our example matrix:
-
Determinant (computed numerically):
⇒ Non-zero, so is invertible. -
Inverse (numerical value computed via libraries):
-
Verification
A @ A_inv
yields the identity matrix up to tiny floating point residuals (values like appear due to rounding). -
Condition number computed for this matrix is approximately
29.13
— a modest number, so the problem is not ill-conditioned.
Interpretation: The matrix is well-behaved (determinant 9, moderate condition number), so standard inversion routines return accurate results.
11. Conclusion & next steps
You now have:
-
a clear mathematical refresher on what matrix inversion is,
-
hands-on implementations of matrix inversion for a 3×3 matrix in NumPy, PyTorch, and TensorFlow,
-
line-by-line explanations so you can understand and adapt the code,
-
practical tips (use
np.linalg.solve
for solving linear systems; check condition number; handle singular matrices).
Next steps you might want to try:
-
Implement Gauss–Jordan elimination by hand for educational purposes.
-
Explore
np.linalg.pinv
andtf.linalg.pinv
to handle singular / rectangular matrices. -
Try using GPU acceleration in PyTorch to invert large matrices (be careful with memory & performance).
-
Practice computing inverses for matrices that are ill-conditioned and observe the numerical instability.
12. FAQ (short)
Q: Can I invert a non-square matrix?
A: No two-sided inverse exists for non-square matrices. Use the Moore–Penrose pseudoinverse (pinv
) for least-squares solutions.
Q: Why is np.linalg.solve
preferred over np.linalg.inv
?
A: solve
uses direct factorization and is faster and more numerically stable than computing the inverse and then multiplying.
Q: What if np.linalg.inv
raises an error?
A: The matrix is singular or numerically rank-deficient. Use np.linalg.pinv
or diagnose by checking np.linalg.cond
and np.linalg.det
.
Q: Are there GPU benefits for inversion?
A: Yes for very large matrices, but inversion is O(n^3)
and may be memory-bound. Consider whether you need the full inverse or only solve linear systems.
Comments
Post a Comment