4.1 張成與線性獨立:用圖形看空間#
本節目標#
- 建立 span(張成) 的幾何直覺:一組向量「能到達的全部區域」
- 用 係數掃描 實驗親眼看到:1 個向量張成直線、2 個向量張成平面(或退化成直線)
- 理解線性獨立 / 相依的幾何意義:共線、共面
- 學會用 秩(rank) 判斷線性獨立
- 實驗:把三個 3D 向量的 span 情況完整分類
span 的直覺:一組向量的「可達區域」#
給定一組向量 \(\mathbf{v}_1, \mathbf{v}_2, \ldots, \mathbf{v}_k\) ,它們的 張成(span) 是所有線性組合能到達的點的集合:
白話版:把每個向量當成「可以自由伸縮的箭頭」,係數 \(c_i\) 就是你對第 \(i\) 支箭頭的伸縮倍數(可以負、可以零)。 span 就是隨便伸縮、隨便相加之後,全部能踩到的地盤。
幾何上的三種命運(2D 中):
| 情況 | span 長什麼樣 |
|---|---|
| 一個非零向量 | 一條通過原點的 直線 |
| 兩個不共線向量 | 整個 平面 \(\mathbb{R}^2\) |
| 兩個共線向量 | 還是那條 直線(第二個向量沒幫上忙) |
關鍵字是「沒幫上忙」:如果新加入的向量落在舊向量的可達區域裡,地盤不會變大 —— 這正是線性相依的種子。
係數掃描實驗:親眼看 span#
與其背定義,不如動手掃:讓係數在 \([-2, 2]\) 之間大量取值,畫出所有線性組合的終點。
import numpy as np
import matplotlib.pyplot as plt
from linalg_viz import plot_vectors
np.random.seed(0)
def scan_span(vectors, n=400, lim=2.0):
"""對每個向量的係數均勻掃描,畫出所有線性組合的終點。"""
coefs = np.random.uniform(-lim, lim, size=(n, len(vectors)))
pts = coefs @ np.array(vectors) # (n, k) @ (k, dim) -> (n, dim)
return pts
# 情況 A:單一向量 -> 直線
v = np.array([2.0, 1.0])
pts = scan_span([v])
plt.figure(figsize=(5, 5))
plt.scatter(pts[:, 0], pts[:, 1], s=4, alpha=0.4)
plot_vectors([v], color="red")
plt.gca().set_aspect("equal"); plt.title("span{v}:一條直線")
plt.show()
# 情況 B:兩個不共線向量 -> 平面
u, w = np.array([2.0, 0.0]), np.array([1.0, 2.0])
pts = scan_span([u, w])
plt.figure(figsize=(5, 5))
plt.scatter(pts[:, 0], pts[:, 1], s=4, alpha=0.4)
plot_vectors([u, w], color=["red", "green"])
plt.gca().set_aspect("equal"); plt.title("span{u, w}:整個平面")
plt.show()
# 情況 C:兩個共線向量 -> 仍是直線
u2 = np.array([1.0, 1.0])
w2 = np.array([2.0, 2.0]) # 是 u2 的兩倍,沒有新地盤
pts = scan_span([u2, w2])
plt.figure(figsize=(5, 5))
plt.scatter(pts[:, 0], pts[:, 1], s=4, alpha=0.4)
plot_vectors([u2, w2], color=["red", "green"])
plt.gca().set_aspect("equal"); plt.title("span{u, 2u}:還是那條直線")
plt.show()
執行後你會看到:情況 A 的點密密地排成一條線;情況 B 的點糊成一片;情況 C 看起來和 A 一模一樣 —— 第二個向量 \(2\mathbf{u}\) 完全被 \(\mathbf{u}\) 吸收了。
線性獨立與相依:幾何版定義#
一組向量 線性獨立,代表其中沒有任何一個向量落在其他向量張成的空間裡; 換句話說,每一支箭頭都帶來「新的方向」。反之就是 線性相依。
幾何翻譯表:
| 向量個數 | 相依的幾何特徵 | 獨立的幾何特徵 |
|---|---|---|
| 2 個 | 共線(在同一直線上) | 不共線 |
| 3 個(在 3D) | 共線或共面(在同一平面上) | 不共面(撐起整個 3D 空間) |
用方程式說: \(\mathbf{v}_1, \ldots, \mathbf{v}_k\) 線性相依,代表存在不全為零的係數使得
例如 \(\mathbf{w}_2 = 2\mathbf{u}_2\) 時, \(2\mathbf{u}_2 - \mathbf{w}_2 = \mathbf{0}\) ,係數 \((2, -1)\) 不全為零 —— 相依成立。
用秩判斷獨立:把向量排成矩陣#
把向量當成矩陣的 行(或列),矩陣的秩就是 span 的維度:
def is_independent(*vectors):
"""用秩判斷一組向量是否線性獨立。"""
A = np.array(vectors).T # 每個向量一行
return np.linalg.matrix_rank(A) == A.shape[1]
print(is_independent([2, 0], [1, 2])) # True :撐起平面
print(is_independent([1, 1], [2, 2])) # False:共線
print(is_independent([1, 0, 0], [0, 1, 0], [1, 1, 0])) # False:共面(都在 z=0 平面)
print(is_independent([1, 0, 0], [0, 1, 0], [0, 0, 1])) # True :標準基
注意最後一個觀察:在 \(\mathbb{R}^n\) 中,超過 \(n\) 個向量必定相依。 因為秩最多只能到 \(n\) ,向量個數一超過 \(n\) ,秩就追不上了 —— 3 根火柴棒再怎麼擺,也無法在紙面上撐出第三個獨立方向。
實驗:三個 3D 向量的 span 分類器#
三個 3D 向量的 span 只有兩種可能:一個平面(rank 2,相依) 或 整個空間(rank 3,獨立)(若三個都共線則是直線,rank 1)。 我們寫一個完整分類器,並大量隨機測試:
def classify_span_3d(v1, v2, v3):
A = np.column_stack([v1, v2, v3])
r = np.linalg.matrix_rank(A)
return {1: "直線(三向量共線)",
2: "平面(三向量共面)",
3: "整個 R^3(線性獨立)"}[r]
cases = {
"共線": ([1, 2, 3], [2, 4, 6], [-1, -2, -3]),
"共面": ([1, 0, 0], [0, 1, 0], [1, 1, 0]), # 全在 z=0 平面
"獨立": ([1, 0, 0], [0, 1, 0], [0, 0, 1]),
}
for name, (a, b, c) in cases.items():
print(f"{name}: {classify_span_3d(np.array(a, float), np.array(b, float), np.array(c, float))}")
# 隨機 10000 組:三個隨機 3D 向量幾乎總是獨立!
from collections import Counter
counts = Counter()
for _ in range(10000):
vs = [np.random.randn(3) for _ in range(3)]
counts[classify_span_3d(*vs)] += 1
print(counts)
一個值得停一下的觀察:隨機三個 3D 向量幾乎總是線性獨立。 「共面」需要三支箭頭剛好被壓進同一個平面,這是一個機率為零的事件(除非你刻意設計)。 反之,如果你在 3D 裡拿 四個 隨機向量,它們就必定相依 —— 4 > 3,秩追不上個數。
# 3D 共面情況的視覺化:畫出三向量與它們所在的平面
from mpl_toolkits.mplot3d import Axes3D # noqa: F401
vs = [np.array([1., 0., 0.]), np.array([0., 1., 0.]), np.array([1., 1., 0.])]
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(projection="3d")
s, t = np.meshgrid(np.linspace(-2, 2, 10), np.linspace(-2, 2, 10))
ax.plot_surface(s, t, 0 * s, alpha=0.15, color="gray") # z=0 平面
for v in vs:
ax.quiver(0, 0, 0, *v, color=np.random.rand(3), arrow_length_ratio=0.1)
ax.set_box_aspect([1, 1, 1]); ax.set_title("三個共面向量")
plt.show()
小結與練習#
本節重點 1. span = 一組向量所有線性組合的可達區域:1 個向量是直線、2 個不共線向量是平面。 2. 線性相依 = 有向量落在其他向量的 span 裡(幾何上是共線 / 共面)。 3. 判斷獨立的實用工具:把向量排成矩陣, \(\mathrm{rank} = \text{個數} \iff\) 獨立。 4. \(\mathbb{R}^n\) 中超過 \(n\) 個向量必相依;隨機向量幾乎總是獨立。
練習 1. 用 scan_span 畫出 \(\mathrm{span}\{(1,2), (2,4)\}\) ,它應該是一條直線 —— 用 np.linalg.matrix_rank 驗證秩為 1。 2. 判斷 \((1,1,0)\) 、 \((0,1,1)\) 、 \((1,2,1)\) 是否線性獨立?先心算第三個是否為前兩個之和,再用程式驗證。 3. 寫一個實驗:在 2D 隨機取 3 個向量,統計它們 span 的分類結果,並解釋為什麼答案永遠只有一種。 4. (思考題)兩個向量若其中一個是零向量,它們的 span 與獨立性如何?