跳轉到

4.1 張成與線性獨立:用圖形看空間#

本節目標#

  • 建立 span(張成) 的幾何直覺:一組向量「能到達的全部區域」
  • 用 係數掃描 實驗親眼看到:1 個向量張成直線、2 個向量張成平面(或退化成直線)
  • 理解線性獨立 / 相依的幾何意義:共線、共面
  • 學會用 秩(rank) 判斷線性獨立
  • 實驗:把三個 3D 向量的 span 情況完整分類

span 的直覺:一組向量的「可達區域」#

給定一組向量 \(\mathbf{v}_1, \mathbf{v}_2, \ldots, \mathbf{v}_k\) ,它們的 張成(span) 是所有線性組合能到達的點的集合:

\[ \mathrm{span}\{\mathbf{v}_1, \ldots, \mathbf{v}_k\} = \{ c_1\mathbf{v}_1 + c_2\mathbf{v}_2 + \cdots + c_k\mathbf{v}_k \;:\; c_i \in \mathbb{R} \} \]

白話版:把每個向量當成「可以自由伸縮的箭頭」,係數 \(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\) 線性相依,代表存在不全為零的係數使得

\[ c_1\mathbf{v}_1 + c_2\mathbf{v}_2 + \cdots + c_k\mathbf{v}_k = \mathbf{0} \]

例如 \(\mathbf{w}_2 = 2\mathbf{u}_2\) 時, \(2\mathbf{u}_2 - \mathbf{w}_2 = \mathbf{0}\) ,係數 \((2, -1)\) 不全為零 —— 相依成立。


用秩判斷獨立:把向量排成矩陣#

把向量當成矩陣的 行(或列),矩陣的秩就是 span 的維度:

\[ \text{向量們線性獨立} \iff \mathrm{rank} = \text{向量個數} \]
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 與獨立性如何?