NumPy Linear Algebra
Deep dive · part of Python NumPy Basics
numpy.linalg covers the linear algebra essentials: matrix multiplication, inverse, determinant, eigendecomposition, SVD and least-squares. For small problems prefer the dedicated functions; for very large/sparse problems use SciPy.
numpy.linalg wraps BLAS/LAPACK for solves, inverses, determinants, eigenvalues, SVD, and least squares. Choose solve over inv for Ax=b—faster and numerically stabler.
Small dense problems live entirely in NumPy; sparse or huge systems move to scipy.sparse.linalg.
Engineering notebooks often chain lstsq for calibration, eig for stability analysis, and SVD for dimensionality reduction before exporting coefficients to production C++ or Rust services.
Production code combines this topic with logging, tests, and clear module boundaries so refactors stay safe when requirements grow.
np.linalg.solve(A, b) for square nonsingular A.
lstsq solves overdetermined systems minimizing ||Ax-b||.
eig and eigh for eigen decomposition; eigh for symmetric matrices.
svd for PCA-style decomposition and rank-deficient solves.
det and inv exist but inv rarely needed explicitly.
@ operator is matrix multiplication (Python 3.5+).
Condition number high means solve is ill-posed—regularize or use lstsq. float64 default; float32 faster on GPU pipelines but less precise.
Cholesky via np.linalg.cholesky on positive definite covariance matrices in statistics.
Broadcasting interacts with linalg when solving many right-hand sides stacked as columns—np.linalg.solve(A, B) where B is (n, k) amortizes factorization cost across k vectors.
Check residual norm after solve in tests; ill-conditioned matrices need lstsq or regularization.
Read the parent tutorial on pythondeck.com for runnable snippets, then reproduce them locally in a virtual environment with pinned dependency versions matching your deployment target.
When pairing with teammates, agree on one idiomatic pattern per concern—mixed styles in one repo slow reviews and invite subtle integration bugs during merges.
Computing inverse then matmul instead of solve.
Using float32 for ill-conditioned matrices without error analysis.
Assuming eig vectors are sorted by eigenvalue magnitude.
Feeding non-square A to solve without lstsq.
Prefer solve/lstsq; document expected matrix properties (SPD, banded).
Reuse decompositions when solving many b vectors (LU factorization).
Validate residuals np.linalg.norm(A@x-b) in tests.
Escalate large sparse systems to SciPy with same dtype discipline.
Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.
The program below demonstrates solve ax = b. Read the comments on each line, run the code, then change names or values to see how the output shifts.
# Example: Solve Ax = b
# Run in the REPL or save as a .py file and execute with python.
import numpy as np
A = np.array([[3.0, 1.0],
[1.0, 2.0]])
b = np.array([9.0, 8.0])
x = np.linalg.solve(A, b)
print(x)
print(A @ x)
This sample walks through least squares fit in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.
# Example: Least squares fit
# Run in the REPL or save as a .py file and execute with python.
import numpy as np
x = np.linspace(0, 1, 50)
y = 3*x + 2 + np.random.randn(50)*0.1
A = np.vstack([x, np.ones_like(x)]).T
(slope, intercept), *_ = np.linalg.lstsq(A, y, rcond=None)
print(slope, intercept)
Here is a hands-on illustration of eigendecomposition. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.
# Example: Eigendecomposition
# Run in the REPL or save as a .py file and execute with python.
import numpy as np
M = np.array([[2.0, 1.0],
[1.0, 3.0]])
vals, vecs = np.linalg.eig(M)
print(vals)
print(vecs)
The program below demonstrates solve linear. Read the comments on each line, run the code, then change names or values to see how the output shifts.
# np.linalg.solve finds x in Ax = b
import numpy as np # numpy
A = np.array([[3., 1.], [1., 2.]]) # coefficients
b = np.array([9., 8.]) # constants
x = np.linalg.solve(A, b) # solution vector
print(x) # unknowns
print(A @ x) # verifies b
print(np.linalg.det(A)) # determinant (non-singular)
This sample walks through least squares in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.
# lstsq fits overdetermined systems in least-squares sense
import numpy as np # numpy
x = np.linspace(0, 1, 20) # predictors
y = 2.5 * x + 1.0 + np.random.randn(20) * 0.05 # noisy line
A = np.vstack([x, np.ones_like(x)]).T # design matrix
coef, *_ = np.linalg.lstsq(A, y, rcond=None) # slope, intercept
print(coef.round(3)) # near [2.5, 1.0]
pred = A @ coef # fitted values
print(np.mean((pred - y) ** 2)) # mean squared residual
Related deep dives on Python NumPy Basics: