Workspace IndexMath › Day 25

Determinant and Rank TODO

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

Concept

The determinant is a scalar associated with a square matrix that expresses by what factor the linear transformation it represents scales volume, and whether it flips orientation. A determinant of zero means the transformation flattens the space into a lower dimension, which is equivalent to the inverse not existing. Rank is the dimension of the space spanned by the matrix's columns — the maximum number of linearly independent columns — and row rank always equals column rank. By the rank-nullity theorem, for a matrix with n columns, rank plus the dimension of the null space equals n, and this relationship determines whether a system of linear equations has a unique solution or infinitely many. In numerical computation, it's more stable to look at the condition number derived from the singular values than to check whether the determinant is zero, because the determinant is scale-sensitive and unsuitable as an indicator for detecting near-singular matrices.

Whether a linear system has a unique solution, whether the data effectively has redundant explanatory variables, and whether the numerical computation will become unstable — all of these are determined by rank and condition number.

Code & Formula

# 행렬식과 랭크 — det=0 <=> 열이 선형종속 <=> 역행렬 없음 <=> 랭크 부족, 을 수치로 확인한다.

import numpy as np

A_full_rank = np.array([[1.0, 2.0, 0.0],
                         [0.0, 1.0, 3.0],
                         [4.0, 0.0, 1.0]])

# 세 번째 열을 앞 두 열의 선형결합으로 만들어 일부러 랭크를 하나 부족하게 만든 행렬
A_deficient = A_full_rank.copy()
A_deficient[:, 2] = 2 * A_full_rank[:, 0] - A_full_rank[:, 1]

for name, A in [("full-rank 행렬", A_full_rank), ("랭크 부족 행렬 (열3 = 2*열1 - 열2)", A_deficient)]:
    det = np.linalg.det(A)
    rank = np.linalg.matrix_rank(A)
    invertible = not np.isclose(det, 0)
    print(f"[{name}]")
    print(f"  det(A) = {det:.6f}")
    print(f"  rank(A) = {rank} (정방행렬 크기 = {A.shape[0]})")
    print(f"  역행렬 존재? {invertible}\n")

# 랭크-널리티 정리: rank(A) + dim(null(A)) = n (열 개수)
n = A_deficient.shape[1]
rank_deficient = np.linalg.matrix_rank(A_deficient)
# SVD로 영공간 차원을 구한다 (특이값이 ~0인 개수)
_, S, _ = np.linalg.svd(A_deficient)
nullity = np.sum(np.isclose(S, 0))
print(f"랭크-널리티 검증: rank({rank_deficient}) + nullity({nullity}) = {rank_deficient + nullity} = n({n})")

Exercise

Construct a rank-deficient 3x3 matrix, confirm its determinant is zero, then add a very small value to one entry and compare how the determinant and the condition number each change.

Practical Connection

When working with data whose columns are nearly linearly dependent — like a price correlation matrix or risk metrics across multiple markets — the solution becomes unstable, so checking rank and condition number before regression or covariance estimation needs to be a habit.

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/.


한국어

행렬식과 랭크 TODO

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

개념

행렬식은 정사각행렬에 대응하는 스칼라로, 그 행렬이 나타내는 선형변환이 부피를 몇 배로 바꾸는지와 방향을 뒤집는지를 나타낸다. 행렬식이 0이라는 것은 변환이 공간을 더 낮은 차원으로 납작하게 만든다는 뜻이고, 이는 역행렬이 존재하지 않는다는 것과 동치다. 랭크는 행렬의 열들이 생성하는 공간의 차원, 즉 선형독립인 열의 최대 개수이며 행랭크와 열랭크는 언제나 같다. 랭크-널리티 정리에 따라 열이 n개인 행렬에서 랭크와 영공간의 차원을 더하면 n이 되고, 이 관계가 선형 연립방정식의 해가 유일한지 무수히 많은지를 결정한다. 수치 계산에서는 행렬식이 0인지 보는 것보다 특이값에서 나오는 조건수를 보는 편이 안정적인데, 행렬식은 스케일에 민감해 거의 특이한 행렬을 판별하는 지표로는 부적합하기 때문이다.

선형 시스템이 유일해를 갖는지, 데이터에 사실상 중복된 설명변수가 있는지, 수치 계산이 불안정해질지가 전부 랭크와 조건수로 판정되기 때문이다.

코드 · 수식

# 행렬식과 랭크 — det=0 <=> 열이 선형종속 <=> 역행렬 없음 <=> 랭크 부족, 을 수치로 확인한다.

import numpy as np

A_full_rank = np.array([[1.0, 2.0, 0.0],
                         [0.0, 1.0, 3.0],
                         [4.0, 0.0, 1.0]])

# 세 번째 열을 앞 두 열의 선형결합으로 만들어 일부러 랭크를 하나 부족하게 만든 행렬
A_deficient = A_full_rank.copy()
A_deficient[:, 2] = 2 * A_full_rank[:, 0] - A_full_rank[:, 1]

for name, A in [("full-rank 행렬", A_full_rank), ("랭크 부족 행렬 (열3 = 2*열1 - 열2)", A_deficient)]:
    det = np.linalg.det(A)
    rank = np.linalg.matrix_rank(A)
    invertible = not np.isclose(det, 0)
    print(f"[{name}]")
    print(f"  det(A) = {det:.6f}")
    print(f"  rank(A) = {rank} (정방행렬 크기 = {A.shape[0]})")
    print(f"  역행렬 존재? {invertible}\n")

# 랭크-널리티 정리: rank(A) + dim(null(A)) = n (열 개수)
n = A_deficient.shape[1]
rank_deficient = np.linalg.matrix_rank(A_deficient)
# SVD로 영공간 차원을 구한다 (특이값이 ~0인 개수)
_, S, _ = np.linalg.svd(A_deficient)
nullity = np.sum(np.isclose(S, 0))
print(f"랭크-널리티 검증: rank({rank_deficient}) + nullity({nullity}) = {rank_deficient + nullity} = n({n})")

연습

랭크가 부족한 3x3 행렬을 만들어 행렬식이 0임을 확인한 뒤, 원소 하나에 아주 작은 값을 더했을 때 행렬식과 조건수가 각각 어떻게 달라지는지 비교하기.

실무 · Verex 연결

여러 시장의 가격 상관행렬이나 리스크 지표처럼 열이 거의 선형종속인 데이터를 다룰 때 해가 불안정해지므로, 회귀나 공분산 추정 전에 랭크와 조건수를 확인하는 습관이 필요하다.

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

← 24. 수치선형대수(조건수)26. 최소제곱법(Least Squares) →