Workspace IndexMath › Day 26

Least Squares TODO

Math · Day 26 / 52 · September — Linear Algebra (Day 18-26)

Concept

Least squares is a method for an overdetermined system Ax=b — where there are more equations than unknowns and no exact solution exists — that finds the x minimizing the Euclidean norm of the residual, ||Ax-b||. Geometrically, this is the same as projecting b orthogonally onto the column space of A, and at the optimum the residual is orthogonal to the column space. Using this orthogonality condition yields the normal equations AᵀAx = Aᵀb, and the solution is unique when A's columns are linearly independent. Numerically, however, forming AᵀA directly squares the condition number and loses precision, so in practice it's safer to solve via QR decomposition or SVD. When the columns are nearly dependent or the data is noisy, adding a regularization term, as in ridge regression, stabilizes the solution.

Nearly every task that fits data to a model — regression, calibration, sensor correction — is least squares, and carelessly using the normal equations is a common source of coefficients that wobble due to condition-number issues. Understanding why the residual must be orthogonal also makes diagnosing results easier.

Code & Formula

# 최소제곱법(Least Squares) — 과결정계 Ax=b를 lstsq로 풀고, 정규방정식 AᵀAx=Aᵀb 및
# "잔차는 열공간과 직교한다"는 기하적 성질을 직접 검증한다.

import numpy as np

# 직선 y = a*x + c 를 5개의 잡음 섞인 점에 최소제곱으로 맞추는 과결정계 (미지수 2개, 식 5개)
x_data = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
y_data = np.array([1.1, 2.9, 4.8, 7.2, 8.9])  # 대략 y ≈ 2x + 1 근처의 잡음 데이터

A = np.column_stack([x_data, np.ones_like(x_data)])  # [a, c]를 구하기 위한 설계행렬
b = y_data

x_lstsq, residuals, rank, sv = np.linalg.lstsq(A, b, rcond=None)
a_hat, c_hat = x_lstsq
print(f"lstsq 해: y ≈ {a_hat:.4f}*x + {c_hat:.4f}")

# 정규방정식으로 직접 풀어서 lstsq 결과와 일치하는지 확인 (교육적 검증용, 실무는 lstsq/QR 권장)
x_normal_eq = np.linalg.solve(A.T @ A, A.T @ b)
print(f"정규방정식(AᵀAx=Aᵀb) 해: {x_normal_eq}")
print(f"lstsq와 일치? {np.allclose(x_lstsq, x_normal_eq)}")

# 기하적 성질: 최적점에서 잔차 벡터는 A의 열공간과 직교 → Aᵀ(Ax-b) ≈ 0
residual = A @ x_lstsq - b
orthogonality = A.T @ residual
print(f"\n잔차 벡터: {np.round(residual, 4)}")
print(f"Aᵀ·잔차 (열공간과의 직교성, ≈0이어야 함): {np.round(orthogonality, 10)}")

Exercise

Deliberately construct a matrix with a large condition number, compute the least-squares solution three ways — solving the normal equations directly, via QR, and via SVD — and compare the error against the true value for each.

Practical Connection

In Verex, fitting LMSR's liquidity parameter or a slippage/fee model to historical trade data, or regressing gas cost against block parameters, all apply the same least-squares procedure and the same condition-number cautions.

If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/math-50-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.


한국어

최소제곱법(Least Squares) TODO

Math · Day 26 / 52 · 9월 — 선형대수 (Day 18–26)

개념

최소제곱법은 방정식 수가 미지수 수보다 많아 정확한 해가 없는 과결정 연립방정식 Ax=b에서, 잔차의 유클리드 노름 ||Ax-b||를 최소로 만드는 x를 구하는 방법이다. 기하학적으로 이는 b를 A의 열공간 위로 정사영하는 것과 같고, 최적점에서 잔차는 열공간과 직교한다. 이 직교 조건을 쓰면 정규방정식 AᵀAx = Aᵀb가 나오며, A의 열이 일차독립이면 해는 유일하다. 다만 수치적으로 AᵀA를 직접 만드는 것은 조건수를 제곱시켜 정밀도를 잃으므로, 실무에서는 QR 분해나 SVD로 푸는 편이 안전하다. 열이 거의 종속이거나 잡음이 큰 경우에는 릿지처럼 정규화 항을 더해 해를 안정시킨다.

회귀·캘리브레이션·센서 보정 등 데이터를 모델에 맞추는 거의 모든 작업이 최소제곱이며, 정규방정식을 무심코 쓰다 조건수 문제로 계수가 요동치는 사고가 흔하다. 잔차가 왜 직교해야 하는지를 알면 결과 진단도 쉬워진다.

코드 · 수식

# 최소제곱법(Least Squares) — 과결정계 Ax=b를 lstsq로 풀고, 정규방정식 AᵀAx=Aᵀb 및
# "잔차는 열공간과 직교한다"는 기하적 성질을 직접 검증한다.

import numpy as np

# 직선 y = a*x + c 를 5개의 잡음 섞인 점에 최소제곱으로 맞추는 과결정계 (미지수 2개, 식 5개)
x_data = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
y_data = np.array([1.1, 2.9, 4.8, 7.2, 8.9])  # 대략 y ≈ 2x + 1 근처의 잡음 데이터

A = np.column_stack([x_data, np.ones_like(x_data)])  # [a, c]를 구하기 위한 설계행렬
b = y_data

x_lstsq, residuals, rank, sv = np.linalg.lstsq(A, b, rcond=None)
a_hat, c_hat = x_lstsq
print(f"lstsq 해: y ≈ {a_hat:.4f}*x + {c_hat:.4f}")

# 정규방정식으로 직접 풀어서 lstsq 결과와 일치하는지 확인 (교육적 검증용, 실무는 lstsq/QR 권장)
x_normal_eq = np.linalg.solve(A.T @ A, A.T @ b)
print(f"정규방정식(AᵀAx=Aᵀb) 해: {x_normal_eq}")
print(f"lstsq와 일치? {np.allclose(x_lstsq, x_normal_eq)}")

# 기하적 성질: 최적점에서 잔차 벡터는 A의 열공간과 직교 → Aᵀ(Ax-b) ≈ 0
residual = A @ x_lstsq - b
orthogonality = A.T @ residual
print(f"\n잔차 벡터: {np.round(residual, 4)}")
print(f"Aᵀ·잔차 (열공간과의 직교성, ≈0이어야 함): {np.round(orthogonality, 10)}")

연습

의도적으로 조건수가 큰 행렬을 만들어 정규방정식 직접 풀이, QR, SVD 세 방법으로 최소제곱해를 구하고 참값 대비 오차를 비교하라.

실무 · Verex 연결

Verex에서 과거 체결 데이터로 LMSR의 유동성 파라미터나 슬리피지·수수료 모델을 적합시킬 때, 가스 비용을 블록 파라미터로 회귀할 때 모두 같은 최소제곱 절차와 조건수 주의사항이 적용된다.

공부한 날 원본 커리큘럼(docs/knowledge/math-50-curriculum.md)의 이 줄에 노트 링크와 ✅ 를 붙이면, 이 자리는 노트 본문으로 바로 이어집니다. 노트 없이 이 페이지에 바로 적어도 됩니다 — 다만 다시 생성하면 덮어쓰이므로, 남길 글은 docs/algorithms/ 의 마크다운으로 쓰는 편이 안전합니다.

← 25. 행렬식과 랭크27. 미분·기울기·연쇄법칙 →