BRAGA

02 Writing02-02 Notes02-02-198

Distance to affine subspace

Published 16 Apr 20267 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
d(x,L)=∥(x−x0)−πU(x−x0)∥d(x, L) = \|(x - x_0) - \pi_U(x - x_0)\|
(1)

Deep Breakdown

What it tells me (Situation Awareness): An affine subspace L=x0+UL = x_0 + U is a linear subspace UU shifted by a point x0x_0 — it does not necessarily pass through the origin. The distance from a point xx to LL is computed by: (1) translating the problem to the origin (subtract x0x_0 from xx), (2) projecting the translated point onto UU, and (3) measuring the residual. The formula d(x,L)=∥(x−x0)−πU(x−x0)∥d(x, L) = \|(x-x_0) - \pi_U(x-x_0)\| reduces the affine problem to the linear projection problem. In DA/DS: distance from a data point to a hyperplane (a 2D affine subspace in R3\mathbb{R}^3, or (n−1)(n-1)D in Rn\mathbb{R}^n) is used in SVM, linear regression diagnostics, and decision boundary analysis.

Flowchart

Point x, affinesubspace L = x0+ UTranslate: v = x -x0 (shift toorigin)Project v onto U:pi_U(v) = P_pi *vResidual: r = v -pi_U(v)Distance: d(x,L)= ||r|| = ||(x-x0) -P_pi*(x-x0)||d(x,L) = 0 iff x isin LClosest point onL: x0 + pi_U(x -x0)

Real-world use

Where it is used

Distance from a point to a hyperplane (SVM margin), computing the residual of a data point from a fitted regression line/plane (OLS residual in geometric terms), finding the nearest point on a fitted linear manifold to a query point, and clustering (distance from a centroid-defined affine cluster to a new data point).

Problem it solves

Linear subspaces pass through the origin. Real data is rarely centered at the origin. An affine subspace (like a fitted regression plane or an SVM hyperplane) is a linear subspace translated by a specific offset x0x_0. Computing the distance requires removing this offset first before applying the standard linear projection formula.

How it solves the problem

The key idea: translate xx by −x0-x_0 to get v=x−x0v = x - x_0. Now vv is measured relative to the origin of UU, and UU IS a linear subspace containing 0\mathbf{0}. The distance from vv to UU is the standard subspace distance: ∥v−πU(v)∥\|v - \pi_U(v)\|. Since translation preserves distances: d(x,L)=d(x−x0,U)=∥(x−x0)−πU(x−x0)∥d(x, L) = d(x - x_0, U) = \|(x-x_0) - \pi_U(x-x_0)\|.

Example in a business

In SVM: the decision hyperplane is wTx+b=0w^T x + b = 0, which is an affine subspace. The geometric margin (distance from a support vector xsvx_{\text{sv}} to the hyperplane) is d=∣wTxsv+b∣∥w∥d = \frac{|w^T x_{\text{sv}} + b|}{\|w\|}. This is the distance formula for an affine subspace (the hyperplane). SVM maximizes this margin, i.e., pushes support vectors as far from the decision boundary as possible.

The formula, piece by piece

  • L=x0+UL = x_0 + U: the affine subspace; x0∈Rnx_0 \in \mathbb{R}^n is any anchor point on LL; UU is the associated linear subspace (direction space)
  • xx: the point whose distance to LL we want
  • x−x0x - x_0: translate xx to be relative to the anchor point x0x_0; this converts an affine problem to a linear one
  • πU(x−x0)=Pπ(x−x0)\pi_U(x - x_0) = P_\pi(x-x_0): project the translated vector onto the linear subspace UU
  • (x−x0)−πU(x−x0)(x-x_0) - \pi_U(x-x_0): the residual; the component of x−x0x-x_0 not captured by UU
  • ∥(x−x0)−πU(x−x0)∥\|(x-x_0) - \pi_U(x-x_0)\|: the distance; always ≥0\geq 0, equals 0 iff x∈Lx \in L

The formula in words

"Shift the origin to a point on the affine subspace LL. Now LL looks like a linear subspace passing through the origin. Compute the standard linear projection distance. Shift back." Tiny example: LL = the line through (1,1)(1, 1) in the direction (1,0)(1, 0) (horizontal line at height 1). x0=(1,1)x_0 = (1, 1), U=span(1,0)U = \text{span}(1, 0). Query: x=(3,4)x = (3, 4). v=x−x0=(2,3)v = x - x_0 = (2, 3). πU(v)=(2,0)\pi_U(v) = (2, 0) (project onto x-axis). Residual: (2,3)−(2,0)=(0,3)(2,3)-(2,0) = (0,3). d(x,L)=∥(0,3)∥=3d(x, L) = \|(0,3)\| = 3. (Distance from (3,4)(3,4) to the horizontal line y=1y=1 is ∣4−1∣=3|4-1|=3.) ✓\checkmark

Critical Concepts

  • SVM hyperplane distance: for hyperplane wTx+b=0w^T x + b = 0: d(x,H)=∣wTx+b∣∥w∥d(x, H) = \frac{|w^Tx+b|}{\|w\|}. This is the affine subspace distance formula applied to a codimension-1 subspace.
  • OLS residuals: the residual yi−y^iy_i - \hat{y}_i is the distance from observation ii to the fitted hyperplane x0+col(X)x_0 + \text{col}(X) measured in the response direction.
  • Affine vs. linear: a linear subspace contains 0\mathbf{0}; an affine subspace does not (unless x0=0x_0 = 0). The formulas differ by a translation.
  • Closest point on L: πL(x)=x0+πU(x−x0)\pi_L(x) = x_0 + \pi_U(x-x_0) is the closest point on LL to xx (covered in its own file).
  • Invariance: d(x,L)=d(x+c,L+c)d(x, L) = d(x + c, L + c) for any shift cc.

Distance is translation-invariant.

Step-by-step calculation (tiny example)

Step 1: Define the affine subspace Line through x0=(1,2,0)x_0 = (1, 2, 0) in direction b=(1,0,0)b = (1, 0, 0) (the x-axis shifted to height 2 in y, z=0). Query: x=(5,4,3)x = (5, 4, 3).

Step 2: Translate and project v=x−x0=(4,2,3)v = x - x_0 = (4, 2, 3). bunit=(1,0,0)b_{\text{unit}} = (1,0,0). πU(v)=(bTv)b=(4)(1,0,0)=(4,0,0)\pi_U(v) = (b^Tv)b = (4)(1,0,0) = (4,0,0). Residual: (4,2,3)−(4,0,0)=(0,2,3)(4,2,3)-(4,0,0) = (0,2,3).

Step 3: Compute distance d(x,L)=∥(0,2,3)∥=0+4+9=13≈3.606d(x, L) = \|(0,2,3)\| = \sqrt{0+4+9} = \sqrt{13} \approx 3.606. Interpretation: the point (5,4,3)(5,4,3) is 13\sqrt{13} units from the line.

Code examples

Beginner example (Python)

python
import numpy as np

# -- Distance from a point to an affine subspace ---
# L = x0 + span(b): a line through x0 in direction b
x0 = np.array([1.0, 2.0, 0.0])   # anchor point on L
b = np.array([1.0, 0.0, 0.0])   # direction of the line (unit vector)
x = np.array([5.0, 4.0, 3.0])   # query point

# Step 1: translate
v = x - x0

# Step 2: project onto U = span(b)
proj_v = np.dot(b, v) * b   # pi_U(v)

# Step 3: residual and distance
residual = v - proj_v
dist = np.linalg.norm(residual)
print(f"v = x - x0 = {v}")
print(f"pi_U(v) = {proj_v}")
print(f"Residual = {residual}")
print(f"d(x, L) = {dist:.4f}")

# Closest point on L
closest_on_L = x0 + proj_v
print(f"\nClosest point on L: {closest_on_L}")
print(f"Distance verification: {np.linalg.norm(x - closest_on_L):.4f}")

Beginner example (R)

r
# -- Distance from point to affine subspace ---
x0 <- c(1, 2, 0)
b <- c(1, 0, 0)
x <- c(5, 4, 3)
v <- x - x0
proj_v <- sum(b * v) * b
resid <- v - proj_v
dist <- sqrt(sum(resid^2))
cat(sprintf("d(x, L) = %.4f\n", dist))
closest <- x0 + proj_v
cat(sprintf("Closest point on L: (%g, %g, %g)\n", closest[1], closest[2], closest[3]))

Professional example (Python)

python
import numpy as np
import pandas as pd
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
np.random.seed(42)

# -- Business scenario: SVM margin = distance to hyperplane (affine subspace) ---
# The SVM hyperplane w^T x + b = 0 is an affine subspace.
# Margin = distance from support vectors to this affine subspace.

# Generate two-class customer data (2 features for visualization clarity)
N = 200
X_class0 = np.random.randn(N // 2, 2) - 1.5
X_class1 = np.random.randn(N // 2, 2) + 1.5
X = np.vstack([X_class0, X_class1])
y = np.array([0] * (N // 2) + [1] * (N // 2))
scaler = StandardScaler()
X_s = scaler.fit_transform(X)
svm = SVC(kernel='linear', C=1.0)
svm.fit(X_s, y)
w = svm.coef_[0]
b_val = svm.intercept_[0]

# Distance from each training point to the hyperplane
# Affine subspace formula: d = |w^T x + b| / ||w||
distances = np.abs(X_s @ w + b_val) / np.linalg.norm(w)
margin = 2 / np.linalg.norm(w)   # total margin width
results = pd.DataFrame({
    "obs": range(N),
    "class": y,
    "distance": distances.round(4),
})
print(f"SVM hyperplane: w = {w.round(4)}, b = {b_val:.4f}")
print(f"||w|| = {np.linalg.norm(w):.4f}")
print(f"\nMargin width = 2/||w|| = {margin:.4f}")
print(f"\nSupport vectors (distance to hyperplane <= 1/||w|| + tolerance):")
sv_mask = distances < (1.0 / np.linalg.norm(w) + 0.05)
print(results[sv_mask].head(10).to_string(index=False))

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