1 핵심 질문
소거법을 마치면 행렬은 \(\mathbf{U}\) 또는 \(\mathbf{R}\) 로 단순화된다. 그런데 행렬의 “진짜 크기”는 무엇인가?
- \(m \times n\) 이라는 외형적 크기는 \(0 = 0\) 인 중복 방정식도 포함한다.
- 행렬이 실제로 몇 개의 독립적인 제약을 가하는지가 진짜 크기다.
이것을 수로 포착한 것이 랭크(rank) 다.
2 랭크의 정의
행렬 \(\mathbf{A}\) 의 랭크 \(r\) 은 소거법으로 얻은 피벗의 수다.
\[r = \text{rank}(\mathbf{A}) = \text{피벗의 수}\]
이 수는 \(\mathbf{A}\) 뿐만 아니라 \(\mathbf{U} = \text{echelon}(\mathbf{A})\) 와 \(\mathbf{R} = \text{rref}(\mathbf{A})\) 에서도 동일하다.
단순히 “피벗 세기”지만 이 수는 행렬의 구조 전체를 요약한다. 동일한 랭크 개념을 세 가지 수준에서 바라볼 수 있다.
| 수준 | 정의 | 관점 |
|---|---|---|
| 계산적 (computational) | 소거 후 피벗의 수 | 알고리즘 |
| 벡터 (vector) | 독립 행의 수 = 독립 열의 수 | 선형 독립 |
| 공간 (space) | 열 공간의 차원 = 행 공간의 차원 | 부분공간 이론 |
세 수준 모두 같은 수 \(r\) 을 가리킨다. 이 포스트에서는 계산적 관점을 중심으로, 나머지 두 관점과의 연결을 설명한다.
3 주요 예시: 3×4 행렬의 랭크와 RREF
\[\mathbf{A} = \begin{bmatrix} 1 & 1 & 2 & 4 \\ 1 & 2 & 2 & 5 \\ 1 & 3 & 2 & 6 \end{bmatrix}\]
3열 \((2, 2, 2)\) 은 1열 \((1, 1, 1)\) 의 2배다. 4열 \((4, 5, 6)\) 은 1열과 2열의 합이다. 피벗은 1열과 2열에만 생길 것이다.
3.1 A → U 소거
\[\mathbf{A} \rightarrow \begin{bmatrix} 1 & 1 & 2 & 4 \\ 0 & 1 & 0 & 1 \\ 0 & 2 & 0 & 2 \end{bmatrix} \rightarrow \mathbf{U} = \begin{bmatrix} 1 & 1 & 2 & 4 \\ 0 & 1 & 0 & 1 \\ 0 & 0 & 0 & 0 \end{bmatrix}\]
- 랭크: \(r = 2\) (피벗 2개: \(u_{11} = 1\), \(u_{22} = 1\))
- 피벗 열: 1, 2열
- 자유 열: 3, 4열 → 자유 변수 \(x_3\), \(x_4\)
3.2 U → R (기약 행 사다리꼴)
1행에서 2행을 빼면:
\[\mathbf{R} = \text{rref}(\mathbf{A}) = \begin{bmatrix} 1 & 0 & 2 & 3 \\ 0 & 1 & 0 & 1 \\ 0 & 0 & 0 & 0 \end{bmatrix}\]
\(\mathbf{R}\) 읽기: 3열 = \(2 \times\) 1열, 4열 = \(3 \times\) 1열 \(+ 1 \times\) 2열. 자유 열이 피벗 열의 어떤 결합인지 \(\mathbf{R}\) 이 직접 보여준다.
4 자유 열 = 피벗 열의 선형결합
- 피벗 열: 이전 열들의 선형결합이 아니다 (독립)
- 자유 열: 이전 피벗 열들의 선형결합이다 (종속)
\(\mathbf{R}\) 의 자유 열에 있는 항목 \(F\) 가 바로 그 결합 계수다.
위 예시에서:
\[\text{3열} = 2 \cdot \text{1열} \quad \Rightarrow \quad \mathbf{s}_1 = (-2, 0, 1, 0) \text{ 이 특수해}\] \[\text{4열} = 3 \cdot \text{1열} + 1 \cdot \text{2열} \quad \Rightarrow \quad \mathbf{s}_2 = (-3, -1, 0, 1) \text{ 이 특수해}\]
부호가 반전되는 이유: \(\mathbf{A}\mathbf{x} = \mathbf{0}\) 을 “자유 열을 나머지로 표현”으로 재배치하면 자유 변수에 1을 두고 피벗 변수에 \(-F\) 항목이 온다.
5 영공간 행렬 N = [-F; I]
랭크 \(r\) 인 \(m \times n\) 행렬에서 피벗 열이 앞에 오도록 재배열하면 \(\mathbf{R}\) 은 블록 구조를 가진다:
\[\mathbf{R} = \begin{bmatrix} \mathbf{I}_r & \mathbf{F} \\ \mathbf{0} & \mathbf{0} \end{bmatrix}\]
여기서 \(\mathbf{I}_r\) 은 \(r \times r\) 단위행렬, \(\mathbf{F}\) 는 \(r \times (n-r)\) 자유 블록이다.
영공간 행렬 \(\mathbf{N}\) (특수해들을 열로 나열):
\[\mathbf{N} = \begin{bmatrix} -\mathbf{F} \\ \mathbf{I}_{n-r} \end{bmatrix}\]
검증: \(\mathbf{R}\mathbf{N} = \begin{bmatrix} \mathbf{I} & \mathbf{F} \\ \mathbf{0} & \mathbf{0} \end{bmatrix} \begin{bmatrix} -\mathbf{F} \\ \mathbf{I} \end{bmatrix} = \begin{bmatrix} -\mathbf{F} + \mathbf{F} \\ \mathbf{0} \end{bmatrix} = \mathbf{0}\)
직관: \(\mathbf{R}\) 에서 “자유 변수 부분”을 우변으로 이항하면
\[\mathbf{I} \cdot (\text{피벗 변수}) = -\mathbf{F} \cdot (\text{자유 변수})\]
각 특수해에서 자유 변수 = 단위행렬의 한 열, 피벗 변수 = \(-\mathbf{F}\) 의 해당 열.
6 5×3 예시: 더 많은 자유 변수
\[\mathbf{A} = \begin{bmatrix} 1 & 3 & 0 & 2 & -1 \\ 0 & 0 & 1 & 4 & -3 \\ 1 & 3 & 1 & 6 & -4 \end{bmatrix}\]
3행 = 1행 + 2행이므로 소거 후:
\[\mathbf{R} = \begin{bmatrix} 1 & 3 & 0 & 2 & -1 \\ 0 & 0 & 1 & 4 & -3 \\ 0 & 0 & 0 & 0 & 0 \end{bmatrix}\]
- 피벗 열: 1, 3열 → 피벗 변수 \(x_1\), \(x_3\)
- 자유 열: 2, 4, 5열 → 자유 변수 \(x_2\), \(x_4\), \(x_5\)
- 랭크 \(r = 2\), 특수해 수 = \(n - r = 5 - 2 = 3\)
세 특수해:
\[\mathbf{s}_1 = (-3, 1, 0, 0, 0), \quad \mathbf{s}_2 = (-2, 0, -4, 1, 0), \quad \mathbf{s}_3 = (1, 0, 3, 0, 1)\]
\(\mathbf{F}\) 는 자유 열에서 피벗 행만 추출한 것: \(\mathbf{F} = \begin{bmatrix} 3 & 2 & -1 \\ 0 & 4 & -3 \end{bmatrix}\).
\[\mathbf{N} = \begin{bmatrix} -\mathbf{F} \\ \mathbf{I}_3 \end{bmatrix} = \begin{bmatrix} -3 & -2 & 1 \\ 1 & 0 & 0 \\ 0 & -4 & 3 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}\]
7 랭크 1 행렬: A = uvᵀ
가장 단순한 경우인 랭크 1 행렬은 아름다운 구조를 가진다.
랭크 1인 행렬은 항상 다음과 같이 쓸 수 있다:
\[\mathbf{A} = \mathbf{u}\mathbf{v}^\top \quad (\text{열벡터} \times \text{행벡터})\]
예시:
\[\mathbf{A} = \begin{bmatrix} 1 & 3 & 10 \\ 2 & 6 & 20 \\ 3 & 9 & 30 \end{bmatrix}\]
모든 행이 1행의 배수, 모든 열이 1열의 배수다. 따라서:
\[\mathbf{A} = \underbrace{\begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix}}_{\mathbf{u}} \underbrace{\begin{bmatrix} 1 & 3 & 10 \end{bmatrix}}_{\mathbf{v}^\top}\]
소거하면 2행, 3행이 0이 되어 피벗은 1개뿐이다.
영공간 구조: \(\mathbf{A}\mathbf{x} = \mathbf{0}\) 은 \(\mathbf{u}(\mathbf{v}^\top \mathbf{x}) = \mathbf{0}\) 이므로 \(\mathbf{v}^\top \mathbf{x} = 0\). 즉, 영공간은 \(\mathbf{v}\) 에 수직인 모든 벡터의 집합이다 — 행 공간(\(\mathbf{v}\) 의 방향)과 영공간(\(\mathbf{v}\) 에 수직인 평면)이 서로 직교한다.
일반 랭크 \(r\) 행렬: 랭크 \(r\) 행렬은 랭크 1 행렬 \(r\) 개의 합으로 분해된다:
\[\mathbf{A} = \mathbf{u}_1 \mathbf{v}_1^\top + \mathbf{u}_2 \mathbf{v}_2^\top + \cdots + \mathbf{u}_r \mathbf{v}_r^\top\]
여기서 \(\mathbf{u}_i\) 는 \(\mathbf{A}\) 의 피벗 열, \(\mathbf{v}_i^\top\) 는 \(\mathbf{R}\) 의 비零 행이다. 이것이 랭크-\(r\) 분해(rank factorization) 다.
8 RREF의 유일성
\(\mathbf{A}\) 를 \(\mathbf{R}\) 로 축소하는 방법은 무수히 많다. 어떤 순서로 소거하든, 누가 계산하든 \(\mathbf{R}\) 은 항상 동일하다.
왜 유일한가? 피벗 열과 자유 열은 \(\mathbf{R}\) 의 형태가 아니라 원래 행렬 \(\mathbf{A}\) 의 내재적 성질에 의해 결정된다:
- 피벗 열: 이전 열들의 선형결합이 아닌 열 (독립)
- 자유 열: 이전 피벗 열들의 선형결합인 열 (종속), 그 결합 계수가 \(\mathbf{F}\)
\(\mathbf{A}\) 의 열들 사이의 선형 관계는 행 연산으로 바뀌지 않는다. 따라서 \(\mathbf{F}\) 도 불변이다.
\(m \times n\) 행렬 \(\mathbf{A}\) 에 대해 \(\text{rref}(\mathbf{A}) = \mathbf{R}\) 은 유일하다. 행 연산의 순서나 방식에 관계없이 같은 \(\mathbf{R}\) 을 얻는다.
실용적 의미: \(\mathbf{R}\) 은 \(\mathbf{A}\) 의 “정규형(canonical form)”이다. 두 행렬이 행 동치(row equivalent)인지 확인하려면 각각의 \(\mathbf{R}\) 을 비교하면 된다.
9 랭크와 행렬 크기의 관계
| 조건 | 의미 |
|---|---|
| \(r = m = n\) | 정사각 가역 행렬, \(N(\mathbf{A}) = \{\mathbf{0}\}\), \(C(\mathbf{A}) = \mathbb{R}^m\) |
| \(r = m < n\) | 행이 독립 (“넓은” 행렬), \(\mathbf{A}\mathbf{x} = \mathbf{b}\) 는 항상 해 존재 |
| \(r = n < m\) | 열이 독립 (“좁은” 행렬), \(\mathbf{A}\mathbf{x} = \mathbf{b}\) 는 해가 0 또는 1개 |
| \(r < m, r < n\) | 행도 열도 독립 아님, 해가 없거나 무수히 많음 |
랭크 부족(rank deficiency): \(r < \min(m, n)\) 인 경우. 행렬이 정보 손실을 일으킨다.
10 왜 랭크가 중요한가
머신러닝/데이터 과학에서의 의미:
데이터 행렬 \(\mathbf{X}\) (행 = 관측치, 열 = 특성)의 랭크는 실질적인 특성의 수다. \(n\) 개의 특성이 있어도 \(r < n\) 이면 \(n - r\) 개의 특성이 다른 특성들의 선형결합이다. 이 경우 차원 축소(PCA 등)가 필요하다.
연립방정식 풀이:
\(\mathbf{A}\mathbf{x} = \mathbf{b}\) 의 해 존재와 유일성은 랭크로 결정된다.
- \(r = n\): 유일해 (영공간 = \(\{\mathbf{0}\}\))
- \(r < n\): 무수한 해 (\(n - r\) 개의 자유 변수)
- \(r < m\) 이고 \(\mathbf{b} \notin C(\mathbf{A})\): 해 없음
이 세 가지 경우가 §3.4에서 완전해(complete solution) 분류로 이어진다.
11 응용 분야
| 분야 | 활용 | 랭크의 의미 |
|---|---|---|
| 머신러닝 | 특성 선택, 정규화 | 낮은 랭크 = 중복 특성 존재 |
| 딥러닝 | 저랭크 근사 (LoRA) | 큰 행렬을 두 작은 행렬 곱으로 근사 |
| 영상 처리 | SVD 압축 | 랭크 \(k\) 근사로 이미지 압축 |
| 제어 이론 | 가관측성/가제어성 행렬 | 랭크 결핍 = 관측/제어 불가 모드 존재 |
| 통계학 | 다중공선성(multicollinearity) | 랭크 결핍 = 설명 변수 간 선형 의존 |
12 코드 예시
12.0.1 Step 1: 소거법으로 RREF와 랭크 직접 계산 (원리 이해)
import numpy as np
def full_rref(A):
"""
행렬 A의 RREF와 피벗 열 목록을 반환한다.
"""
A = A.astype(float).copy()
m, n = A.shape
pivot_cols = []
row = 0
for col in range(n):
pivot = None
for r in range(row, m):
if abs(A[r, col]) > 1e-10:
pivot = r
break
if pivot is None:
continue
A[[row, pivot]] = A[[pivot, row]]
A[row] /= A[row, col]
for r in range(m):
if r != row and abs(A[r, col]) > 1e-10:
A[r] -= A[r, col] * A[row]
pivot_cols.append(col)
row += 1
return A, pivot_cols
# 3×4 예시
A = np.array([
[1, 1, 2, 4],
[1, 2, 2, 5],
[1, 3, 2, 6]
], dtype=float)
R, pcols = full_rref(A)
r = len(pcols)
n = A.shape[1]
free_cols = [c for c in range(n) if c not in pcols]
print("RREF R:")
print(np.round(R, 4))
print(f"랭크 r = {r}")
print(f"피벗 열: {pcols}")
print(f"자유 열: {free_cols}")
print(f"영공간 차원 (n-r): {n - r}")
# 영공간 행렬 N = [-F; I] 구성
F = R[:r, :][:, free_cols] # r × (n-r) 자유 블록
N = np.zeros((n, n - r))
for i, fc in enumerate(free_cols):
N[fc, i] = 1.0 # 자유 변수 행: I
for i, pc in enumerate(pcols):
N[pc, :] = -F[i, :] # 피벗 변수 행: -F
print("\n영공간 행렬 N = [-F; I]:")
print(N)
print("\n검증 A @ N (0이어야 함):")
print(np.round(A @ N, 10))12.0.2 Step 2: 랭크-1 분해 A = uvᵀ
import numpy as np
# 랭크-1 행렬
A = np.array([
[1, 3, 10],
[2, 6, 20],
[3, 9, 30]
], dtype=float)
print(f"랭크: {np.linalg.matrix_rank(A)}")
# uvᵀ 분해: u = 첫 번째 열 / u[0], vᵀ = 첫 번째 행
u = A[:, 0:1] # 열벡터 [1, 2, 3]ᵀ
vT = A[0:1, :] / A[0, 0] # 행벡터 [1, 3, 10]
print(f"\nu = {u.flatten()}")
print(f"vᵀ = {vT.flatten()}")
print(f"\nu @ vᵀ =\n{u @ vT}")
print(f"\nA - uvᵀ = {np.allclose(A, u @ vT)}") # True여야 함
# 일반 랭크-r 분해: A = (피벗 열들) × (R의 비零 행들)
A2 = np.array([
[1, 1, 2, 4],
[1, 2, 2, 5],
[1, 3, 2, 6]
], dtype=float)
R, pcols = full_rref(A2)
r = len(pcols)
U_cols = A2[:, pcols] # 피벗 열들 (열공간 기저)
R_rows = R[:r, :] # R의 비零 행들 (행공간 기저)
print(f"\n랭크-{r} 분해 검증:")
print(f"A ≈ (피벗 열들) × (R의 비零 행들): {np.allclose(A2, U_cols @ R_rows)}")12.0.3 Step 3: NumPy로 랭크 확인 및 시각화
import numpy as np
import matplotlib.pyplot as plt
# 랭크가 다른 행렬들의 singular value 비교
matrices = {
"랭크 3 (전랭크)": np.random.randn(4, 3),
"랭크 1": np.outer(np.array([1, 2, 3, 4]), np.array([1, 2, 3])),
"랭크 2": np.outer(np.array([1, 2, 3, 4]), np.array([1, 0, 0]))
+ np.outer(np.array([0, 1, 0, 1]), np.array([0, 1, 0])),
}
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
for ax, (name, M) in zip(axes, matrices.items()):
svs = np.linalg.svd(M, compute_uv=False)
ax.bar(range(1, len(svs) + 1), svs, color='steelblue')
ax.set_title(f"{name}\n랭크 = {np.linalg.matrix_rank(M)}")
ax.set_xlabel("특잇값 번호")
ax.set_ylabel("특잇값 크기")
ax.axhline(y=1e-10, color='red', linestyle='--', label='수치적 0')
plt.suptitle("랭크와 특잇값의 관계\n(0인 특잇값의 수 = 영공간 차원 = n - r)")
plt.tight_layout()
plt.show()13 핵심 정리
| 개념 | 내용 |
|---|---|
| 랭크 \(r\) | 피벗의 수 = 독립 행/열 수 = 열 공간 차원 |
| RREF \(\mathbf{R}\) | 피벗 = 1, 피벗 위아래 모두 0 → 유일함 |
| 피벗 열 | 이전 열들의 선형결합 아님 → 독립 |
| 자유 열 | 이전 피벗 열들의 선형결합 → 계수가 \(\mathbf{F}\) |
| 영공간 행렬 | \(\mathbf{N} = [-\mathbf{F};\ \mathbf{I}]\), \(\mathbf{R}\mathbf{N} = \mathbf{0}\) |
| 랭크-1 행렬 | \(\mathbf{A} = \mathbf{u}\mathbf{v}^\top\) (열 \(\times\) 행) |
| 랭크-\(r\) 분해 | \(\mathbf{A} = \sum_{i=1}^r \mathbf{u}_i \mathbf{v}_i^\top\) |
| \(n > m\) | \(r \leq m < n\) → 자유 변수 최소 \(n - m\) 개 → 비자명해 존재 |
14 관련 주제
선행 지식
후속 주제
- Ch.3 §3.4 — The Complete Solution to Ax = b — 특정해 + 영공간
- Ch.3 §3.5 — Independence, Basis, Dimension — 랭크 = 기저 수 = 차원
- Ch.3 §3.6 — Dimensions of the Four Subspaces — 차원 방정식 \(r + (n-r) = n\)
다른 카테고리 연결
- 투영과 최소자승법 — 랭크가 최소제곱 해의 유일성을 결정