BRAGA

02 Writing02-02 Notes02-02-206

Pseudo-inverse of B

Published 16 Apr 20266 min read
Contents
  1. 01Deep Breakdown
  2. 02Flowchart
  3. 03Real-world use
  4. 04The formula, piece by piece
  5. 05The formula in words
  6. 06Critical Concepts
  7. 07Step-by-step calculation (tiny example)
  8. 08Code examples
(BTB)−1BT(B^T B)^{-1} B^T
(1)

Deep Breakdown

What it tells me (Situation Awareness): (BTB)−1BT(B^TB)^{-1}B^T is the left pseudo-inverse (or Moore-Penrose pseudoinverse when BB has full column rank) of the matrix BB. It is a k×nk \times n matrix that maps any vector x∈Rnx \in \mathbb{R}^n to the least-squares solution λ^=(BTB)−1BTx∈Rk\hat{\lambda} = (B^TB)^{-1}B^Tx \in \mathbb{R}^k. When BB is a tall matrix (n>kn > k) with full column rank, the system Bλ=xB\lambda = x is overdetermined (more equations than unknowns) and generally has no exact solution. The pseudo-inverse gives the best approximate solution: λ^\hat{\lambda} minimizes ∥Bλ−x∥2\|B\lambda - x\|^2. In OLS: β^=(XTX)−1XTy\hat{\beta} = (X^TX)^{-1}X^Ty is the pseudo-inverse of XX applied to yy.

Flowchart

Overdeterminedsystem: Blambda = x (n k,no exactsolution)Least squares:minimize ||Blambda - x||^2Normalequation: B^T Blambda = B^T xPseudo-inverse:B^+ = (B^TB)^{-1} B^TLeast-squaressolution:lambda_hat =B^+ xProjection:pi_U(x) = Blambda_hat = BB^+ xLeft inverse: B^+B = I_k (not afull inverse)NOT B B^+ =I_n (only B B^+= P_pi,projectionmatrix)

Real-world use

Where it is used

OLS regression (most common use): β^=(XTX)−1XTy\hat{\beta} = (X^TX)^{-1}X^Ty. Any overdetermined linear system (more observations than parameters). Computing the coordinates of a vector's projection onto a subspace. Implementing least-squares fitting in signal processing, control systems, and statistics.

Problem it solves

A regular inverse B−1B^{-1} only exists for square, invertible matrices. For a tall matrix BB (n>kn > k), there is no inverse. The pseudo-inverse (BTB)−1BT(B^TB)^{-1}B^T is the "best possible substitute": it gives the unique minimum-norm least-squares solution to Bλ=xB\lambda = x.

How it solves the problem

(BTB)−1BT(B^TB)^{-1}B^T is called the left pseudo-inverse because (BTB)−1BT⋅B=(BTB)−1(BTB)=Ik(B^TB)^{-1}B^T \cdot B = (B^TB)^{-1}(B^TB) = I_k. It satisfies "left inverse": B+B=IkB^+B = I_k. But BB+=B(BTB)−1BT=Pπ≠InBB^+ = B(B^TB)^{-1}B^T = P_\pi \neq I_n (it's the projection matrix, not the identity). So it is a one-sided inverse.

Example in a business

In OLS with n=1000n=1000 observations and k=5k=5 predictors: XX is 1000×5 (tall, full column rank). X+=(XTX)−1XTX^+= (X^TX)^{-1}X^T is 5×1000. Applying it to yy gives β^=X+y∈R5\hat{\beta} = X^+y \in \mathbb{R}^5: the 5 regression coefficients. The fitted values y^=Xβ^=XX+y=Pπy\hat{y} = X\hat{\beta} = XX^+y = P_\pi y are the projection of yy onto col(X)\text{col}(X).

The formula, piece by piece

  • BTB^T: k×nk \times n transpose; maps Rn→Rk\mathbb{R}^n \to \mathbb{R}^k
  • BTBB^T B: k×kk \times k Gram matrix; invertible iff BB has full column rank (no redundant basis vectors)
  • (BTB)−1(B^T B)^{-1}: k×kk \times k inverse of the Gram matrix
  • (BTB)−1BT(B^T B)^{-1} B^T: k×nk \times n pseudo-inverse; maps Rn→Rk\mathbb{R}^n \to \mathbb{R}^k
  • Notation: B+=(BTB)−1BTB^+ = (B^TB)^{-1}B^T (full column rank case); more generally, B+=VΣ+UTB^+ = V\Sigma^+U^T (SVD-based)
  • Left inverse: B+B=IkB^+B = I_k
  • BB+=PπBB^+ = P_\pi (projection matrix, NOT the identity)
  • Applied to a vector: B+x=λ^B^+x = \hat{\lambda}, the coordinates of πU(x)\pi_U(x) in basis BB

The formula in words

"The pseudo-inverse solves the unsolvable: it finds the best-fit coefficients for an overdetermined system. When you cannot find λ\lambda such that Bλ=xB\lambda = x exactly (because there is no such λ\lambda), the pseudo-inverse gives the λ\lambda that makes BλB\lambda as close to xx as possible." Tiny example: B=(1,2,3)TB = (1, 2, 3)^T, x=(1,1,1)Tx = (1, 1, 1)^T. B+=(BTB)−1BT=114(1,2,3)B^+= (B^TB)^{-1}B^T = \frac{1}{14}(1,2,3). λ^=B+x=1+2+314=614=3/7\hat{\lambda} = B^+x = \frac{1+2+3}{14} = \frac{6}{14} = 3/7. πU(x)=Bλ^=37(1,2,3)T=(3/7,6/7,9/7)T\pi_U(x) = B\hat{\lambda} = \frac{3}{7}(1,2,3)^T = (3/7, 6/7, 9/7)^T.

Critical Concepts

  • Requires full column rank: (BTB)−1(B^TB)^{-1} exists iff columns of BB are linearly independent. If not, use SVD-based pseudoinverse via np.linalg.pinv.
  • Left inverse: B+B=IkB^+B = I_k. Not a right inverse: BB+=Pπ≠InBB^+ = P_\pi \neq I_n.
  • SVD form: for general BB, B+=VΣ+UTB^+ = V\Sigma^+U^T where Σ+\Sigma^+ replaces each nonzero singular value σi\sigma_i with 1/σi1/\sigma_i.
  • Minimum norm: among all least-squares solutions, B+xB^+x has the smallest ∥λ^∥\|\hat{\lambda}\|.
  • OLS: β^=(XTX)−1XTy=X+y\hat{\beta} = (X^TX)^{-1}X^Ty = X^+y. Numerically, never compute (XTX)−1(X^TX)^{-1} explicitly; use np.linalg.lstsq or scipy.linalg.solve.
  • Numerical stability: explicit inversion is ill-conditioned for near-singular BTBB^TB. SVD-based np.linalg.pinv is always preferred.

Step-by-step calculation (tiny example)

Step 1: Identify B and x B=(122)B = \begin{pmatrix}1\\2\\2\end{pmatrix}, x=(312)x = \begin{pmatrix}3\\1\\2\end{pmatrix}. Overdetermined: 3 equations, 1 unknown.

Step 2: Compute the pseudo-inverse BTB=1+4+4=9B^TB = 1+4+4 = 9. (BTB)−1=1/9(B^TB)^{-1} = 1/9. B+=19(1,2,2)B^+ = \frac{1}{9}(1, 2, 2).

Step 3: Apply to get the least-squares solution λ^=B+x=19(3+2+4)=99=1\hat{\lambda} = B^+x = \frac{1}{9}(3+2+4) = \frac{9}{9} = 1. πU(x)=Bλ^=(1,2,2)T\pi_U(x) = B\hat{\lambda} = (1,2,2)^T. r=(3,1,2)−(1,2,2)=(2,−1,0)r = (3,1,2)-(1,2,2) = (2,-1,0). BTr=2−2+0=0B^Tr = 2-2+0 = 0. ✓\checkmark

Code examples

Beginner example (Python)

python
import numpy as np

# -- Pseudo-inverse: (B^T B)^{-1} B^T ---
B = np.array([[1.0], [2.0], [2.0]])   # tall matrix (3x1), overdetermined
x = np.array([3.0, 1.0, 2.0])

# Manual pseudo-inverse
gram = B.T @ B                       # 1x1
gram_inv = np.linalg.inv(gram)       # 1x1
B_plus = gram_inv @ B.T              # pseudo-inverse: 1x3
lambda_hat = (B_plus @ x).item()     # least-squares scalar
proj = B * lambda_hat                # projection vector
residual = x - proj.flatten()
print(f"B^T B = {gram[0,0]:.2f}")
print(f"Pseudo-inverse B^+: {B_plus.round(4)}")
print(f"lambda_hat = {lambda_hat:.4f}")
print(f"Projection pi_U(x) = {proj.flatten().round(4)}")
print(f"Residual = {residual.round(4)}")
print(f"B^T residual = {(B.T @ residual).round(10)}")

# Compare to NumPy pinv
B_plus_np = np.linalg.pinv(B)
print(f"\nnp.linalg.pinv(B): {B_plus_np.round(4)}")
print(f"Match: {np.allclose(B_plus, B_plus_np)}")

Beginner example (R)

r
# -- Pseudo-inverse ---
B <- matrix(c(1, 2, 2), ncol=1)
x <- c(3, 1, 2)
gram <- t(B) %*% B
B_plus <- solve(gram) %*% t(B)
lambda <- B_plus %*% x
proj <- B %*% lambda
resid <- x - proj
cat(sprintf("lambda_hat: %.4f\n", lambda))
cat(sprintf("projection: %s\n", paste(round(proj, 4), collapse=", ")))
cat(sprintf("B^T resid: %.10f\n", t(B) %*% resid))

Professional example (Python)

python
import numpy as np
import pandas as pd
np.random.seed(42)

# -- Business scenario: OLS coefficients via pseudo-inverse ---
# Compare pseudo-inverse methods for numerical stability.
N, K = 300, 5
X = np.column_stack([
    np.ones(N),
    np.random.uniform(1, 100, N),
    np.random.uniform(0, 50, N),
    np.random.uniform(0, 20, N),
    np.random.uniform(0, 10, N),
])
true_beta = np.array([10.0, 2.5, -1.8, 0.5, 3.0])
y = X @ true_beta + np.random.randn(N) * 2.0

# Method 1: explicit pseudo-inverse (unstable if X^T X ill-conditioned)
gram = X.T @ X
B_plus_exp = np.linalg.inv(gram) @ X.T
beta_exp = B_plus_exp @ y

# Method 2: NumPy pinv (SVD-based, always stable)
B_plus_svd = np.linalg.pinv(X)
beta_svd = B_plus_svd @ y

# Method 3: lstsq (best practice)
beta_lstsq, residuals, rank, sv = np.linalg.lstsq(X, y, rcond=None)
comparison = pd.DataFrame({
    "param": [f"beta_{i}" for i in range(K)],
    "true": true_beta,
    "explicit_inv": beta_exp.round(4),
    "pinv_svd": beta_svd.round(4),
    "lstsq": beta_lstsq.round(4),
})
print("Pseudo-inverse comparison for OLS:")
print(comparison.to_string(index=False))
print(f"\nCondition number of X^T X: {np.linalg.cond(gram):.2f}")
print(f"Matrix rank: {rank}")
print("\nPrefer lstsq or pinv over explicit inversion for numerical stability.")

Source: MML1

#linear-algebra#spatial-distance-norms-and-analytic-geometry#orthogonal-projections

Keyboard shortcuts

Single keys, ignored while typing in a field or with Cmd, Ctrl or Alt held.

0
Home
1 2 3 4
Work, Writing, Tools, About
j / k
Next / previous section on this page
n / p
Next / previous project or essay
u
Up one level
l
Deutsch
t
Light or dark theme
?
This list
Esc
Close