Linear Systems & Applications
The Problem Behind Every ML Model
Every machine learning model eventually boils down to solving a system of linear equations. When you train a linear regression, you’re solving:Difficulty: Intermediate
Prerequisites: Matrices module
What You’ll Build: Equation solver, network flow optimizer, least squares regression
The Classic Problem: Three Equations, Three Unknowns
A Real Scenario: Pricing Mystery
You’re a detective investigating suspicious pricing at three stores. Each store sells the same three products (apples, bananas, oranges) but only shows the total bill:Setting Up the System
Let’s call:- = price of an apple
- = price of a banana
- = price of an orange
Method 1: Gaussian Elimination (The Classic)
This is the method you (probably) learned in high school, but let’s see it with fresh eyes.The Idea: Simplify Step by Step
Transform the system into a simpler form where the solution becomes obvious. The core principle is the same thing you do when solving algebra problems by hand: eliminate variables one at a time until you have a single equation with a single unknown, then work backwards. Think of it like a Sudoku puzzle: you use the information you have to narrow down possibilities until everything is determined. Each elimination step removes one variable from the equations below it.Method 2: LU Decomposition (The Efficient Way)
The Insight: Factor Once, Solve Many
What if you need to solve for many different values? This happens constantly in ML — for instance, when you train a model on the same features but different target variables, or when you serve predictions in real-time with new inputs arriving every millisecond. Gaussian elimination from scratch each time is wasteful. Instead, we factor once and reuse the factorization: Where:- = Lower triangular matrix (all zeros above diagonal)
- = Upper triangular matrix (all zeros below diagonal)
- Solve for (forward substitution - easy!)
- Solve for (back substitution - easy!)
The Least Squares Problem: When There’s No Exact Solution
Real-World Data is Messy
In ML, we rarely have an exact solution. We have:- More equations than unknowns (overdetermined system)
- Noisy measurements
- Contradictory data points
The Normal Equations
The least squares solution minimizes the squared error: Geometrically, you are projecting the vector onto the column space of — finding the closest point in the “world of possible predictions” to the actual observations. The residual (the error) is perpendicular to the column space, which is why this method is sometimes called “orthogonal projection.” The solution is:Application 1: Network Flow Analysis
The Problem
You’re managing a water distribution network. Water flows from sources through pipes to destinations. You need to find the flow in each pipe.Application 2: Electrical Circuit Analysis
Kirchhoff’s Laws as Linear Systems
When Systems Fail: Singular Matrices
Not all systems have solutions. Understanding when and why is crucial.Case 1: No Solution (Inconsistent System)
Case 2: Infinite Solutions (Underdetermined)
Case 3: Numerical Instability (Ill-Conditioned)
This is the sneakiest failure mode because the code runs without errors — it just gives you wrong answers. The system has a unique mathematical solution, but floating-point arithmetic cannot compute it accurately because tiny rounding errors get amplified catastrophically.The Connection to ML
Linear Regression IS Solving a Linear System
This is not an analogy — it is a mathematical identity. When scikit-learn’sLinearRegression().fit(X, y) runs, it is literally solving the normal equations , which is a linear system. Every concept in this module — Gaussian elimination, LU decomposition, condition numbers, least squares — directly applies to understanding why your linear regression works, fails, or produces numerically unstable results.
Practice Exercises
Exercise 1: Traffic Flow
Exercise 1: Traffic Flow
- Into intersection A: 100 from north, 80 from east
- Out of A to B: x
- Out of A to C: y
- Into B from A: x, out to east: 90
- Into C from A: y, out to south: 90
Exercise 2: Chemical Balancing
Exercise 2: Chemical Balancing
Exercise 3: Portfolio Optimization
Exercise 3: Portfolio Optimization
- Stock A: Expected return 8%, risk factor 2
- Stock B: Expected return 12%, risk factor 5
- Stock C: Expected return 6%, risk factor 1
- Total investment: $10,000
- Expected return: 9%
- Total risk factor: 2.5
Summary
Geometric Visualization: What Does “Solving a System” Look Like?
For a 2-variable system, each equation is a line in 2D. Solving the system means finding where the lines intersect.- Unique solution: The matrix is non-singular (). Each equation gives independent information. This is the normal case in well-posed problems.
- No solution: The equations are contradictory. In ML, this happens when data is noisy — you cannot pass a line exactly through all points. The fix: use least squares to find the “closest” solution.
- Infinite solutions: The equations are redundant (one is a multiple of another). The matrix is singular. In ML, this happens with highly correlated features (multicollinearity). The fix: regularization (L1/L2) or dropping redundant features.
Common Numerical Gotchas in Production
Interview Deep-Dive
Explain the condition number of a matrix. Why should every ML engineer check it, and what does it tell you about the reliability of your model's solution?
Explain the condition number of a matrix. Why should every ML engineer check it, and what does it tell you about the reliability of your model's solution?
- The condition number (or equivalently, — the ratio of the largest to smallest singular value) measures how much small perturbations in the input are amplified in the output. Think of it as a “noise amplification factor.” If and your input data has errors in the 6th decimal place, your output could be wrong in the 1st decimal place.
- The practical rule: with float64 (about 16 digits of precision), you lose roughly digits of accuracy. If , you have about 8 reliable digits. If , you have zero reliable digits — the solution is meaningless noise. With float32 (about 7 digits), a condition number above is already dangerous.
- In ML, this matters in multiple places. Linear regression via normal equations: has condition number , so a moderately ill-conditioned feature matrix () produces a severely ill-conditioned normal equations system (). Gaussian processes: the kernel matrix must be inverted, and near-singular kernels (data points very close together) produce absurd predictions. Neural network Hessians: ill-conditioned Hessians at saddle points slow second-order optimizers to a crawl.
- The fix depends on the cause. If multicollinearity is the culprit (correlated features), regularization () shifts all singular values up by , dramatically improving conditioning. If the problem is inherently ill-conditioned (e.g., polynomial regression at high degree), switch to a more stable solver (QR instead of normal equations, SVD-based lstsq) or reformulate the problem (use orthogonal polynomials instead of raw monomials).
- Always check:
np.linalg.cond(X)before trusting a linear solve. This takes but saves you hours of debugging mysterious numerical artifacts.
np.linalg.cond(X) where is your feature matrix. If it exceeds , the gradient landscape is extremely elongated — the loss surface looks like a narrow canyon. Even small steps in the high-curvature direction overshoot, while the low-curvature direction needs enormous steps. This creates oscillation. Three fixes: (1) Add L2 regularization, which “rounds out” the canyon by adding to all eigenvalues of . (2) Use feature standardization (mean=0, std=1), which often reduces the condition number by orders of magnitude. (3) Switch from gradient descent to a solver that accounts for curvature — either the closed-form normal equations (via QR or SVD) or a preconditioned optimizer like Adam (which implicitly adapts per-parameter learning rates based on gradient history, approximating the effect of dividing by the condition number).Compare LU decomposition, QR decomposition, and SVD for solving linear systems. When would you choose each in an ML pipeline?
Compare LU decomposition, QR decomposition, and SVD for solving linear systems. When would you choose each in an ML pipeline?
- LU decomposition (, or with pivoting): factors a square matrix into lower and upper triangular matrices. Each solve after factoring is via forward and back substitution. Best for: solving for many different vectors with the same (e.g., real-time prediction serving where features change but the model’s system matrix stays fixed). Also used internally by
np.linalg.solve(). Limitation: only works for square, non-singular systems. - QR decomposition (, orthogonal, upper triangular): the workhorse for least squares. Solving becomes — a triangular solve after a single matrix multiply. Key advantage: it never forms , so the condition number is , not . This makes it dramatically more stable than the normal equations for ill-conditioned problems. Best for: overdetermined systems (more equations than unknowns), which is the standard situation in regression.
- SVD (): the most expensive but most robust. It handles rank-deficient systems gracefully (just ignore zero singular values), gives the minimum-norm solution for underdetermined systems, and provides complete diagnostic information (the singular values tell you the rank, condition number, and which directions are problematic). Best for: ill-conditioned or rank-deficient systems, and when you need the pseudo-inverse. Also essential when you want the actual decomposition (for PCA, compression, recommendations), not just the solution to .
- The cost hierarchy: LU is to factor, per solve. QR is for an matrix. SVD is — the most expensive. In practice, the cost difference matters only for very large systems or very hot loops.
- In a typical ML pipeline: use QR (via
np.linalg.lstsq) for training-time regression. Use LU (viascipy.linalg.lu_factor/lu_solve) for serving-time solves that reuse the same system matrix. Use SVD when you need diagnostic information or when the system is ill-conditioned and you want the most robust solution.
A colleague's linear regression model produces coefficient values in the billions for a problem where predictions should be in the range 0-100. What is likely going wrong, and how do you fix it?
A colleague's linear regression model produces coefficient values in the billions for a problem where predictions should be in the range 0-100. What is likely going wrong, and how do you fix it?
- Coefficients in the billions are the hallmark of an ill-conditioned feature matrix — specifically, multicollinearity or near-linear dependence among features. What is happening: two or more features are highly correlated, so the model finds that “adding 10 billion to feature A’s coefficient and subtracting 10 billion from feature B’s coefficient” produces nearly the same predictions as small, reasonable coefficients. The solution is mathematically valid but numerically unstable — tiny changes in the data cause the coefficients to swing wildly.
- Diagnosis steps: (1) Compute the correlation matrix and look for between feature pairs. (2) Compute
np.linalg.cond(X)— values above confirm ill-conditioning. (3) Computenp.linalg.svd(X)and check for near-zero singular values — these correspond to the “degenerate” directions causing the problem. - Fix 1: Remove redundant features. If “total_sales” = “unit_price” * “quantity” and all three are in the model, remove one. Variance Inflation Factor (VIF) automates this detection — VIF above 10 indicates problematic multicollinearity.
- Fix 2: L2 regularization (Ridge regression). Adding to guarantees a well-conditioned system and shrinks unstable large coefficients toward zero. The regularization parameter trades bias for stability — cross-validate to find the sweet spot.
- Fix 3: PCA before regression. Project features onto the top- principal components, which are orthogonal by construction (zero multicollinearity). The downside is loss of interpretability.
- Fix 4: Standardize features to mean=0, std=1 before fitting. This often reduces the condition number dramatically by putting all features on the same scale. It does not remove true multicollinearity but prevents scale-induced ill-conditioning.
- The key point: large coefficients are a symptom, not the disease. The disease is ill-conditioning of the feature matrix. Treating the symptom (e.g., clipping coefficients) without addressing the cause will produce a model that appears stable but gives poor out-of-sample predictions.