6.1 矩陣:把數字排成表格,讓計算變成一套規則#
本節目標#
- 理解矩陣是什麼、為什麼要發明矩陣
- 學會用 SymPy 的
Matrix()建構矩陣,並做加法、純量乘法、矩陣乘法 - 親手算一次 \(2 \times 3\) 乘 \(3 \times 2\) 的矩陣乘法,與電腦結果對照
- 認識常用的特殊矩陣:
eye()、zeros()、ones() - 用實驗驗證「矩陣乘法不滿足交換律」
矩陣是什麼?#
矩陣(matrix)就是把數字排成長方形的表格。一個 \(m \times n\) 矩陣有 \(m\) 列、 \(n\) 行:
但矩陣不只是表格——它是線性變換的編碼,也是聯立方程組的壓縮。例如方程組
可以壓縮成 \(A\mathbf{x} = \mathbf{b}\) ,其中 \(A = \begin{pmatrix} 2 & 3 \\ 1 & -1 \end{pmatrix}\) 、 \(\mathbf{x} = \begin{pmatrix} x \\ y \end{pmatrix}\) 、 \(\mathbf{b} = \begin{pmatrix} 8 \\ -1 \end{pmatrix}\) 。
一旦方程組變成 \(A\mathbf{x} = \mathbf{b}\) ,我們就能用同一套規則處理所有方程組,這正是矩陣的威力。
用 Matrix() 建構矩陣#
from sympy import Matrix
# 用「列的串列」建構:每個內層串列是一列
A = Matrix([[2, 3],
[1, -1]])
print(A)
# 也可以只給一層串列,SymPy 會當成「行向量」(直的)
v = Matrix([1, 2])
print(v)
查詢矩陣的形狀與取元素:
print(A.shape) # (2, 2):2 列 2 行
print(A[0, 0]) # 2:注意索引從 0 開始!
print(A[1, 0]) # 1:第 2 列、第 1 行
print(A[:, 0]) # 取出第 1 行:Matrix([[2], [1]])
print(A[0, :]) # 取出第 1 列:Matrix([[2, 3]])
A[i, j] 的順序是「列在前、行在後」,就像座標 \((y, x)\) 一樣,初學者最常在這裡搞混,請多寫幾次確認。
矩陣加法與純量乘法#
兩個同形狀的矩陣可以相加:對應元素相加。矩陣可以乘上一個數(純量):每個元素都乘上那個數。
from sympy import Matrix, Rational
B = Matrix([[1, 2], [3, 4]])
C = Matrix([[5, 6], [7, 8]])
print(B + C) # Matrix([[6, 8], [10, 12]])
print(2 * B) # Matrix([[2, 4], [6, 8]])
print(B - C) # Matrix([[-4, -4], [-4, -4]])
# 純量也可以是符號或精確分數
from sympy import Symbol
k = Symbol('k')
print(k * B) # Matrix([[k, 2*k], [3*k, 4*k]])
print(Rational(1, 2) * B) # Matrix([[1/2, 1], [3/2, 2]])
矩陣乘法:手算一次再對照電腦#
矩陣乘法不像加法那麼直覺。 \(m \times n\) 矩陣乘上 \(n \times p\) 矩陣,得到 \(m \times p\) 矩陣,其中結果的第 \(i\) 列第 \(j\) 行元素,是「左矩陣的第 \(i\) 列」與「右矩陣的第 \(j\) 行」的對應相乘再相加(內積)。
我們來手算一個 \(2 \times 3\) 乘 \(3 \times 2\) 的例子:
結果的每個元素:
- \(c_{11} = 1 \cdot 7 + 2 \cdot 9 + 3 \cdot 11 = 7 + 18 + 33 = 58\)
- \(c_{12} = 1 \cdot 8 + 2 \cdot 10 + 3 \cdot 12 = 8 + 20 + 36 = 64\)
- \(c_{21} = 4 \cdot 7 + 5 \cdot 9 + 6 \cdot 11 = 28 + 45 + 66 = 139\)
- \(c_{22} = 4 \cdot 8 + 5 \cdot 10 + 6 \cdot 12 = 32 + 50 + 72 = 154\)
用 SymPy 驗證:
from sympy import Matrix
A = Matrix([[1, 2, 3],
[4, 5, 6]])
B = Matrix([[7, 8],
[9, 10],
[11, 12]])
print(A.shape, B.shape) # (2, 3) (3, 2):內側維度相同,可以相乘
print(A * B) # Matrix([[58, 64], [139, 154]])
print((A * B).shape) # (2, 2)
一個容易忽略的細節:A * B 在 SymPy 中就是矩陣乘法(不是逐元素相乘)。若想做逐元素乘法(Hadamard 積),要用 A.multiply_elementwise(B)。
常用的特殊矩陣#
from sympy import eye, zeros, ones, Matrix
print(eye(3)) # 3x3 單位矩陣:對角線是 1,其他是 0
print(zeros(2, 3)) # 2x3 全零矩陣
print(ones(2, 2)) # 2x2 全 1 矩陣
輸出:
Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
Matrix([[0, 0, 0], [0, 0, 0]])
Matrix([[1, 1], [1, 1]])
單位矩陣 \(I\) 在矩陣世界裡扮演「1」的角色:任何矩陣乘上大小相符的單位矩陣都不變。
I3 = eye(3)
A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]])
print(A * I3 == A) # True
print(I3 * A == A) # True
轉置#
轉置(transpose)把矩陣的「列變行、行變列」,記作 \(A^T\) :
from sympy import Matrix
A = Matrix([[1, 2, 3], [4, 5, 6]])
print(A.T) # Matrix([[1, 4], [2, 5], [3, 6]])
print(A.T.shape) # (3, 2)
# 轉置的轉置回到原矩陣
print(A.T.T == A) # True
轉置有兩個重要恆等式(可以自己用 SymPy 驗證):
注意 \((AB)^T\) 是反過來的,這一點在 6.4 節推導最小平方法時會用到。
動手實驗:矩陣乘法滿足交換律嗎?#
實數乘法滿足交換律: \(3 \times 5 = 5 \times 3\) 。矩陣乘法呢?讓我們直接測試:
from sympy import Matrix
A = Matrix([[1, 2],
[0, 1]])
B = Matrix([[1, 0],
[3, 1]])
print(A * B) # Matrix([[7, 2], [3, 1]])
print(B * A) # Matrix([[1, 2], [3, 5]])
print(A * B == B * A) # False ← 不交換!
更系統化地,用隨機矩陣大量測試:
import random
from sympy import Matrix
count = 0
for _ in range(100):
A = Matrix(2, 2, lambda i, j: random.randint(-5, 5))
B = Matrix(2, 2, lambda i, j: random.randint(-5, 5))
if A * B != B * A:
count += 1
print(f"100 組隨機矩陣中有 {count} 組 A*B != B*A")
執行後你會發現:幾乎每一組都不相等。能交換的矩陣是少數特例(例如單位矩陣、或 \(A\) 自己乘自己)。
再做一個實驗確認「形狀不合就不能交換」:
A = Matrix([[1, 2, 3], [4, 5, 6]]) # 2x3
B = Matrix([[1, 0], [0, 1], [1, 1]]) # 3x2
print((A * B).shape) # (2, 2):可以乘
try:
B * A # 3x2 乘 2x3 其實也可以,得到 3x3!
print((B * A).shape) # (3, 3):形狀都不同了,怎麼可能相等
except Exception as e:
print(e)
為什麼不交換? 直觀地說,矩陣代表「變換」: \(AB\) 是「先做 \(B\) 、再做 \(A\) 」的複合變換。「先旋轉再平移」和「先平移再旋轉」結果不同——順序當然重要。
小結與練習#
本節重點:
- 矩陣是把數字排成表格的物件,能壓縮聯立方程組、編碼線性變換
Matrix([[...], [...]])逐列建構;A[i, j]取元素,索引從 0 開始- 加法對應元素相加;矩陣乘法是「列乘行」的內積,形狀 \((m \times n)(n \times p) \to m \times p\)
eye()單位矩陣、zeros()零矩陣、ones()全 1 矩陣A.T轉置,且 \((AB)^T = B^T A^T\)- 矩陣乘法不滿足交換律
練習:
- 用 SymPy 建構 \(A = \begin{pmatrix} 2 & 0 \\ 1 & 3 \end{pmatrix}\) 、 \(B = \begin{pmatrix} 1 & 1 \\ 0 & 2 \end{pmatrix}\) ,計算 \(A B\) 與 \(B A\) ,並驗證兩者不相等。
- 手算 \(\begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}\) ,再用 SymPy 對照。你觀察到這個右乘矩陣對 \(A\) 產生了什麼效果?(提示:看行的變化)
- 驗證轉置恆等式 \((AB)^T = B^T A^T\) :任取兩個 \(2 \times 2\) 矩陣,用
==檢查兩邊是否相等。 - 建構 \(A = \begin{pmatrix} 1 & 2 \\ 2 & 4 \end{pmatrix}\) ,計算 \(A \cdot \begin{pmatrix} 2 \\ -1 \end{pmatrix}\) 與 \(A \cdot \begin{pmatrix} 1 \\ -2 \end{pmatrix}\) ,你發現了什麼?這和 6.3 節的特徵向量有關。
- 寫一個迴圈,找出所有滿足 \(A B = B A\) 的 \(2 \times 2\) 矩陣對(其中 \(A\) 固定為 \(\begin{pmatrix} 1 & 1 \\ 0 & 1 \end{pmatrix}\) , \(B\) 的元素取 \(0, 1, 2\) ),觀察這些 \(B\) 有什麼共同特徵。