矩阵变换:把空间重塑成想要的形状 本节摘要:一个矩阵就是一台「重塑空间的机器」——只要搞清它对每一个点做了什么,你就理解了整个变换。本节把矩阵当几何对象来对待:旋转矩阵沿圆弧搬运点,缩放矩阵沿各轴拉伸或压缩,剪切矩阵把矩形扭成平行四边形,反射矩阵把空间翻面。多个变换可以复合,但矩阵乘法不交换——「先转再缩」与「先缩再转」结果不同。我们还会触及线性代数里最深刻的概念:特征向量(Eigenvector)是矩阵作用下「只缩放、不旋转」的特殊方向,特征值(Eigenvalue)是该缩放因子。它们决定 PCA 的主方向、RNN 的稳定性、谱聚类的图结构。最后用 2×2 矩阵从零解特征方程、做特征分解,看到 如何把一个变换拆成「转到特征坐标 → 沿轴缩放 → 转回来」三步。
本节摘要:一个矩阵就是一台「重塑空间的机器」——只要搞清它对每一个点做了什么,你就理解了整个变换。本节把矩阵当几何对象来对待:旋转矩阵沿圆弧搬运点,缩放矩阵沿各轴拉伸或压缩,剪切矩阵把矩形扭成平行四边形,反射矩阵把空间翻面。多个变换可以复合,但矩阵乘法不交换——「先转再缩」与「先缩再转」结果不同。我们还会触及线性代数里最深刻的概念:**特征向量(Eigenvector)**是矩阵作用下「只缩放、不旋转」的特殊方向,**特征值(Eigenvalue)**是该缩放因子。它们决定 PCA 的主方向、RNN 的稳定性、谱聚类的图结构。最后用 2×2 矩阵从零解特征方程、做特征分解,看到
A = V·D·V⁻¹如何把一个变换拆成「转到特征坐标 → 沿轴缩放 → 转回来」三步。
对应原课程:Phase 01 · Lesson 03 ·
matrix-transformations(原英文phases/01-math-foundations/03-matrix-transformations/docs/en.md)。前置:第 1~2 节。
阅读完本节,你应当能够:
你读到 PCA,看到「求协方差矩阵的特征向量」;你读模型稳定性,看到「检查所有特征值的模是否小于 1」;你读数据增强,看到「施加一个随机旋转」。如果不理解矩阵对空间做了什么,这些都毫无意义。
矩阵不仅是数的网格,它们是空间机器。本节就让这些操作变得具体。
2D 中的每个线性变换都能写成一个 2×2 矩阵。矩阵的列就是基向量 [1,0] 和 [0,1] 变换后的新位置,其余一切都由此推出。
2D 旋转 θ 角保持距离与夹角不变,把每个点沿圆弧移动。
R(θ) = | cos θ -sin θ | | sin θ cos θ |
3D 中绕轴旋转,每个轴有各自的旋转矩阵(绕 z 转,xy 平面旋转、z 不动;余类推):
Rz(θ) = | cos -sin 0 | Rx(θ) = | 1 0 0 | Ry(θ) = | cos 0 sin | | sin cos 0 | | 0 cos -sin | | 0 1 0 | | 0 0 1 | | 0 sin cos | | -sin 0 cos |
缩放沿每个轴独立地拉伸或压缩:S = diag(sx, sy)。
剪切让一个轴倾斜、另一个轴保持不动,把矩形扭成平行四边形。
Shx = [[1, k], [0, 1]]:x 按 k·y 平移;Shy = [[1, 0], [k, 1]]:y 按 k·x 平移。反射把点关于某轴或某直线镜像。
[[-1, 0], [0, 1]];[[1, 0], [0, -1]]。先做 A 再做 B,等价于把它们矩阵相乘:result = B @ A @ point。顺序至关重要。
复合矩阵 S @ R = [[0, -2], [0.5, 0]]。
复合矩阵 R @ S = [[0, -0.5], [2, 0]]。结果不同——矩阵乘法不可交换。
大多数向量在矩阵作用下会改变方向。特征向量很特殊:矩阵只缩放它们、不旋转。缩放因子就是特征值。
A @ v = λ · v
例子:A = [[2, 1], [1, 2]]
A@[1,1] = [3,3] = 3·[1,1](同向、放大 3 倍);A@[1,-1] = [1,-1] = 1·[1,-1](同向、不变)。矩阵沿 [1,1] 方向把空间拉伸 3 倍,沿 [1,-1] 方向保持不变。其他任何方向都是这两个方向的混合。
若矩阵有 n 个线性无关特征向量,可分解为:
A = V @ D @ V⁻¹ V = 以特征向量为列的矩阵 D = 以特征值为对角元的对角矩阵 V⁻¹ = V 的逆
含义:转到特征向量坐标系 → 沿每个轴缩放 → 转回来。
det = 1 : 面积不变(旋转) det = 2 : 面积加倍 det = 0 : 空间被压扁到低维(奇异) det = -1: 面积不变但朝向翻转(反射) |det(旋转)| = 1 |det(缩放 sₓ,s_y)| = sₓ · s_y |det(剪切)| = 1 |det(反射)| = -1
完整源码见 phases/01-math-foundations/03-matrix-transformations/code/。
def rotation_2d(theta): c, s = math.cos(theta), math.sin(theta) return [[c, -s], [s, c]] def scaling_2d(sx, sy): return [[sx, 0], [0, sy]] def shearing_2d(kx, ky): return [[1, kx], [ky, 1]] def reflection_y(): return [[-1, 0], [0, 1]]
R = rotation_2d(math.pi / 2) S = scaling_2d(2, 0.5) rotate_then_scale = mat_mul(S, R) # 先 R 后 S scale_then_rotate = mat_mul(R, S) # 先 S 后 R point = [1.0, 0.0] r1 = mat_vec_mul(rotate_then_scale, point) r2 = mat_vec_mul(scale_then_rotate, point) # r1 ≠ r2 —— 矩阵乘法不可交换
对 [[a,b],[c,d]],特征值满足特征方程 λ² - (a+d)λ + (ad−bc) = 0:
def eigenvalues_2x2(matrix): a, b = matrix[0]; c, d = matrix[1] trace = a + d det = a*d - b*c disc = trace**2 - 4*det if disc < 0: # 复特征值(如纯旋转) real = trace / 2 imag = (-disc) ** 0.5 / 2 return (complex(real, imag), complex(real, -imag)) sq = disc ** 0.5 return ((trace + sq)/2, (trace - sq)/2)
对应特征向量:解 (A − λI)v = 0,归一化即得。
设计要点:判别式为负时返回复特征值——这正是 90° 旋转矩阵
[[0,-1],[1,0]]特征值为 ±i 的来源,它没有实特征方向。
NumPy 用优化例程一行完成所有事:
import numpy as np theta = np.pi / 4 R = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) print(R @ np.array([1.0, 0.0])) # 旋转点 S = np.diag([2.0, 3.0]) # 缩放矩阵 print((S @ R) @ np.array([1.0,0.0])) # 先转后缩 A = np.array([[2, 1], [1, 2]], dtype=float) vals, vecs = np.linalg.eig(A) # 特征值、特征向量(列为向量) print(vals); print(vecs) # 特征分解与重建 D = np.diag(vals); V = vecs print(V @ D @ np.linalg.inv(V)) # ≈ A
3D 旋转同理——把二维 [[c,-s],[s,c]] 嵌入对应坐标平面即可。
💡
np.linalg.eig返回的特征向量是按列排列的(vecs[:, i]对应vals[i]),这是初学者最常踩的坑。
本节为后续 PCA(第 3 章)与神经网络权重分析奠定几何地基。本节实现的「特征值/特征向量」算法,正是生产级 ML 系统里降维、谱聚类、稳定性分析所用的同一套思路——只是底层换成了 LAPACK 优化的 np.linalg.eig。
[[4,2],[1,3]] 的特征值(用特征方程),再用自研函数与 NumPy 对照。A = V·D·V⁻¹:把变换拆成「转坐标—沿轴缩放—转回来」。下一节,我们离开离散的线性代数,进入连续的世界——微积分:导数、偏导、梯度,以及它们如何驱动神经网络的训练。