读完这一课,你将能够
- 说出内积的三条公理,并解释长度 \(\|a\|=\sqrt{\langle a,a\rangle}\) 与夹角为何都由内积派生。
- 心算同一向量的 L1 / L2 / L∞ 范数,并说清"圆把权重收小、尖角把权重清零"为何对应 L2 与 L1 正则。
- 用 \(\operatorname{proj}_a(b)=\dfrac{a\cdot b}{\|a\|^2}a\) 手算投影与残差,并验证残差与 \(a\) 正交。
- 把"最小二乘"翻译成"把 \(b\) 投影到列空间",并由"残差 ⊥ 列空间"推出正规方程 \(A^\top Aw=A^\top b\)。
- 用 NumPy 解直线拟合,验证残差与每个特征列正交、投影矩阵 \(P\) 幂等。
1. 开场:给空间装上"尺子"和"量角器"
上一课我们学会把矩阵看成线性变换 linear transformation——它把整个空间拉伸、旋转、剪切。但变换前后,我们还缺一样东西:度量。两个向量有多长?它们之间夹角多大?谁离谁更近?谁和谁垂直?这些"几何问题",统统由一个运算回答——内积 inner product。
把内积想象成空间的"地基协议":一旦约定了内积,长度(范数)和角度(夹角)就被一并确定了。本课的主线是:内积 → 范数(长度的不同定义)→ 正交(垂直)→ 投影(把一个向量"压"到另一个方向或子空间上)。而投影,正是最小二乘 least squares 和线性回归的几何心脏。
2. 内积:定义、公理与几何意义
2.1 从点积说起
上一模块我们见过两个向量 \(a=[a_1,\dots,a_n]\) 与 \(b=[b_1,\dots,b_n]\) 的点积 dot product:
\[ a\cdot b \;=\; a^\top b \;=\; \sum_{i=1}^{n} a_i b_i. \]它的几何意义是这条核心公式(请把它刻进脑子):
\[ a\cdot b \;=\; \|a\|\,\|b\|\cos\theta, \]其中 \(\theta\) 是两向量的夹角。点积同时编码了长度和方向一致程度:同向为正、垂直为零、反向为负。
2.2 内积的三条公理
"点积"是 \(\mathbb{R}^n\) 上最常用的内积,但数学家把内积抽象成三条公理——任何满足这三条的运算 \(\langle a,b\rangle\) 都配叫内积,都能据此定义长度和角度(本课默认在实向量空间 \(\mathbb{R}^n\) 上讨论;复数域上的内积需对一个参数取共轭,是后话):
| 公理 | 含义 | 公式 |
|---|---|---|
| 对称 symmetric | 交换两个参数不变 | \(\langle a,b\rangle=\langle b,a\rangle\) |
| 线性 linear | 对第一个参数线性(可加、可提系数) | \(\langle \alpha a+\beta c,\,b\rangle=\alpha\langle a,b\rangle+\beta\langle c,b\rangle\) |
| 正定 positive-definite | 自己和自己内积非负,且只有零向量为零 | \(\langle a,a\rangle\ge 0\),等号 \(\iff a=0\) |
这里只写了对第一个参数线性,是因为有了对称性,对第二个参数的线性可以白送地推出来(把两个参数换个位置即可),所以只需写一边。两个参数都线性的性质合称双线性 bilinear。对标准点积,这三条都是显然的:交换求和顺序得对称;求和对加法和数乘线性;而 \(\langle a,a\rangle=\sum a_i^2\ge 0\) 且仅当所有 \(a_i=0\) 才为零——这正是"正定",它保证了"长度永远非负、只有零向量长度为零"这件天经地义的事。
要点
内积 = 满足对称 + 线性 + 正定的运算。有了它,长度定义为 \(\|a\|=\sqrt{\langle a,a\rangle}\),夹角定义为 \(\cos\theta=\dfrac{\langle a,b\rangle}{\|a\|\,\|b\|}\)。度量与几何,都是内积的派生物。
3. 范数:长度的多种定义
范数 norm \(\|x\|\) 是"向量长度"的一般化,它给每个向量一个非负实数,满足:非负(\(\|x\|\ge0\),仅零向量为零)、齐次(\(\|\alpha x\|=|\alpha|\,\|x\|\))、三角不等式(\(\|x+y\|\le\|x\|+\|y\|\))。同一个向量,可以用不同的"尺子"量出不同的长度:
| 名称 | 记号 | 定义 | 直觉 |
|---|---|---|---|
| L1 范数(曼哈顿) | \(\|x\|_1\) | \(\sum_i |x_i|\) | 沿坐标轴走的"街区距离" |
| L2 范数(欧几里得) | \(\|x\|_2\) | \(\sqrt{\sum_i x_i^2}\) | 直线距离,由点积导出 \(\sqrt{x^\top x}\) |
| L∞ 范数(最大值) | \(\|x\|_\infty\) | \(\max_i |x_i|\) | 最大的那个分量说了算 |
| Frobenius 范数(矩阵) | \(\|A\|_F\) | \(\sqrt{\sum_{i,j} A_{ij}^2}\) | 把矩阵摊平成长向量后的 L2 |
例题:同一向量的三种范数
设 \(v=[3,-4,0,12]\)。
- \(\|v\|_1=|3|+|{-4}|+|0|+|12|=3+4+0+12=\mathbf{19}\)。
- \(\|v\|_2=\sqrt{3^2+(-4)^2+0^2+12^2}=\sqrt{9+16+0+144}=\sqrt{169}=\mathbf{13}\)。
- \(\|v\|_\infty=\max(3,4,0,12)=\mathbf{12}\)。
对矩阵 \(M=\begin{bmatrix}1&2\\2&1\end{bmatrix}\),\(\|M\|_F=\sqrt{1^2+2^2+2^2+1^2}=\sqrt{10}\approx 3.162\)。
3.1 单位球:菱形 / 圆 / 正方形
理解范数差异的最好方式,是画出每把尺子下"长度恰好为 1"的所有点——它们构成该范数的单位球 unit ball(在二维就是一条单位圈的边界)。三者形状迥异:
- L1:菱形(正方形旋转 45°)。\(|x_1|+|x_2|=1\) 在四个坐标轴方向顶到最远,尖角恰好落在坐标轴上。
- L2:圆。\(x_1^2+x_2^2=1\),各方向完全平等、光滑无尖角。
- L∞:正方形(边平行于坐标轴)。\(\max(|x_1|,|x_2|)=1\),四条边在 \(\pm1\) 处。
一个稳定的包含关系:\(\|x\|_\infty\le\|x\|_2\le\|x\|_1\)(同一向量,L∞ 最小、L1 最大),对应单位球"L1 菱形 ⊂ L2 圆 ⊂ L∞ 正方形"的嵌套。
这两句话方向看似相反,其实不矛盾,恰恰是同一件事的两面:某把尺子量出的数越大,要凑够"长度 = 1"就越省料、向量越短,于是它的单位球反而越小、越往里缩。所以 L1(同一向量量出的数最大)的菱形最小、最靠内,L∞(量出的数最小)的正方形最大、最靠外。把这个"反直觉"想透,正是真正理解范数差异的钩子。
ML 和 ML 的联系:范数 = 正则化的几何
训练模型时常给损失加一个"惩罚权重大小"的正则项 regularization,用的就是范数:
- L2 正则(权重衰减 weight decay / 岭回归 ridge):加 \(\lambda\|w\|_2^2\)。它的等高线是圆,把权重均匀地往原点收缩,使权重整体变小、变平滑,但很少正好为零。
- L1 正则(Lasso):加 \(\lambda\|w\|_1\)。菱形的尖角恰好长在坐标轴上,损失等高线最容易在这些尖角处与约束相切——而尖角意味着某些坐标分量为 0。于是 L1 产生稀疏 sparsity:很多权重被精确压成零,相当于自动做特征选择。
一句话记忆:圆把权重收小,尖角把权重清零。
4. 单位向量与归一化
长度为 1 的向量叫单位向量 unit vector。把任意非零向量 \(v\) 除以它自己的(L2)长度,就得到同方向的单位向量,这一步叫归一化 normalization:
\[ \hat v \;=\; \frac{v}{\|v\|_2}, \qquad \|\hat v\|_2 = 1. \]归一化"丢掉长度、只保留方向"。它在 ML 里无处不在:余弦相似度先把向量归一化再比方向;批归一化 / 层归一化把激活值缩放到统一尺度;嵌入向量常被归一化到单位球面上以便比较。
易错
"归一化"默认指除以 L2 范数得到单位长度,别和"标准化 standardization(减均值除标准差)"混为一谈——后者是对数据集每个特征做的统计变换,不是把单个向量缩到长度 1。
5. 正交:垂直的代数判据
当 \(\cos\theta=0\) 即 \(\theta=90^\circ\) 时,由 \(a\cdot b=\|a\|\|b\|\cos\theta\) 立刻得到最简洁的正交 orthogonal判据:
\[ a \perp b \iff a^\top b = 0. \]无需画图、无需算角度——点积为零就是垂直。两个推广概念:
- 正交基 orthogonal basis:一组互相垂直的基向量。
- 标准正交基 orthonormal basis:互相垂直且每个都是单位向量。若把它们排成矩阵 \(Q\) 的列,则 \(Q^\top Q = I\)(每列自己点积为 1,不同列点积为 0)。这种矩阵叫正交矩阵,它代表纯旋转 / 反射,不改变长度和角度——是数值上最"乖"的变换。
为什么人人都爱标准正交基?因为在它下面,向量 \(b\) 沿第 \(i\) 个基方向的坐标就是简单的点积 \(q_i^\top b\),不用解方程组。坐标提取从"求逆"退化成"做内积"——这就是后面投影公式会变得无比干净的原因。
6. 投影:把一个向量压到另一个方向上
给定方向 \(a\) 和目标 \(b\),我们想找 \(b\) 落在 \(a\) 这条直线上的"影子"。把 \(b\) 分解成两部分:沿 \(a\) 的分量 + 垂直于 \(a\) 的残差 residual。
标量投影 scalar projection(影子的带符号长度):
\[ \text{comp}_a(b) = \frac{a\cdot b}{\|a\|} = \|b\|\cos\theta. \]投影向量 projection vector(影子本身,方向沿 \(a\)):
\[ \operatorname{proj}_a(b) = \frac{a\cdot b}{\|a\|^2}\,a. \]关键性质:残差 \(r=b-\operatorname{proj}_a(b)\) 与 \(a\) 正交。因为投影定义的本意就是"沿 \(a\) 走到离 \(b\) 最近的点",而到直线的最短距离一定是垂直落下的——这就是投影与最小化误差之间的纽带,下一节我们会把它放大成最小二乘。
例题:把 \(b=[3,4]\) 投影到 \(a=[2,1]\)
第 1 步,点积:\(a\cdot b = 2\cdot3 + 1\cdot4 = 6+4 = 10\)。
第 2 步,分母 \(\|a\|^2 = 2^2+1^2 = 5\)。
第 3 步,标量系数 \(c=\dfrac{a\cdot b}{\|a\|^2}=\dfrac{10}{5}=2\)。
第 4 步,投影向量 \(\operatorname{proj}_a(b)=c\,a = 2\cdot[2,1]=[4,2]\)。
第 5 步,残差 \(r=b-\operatorname{proj}_a(b)=[3,4]-[4,2]=[-1,2]\)。
验证正交:\(r\cdot a=(-1)(2)+(2)(1)=-2+2=0\) ✓。残差确实垂直于 \(a\)。
顺带,标量投影(影子长度)\(=\dfrac{a\cdot b}{\|a\|}=\dfrac{10}{\sqrt5}=2\sqrt5\approx4.472\)。这里 \(a\cdot b=10>0\),影子和 \(a\) 同向,所以是正值。"带符号"这件事别忘了:如果换一个与 \(a\) 成钝角的目标,例如 \(b'=[-3,-1]\),则 \(a\cdot b'=2\cdot(-3)+1\cdot(-1)=-7<0\),标量投影为负,说明影子指向 \(a\) 的反方向。
6.1 投影到子空间:投影矩阵
把"一条直线"换成"一个子空间"(比如某矩阵 \(A\) 的列空间 column space,即 \(A\) 各列张成的平面/超平面),投影公式从标量推广成矩阵:
\[ P = A\,(A^\top A)^{-1} A^\top, \qquad \operatorname{proj}_{\text{col}(A)}(b) = P\,b. \]这里要求 \(A\) 的列线性无关,\(A^\top A\) 才可逆(否则得改用伪逆 / SVD,第 7 节末尾会再提一句)。别被它吓到,把它和单数版本对照就懂了:单向量时 \(\operatorname{proj}_a(b)=a\,(a^\top a)^{-1}a^\top b\)(这里 \(a^\top a=\|a\|^2\) 是个标量),矩阵版只是把标量 \(\|a\|^2\) 换成了矩阵 \(A^\top A\)。直觉拆解:
- \(A^\top b\):把 \(b\) 和每个列向量做内积,量出"在各列方向上有多少分量"。
- \((A^\top A)^{-1}\):修正各列之间不正交、不等长带来的"串扰"。
- 左乘 \(A\):用修正后的系数把这些列向量加回去,得到真正落在列空间里的影子。
投影矩阵有两个漂亮性质:幂等 idempotent \(P^2=P\)(影子再投影还是它自己——已经在子空间里了)和 \(P^\top=P\)(对称)。若 \(A\) 的列本就标准正交(\(A^\top A=I\)),公式直接坍缩成 \(P=AA^\top\)——这又一次印证了"标准正交基让一切变简单"。
7. 最小二乘:把目标投影到列空间
现在到本课的高潮。我们想解 \(A w = b\),但现实里 \(b\) 几乎从不恰好落在 \(A\) 的列空间里(数据有噪声、方程比未知数多)。于是退而求其次:找 \(w\) 让 \(Aw\) 尽量接近 \(b\),即最小化误差的 L2 长度
\[ \min_{w}\ \|A w - b\|_2^2. \]几何上,\(Aw\) 只能在列空间这张"平面"上滑动,而 \(b\) 通常悬在平面外。离 \(b\) 最近的平面内的点,就是 \(b\) 在列空间上的投影——此时误差向量(残差)必须垂直于整个列空间:
\[ A^\top (b - A w) = 0 \;\Longrightarrow\; A^\top A\, w = A^\top b \;\Longrightarrow\; \boxed{\,w = (A^\top A)^{-1} A^\top b\,}. \]这就是大名鼎鼎的正规方程 normal equations。"normal"在数学里正是"垂直"的意思——它说的就是"残差与列空间正交"这一句几何事实。把 \(w\) 代回 \(Aw=A(A^\top A)^{-1}A^\top b=Pb\),正好是上一节的投影矩阵。最小二乘 = 投影到列空间,两件事是同一件事的代数面与几何面。
例题:用正规方程拟合一条直线
四个点 \((0,1),(1,3),(2,4),(3,6)\),拟合 \(y=w_0+w_1 x\)。把每个点代入,写成 \(Xw=y\)(行=一个样本,第一列是常数项 1,第二列是 \(x\)):
\[ X=\begin{bmatrix}1&0\\1&1\\1&2\\1&3\end{bmatrix},\quad y=\begin{bmatrix}1\\3\\4\\6\end{bmatrix}. \]第 1 步,\(X^\top X=\begin{bmatrix}4&6\\6&14\end{bmatrix}\)(左上 = 4 个 1 的平方和;右下 = \(0^2+1^2+2^2+3^2=14\);非对角 = \(0+1+2+3=6\))。
第 2 步,\(X^\top y=\begin{bmatrix}1+3+4+6\\0+3+8+18\end{bmatrix}=\begin{bmatrix}14\\29\end{bmatrix}\)。
第 3 步,求逆。这里用到 2×2 矩阵的求逆公式 \(\begin{bmatrix}a&b\\c&d\end{bmatrix}^{-1}=\dfrac{1}{ad-bc}\begin{bmatrix}d&-b\\-c&a\end{bmatrix}\)(行列式 determinant 见上一模块;更高维时不手算逆,直接交给 np.linalg.solve 或 lstsq)。行列式 \(\det=4\cdot14-6\cdot6=56-36=20\),于是 \((X^\top X)^{-1}=\dfrac{1}{20}\begin{bmatrix}14&-6\\-6&4\end{bmatrix}\)。
第 4 步,\(w=\dfrac{1}{20}\begin{bmatrix}14&-6\\-6&4\end{bmatrix}\begin{bmatrix}14\\29\end{bmatrix}=\dfrac{1}{20}\begin{bmatrix}14\cdot14-6\cdot29\\-6\cdot14+4\cdot29\end{bmatrix}=\dfrac{1}{20}\begin{bmatrix}22\\32\end{bmatrix}=\begin{bmatrix}1.1\\1.6\end{bmatrix}.\)
所以拟合直线是 \(y=1.1+1.6x\)。预测值 \([1.1,2.7,4.3,5.9]\),残差 \([-0.1,0.3,-0.3,0.1]\)。验证残差与两列正交:\(\sum r_i=(-0.1+0.3-0.3+0.1)=0\),\(\sum r_i x_i=0\cdot(-0.1)+1\cdot0.3+2\cdot(-0.3)+3\cdot0.1=0.3-0.6+0.3=0\) ✓。
ML 和 ML 的联系:这几乎就是整个线性回归
- 线性回归 linear regression 的解析解就是上面的正规方程 \(w=(X^\top X)^{-1}X^\top y\),其中数据矩阵 \(X\) 每行一个样本(与本课程数据约定一致)。
- L2 损失(均方误差 MSE) \(\|Xw-y\|_2^2\) 的几何意义,正是"把标签向量 \(y\) 投影到特征列空间"。你之后训练的每个回归头、每条线性探针,背后都是这张投影图。
- 余弦相似度 cosine similarity \(\cos\theta=\dfrac{a^\top b}{\|a\|\|b\|}\) 把内积归一化掉长度,只比方向——它是检索、推荐、向量数据库里衡量"语义接近"的默认尺子。
- 正交初始化 orthogonal initialization:用正交矩阵初始化权重,因为正交变换保长度、保角度,能让信号在深层网络里不爆炸也不消失。
易错
正规方程要求 \(X^\top X\) 可逆,即 \(X\) 的列线性无关(这正是第 6.1 节那句前提的来历)。若两个特征高度共线(几乎成比例),\(X^\top X\) 接近奇异、求逆数值爆炸——这正是 L2 正则(岭回归)的另一个用途:把它改成 \((X^\top X+\lambda I)\) 后必可逆且稳定。实践中也常用 np.linalg.lstsq 或 SVD 求解而非显式求逆。
8. Gram-Schmidt:把任意基"扶正"成标准正交基
我们反复看到标准正交基让公式变干净,那如何制造一组标准正交基?Gram-Schmidt 正交化给出一条朴素的流水线:逐个拿来基向量,减掉它在已正交化向量上的投影,剩下的残差自然垂直于前面所有向量;最后各自归一化。
对两个向量 \(a_1, a_2\):
\[ u_1 = a_1,\qquad u_2 = a_2 - \operatorname{proj}_{u_1}(a_2) = a_2 - \frac{u_1^\top a_2}{u_1^\top u_1}u_1, \]再令 \(q_i=u_i/\|u_i\|\) 得标准正交基。"减去投影"用的就是第 6 节的投影向量,"剩下的垂直"用的就是残差正交性——整套技术全是本课零件的拼装。
埋一根线给后续课程:把 Gram-Schmidt 整理成矩阵形式,就得到大名鼎鼎的 QR 分解 \(A=QR\)——\(Q\) 的列正是这里造出的标准正交向量,\(R\) 记录了"减投影、做归一化"的所有系数。它也是数值上比正规方程更稳的最小二乘解法,后面会专门讲。
例题:Gram-Schmidt 一遍
取 \(a_1=[1,1],\ a_2=[2,0]\)。
\(u_1=a_1=[1,1]\)。
\(\operatorname{proj}_{u_1}(a_2)=\dfrac{u_1^\top a_2}{u_1^\top u_1}u_1=\dfrac{2}{2}[1,1]=[1,1]\)。
\(u_2=a_2-[1,1]=[2,0]-[1,1]=[1,-1]\)。验证 \(u_1^\top u_2=1\cdot1+1\cdot(-1)=0\) ✓。
归一化:\(q_1=\dfrac{1}{\sqrt2}[1,1],\ q_2=\dfrac{1}{\sqrt2}[1,-1]\),两者垂直且都为单位长度——一组标准正交基诞生。
9. 动手:用 NumPy 算范数、投影与最小二乘
import numpy as np
# ---------- 范数族 ----------
v = np.array([3., -4., 0., 12.])
print("L1 =", np.linalg.norm(v, 1)) # 19
print("L2 =", np.linalg.norm(v, 2)) # 13
print("Linf =", np.linalg.norm(v, np.inf))# 12
M = np.array([[1., 2.], [2., 1.]])
print("Frobenius =", np.linalg.norm(M)) # sqrt(10) ≈ 3.162
# ---------- 把 b 投影到 a ----------
a = np.array([2., 1.]); b = np.array([3., 4.])
coef = (a @ b) / (a @ a) # 标量系数 = 2
proj = coef * a # 投影向量 = [4, 2]
resid = b - proj # 残差 = [-1, 2]
print("proj_a(b) =", proj)
print("residual =", resid)
print("residual . a =", resid @ a) # 0 -> 正交
# ---------- 余弦相似度 ----------
cos = (a @ b) / (np.linalg.norm(a) * np.linalg.norm(b))
print("cos(theta) =", round(float(cos), 4)) # 0.8944
import numpy as np
# ---------- 用正规方程拟合直线 y = w0 + w1*x ----------
x = np.array([0., 1., 2., 3.])
y = np.array([1., 3., 4., 6.])
X = np.column_stack([np.ones_like(x), x]) # 行=样本, 第1列=常数项
# 正规方程 w = (X^T X)^{-1} X^T y
w = np.linalg.inv(X.T @ X) @ (X.T @ y)
print("w (w0, w1) =", w) # [1.1 1.6]
pred = X @ w
resid = y - pred
print("预测 =", pred) # [1.1 2.7 4.3 5.9]
print("残差 =", resid) # [-0.1 0.3 -0.3 0.1]
print("残差与列空间正交:", np.round(X.T @ resid, 8)) # [0. 0.]
# 投影矩阵 P = X (X^T X)^{-1} X^T,验证 Pb == pred
P = X @ np.linalg.inv(X.T @ X) @ X.T
print("P @ y == pred :", np.allclose(P @ y, pred)) # True
print("P 幂等 P@P==P :", np.allclose(P @ P, P)) # True
调一调,观察现象
下面三个小实验都只用 numpy 和 print,几秒跑完。每个都先猜结果,再运行核对——把"投影、范数、共线"这三件事从公式变成你亲眼见过的现象。
实验 1:改投影目标的方向,看标量系数的符号翻转
改什么:固定 \(a=[2,1]\),把目标 \(b\) 换成与 \(a\) 成锐角、垂直、钝角的三种向量。
预期现象:标量系数 \(c=\dfrac{a\cdot b}{\|a\|^2}\) 依次为 +2.00(锐角同侧,影子是 \([4,2]\))、0.00(垂直,投影是零向量 \([0,0]\))、-1.40(钝角,影子是 \([-2.8,-1.4]\),指向 \(a\) 的反方向)。
为什么:投影系数带的正是 \(a\cdot b\) 的符号;点积锐角为正、垂直为零、钝角为负,所以"影子"会跟着翻到 \(a\) 的反侧——这就是课文强调的"投影是带符号的"。
import numpy as np
a = np.array([2., 1.])
for b in ([3., 4.], [-1., 2.], [-3., -1.]):
b = np.array(b)
c = (a @ b) / (a @ a)
print(f"b={b} dot={a@b:5.1f} coef={c:5.2f} proj={c*a}")
实验 2:增大岭回归的 λ,看权重范数被往零收缩
改什么:在二次拟合数据上,让正则强度 \(\lambda\) 从 0 一路增大到 100,闭式解 \(w=(X^\top X+\lambda I)^{-1}X^\top y\)。
预期现象:\(\|w\|_2\) 单调下降,约 1.94 → 1.79 → 1.31 → 0.71 → 0.38;权重整体被往零拉,但在每个 \(\lambda>0\) 上都没有哪一维被精确压成 0(打印出来全是非零的小数)。
为什么:L2 正则的等高线是圆,把权重均匀收小。这正是课文那句"圆把权重收小"——要想把权重精确清零得换成 L1 的尖角,那是后话。
import numpy as np
x = np.array([0., 1., 2., 3.]); y = np.array([1., 3., 4., 6.])
X = np.column_stack([np.ones_like(x), x, x**2])
for lam in [0., 0.1, 1., 10., 100.]:
w = np.linalg.inv(X.T @ X + lam * np.eye(3)) @ X.T @ y
print(f"lambda={lam:6.1f} ||w||={np.linalg.norm(w):.4f} w={np.round(w,3)}")
实验 3:把一列改成另一列的倍数,看 \(\det(X^\top X)\) 塌成 0
改什么:先用正常的两列(常数项 + \(x\)),再把第三列故意设成第二列的 2 倍(人为共线)。
预期现象:正常时 \(\det(X^\top X)=20.0\)(可逆,正规方程有解);共线时 \(\det=0.0\)(奇异,求逆会爆炸)。
为什么:正规方程要求 \(X\) 的列线性无关,\(X^\top X\) 才可逆。一旦两列成比例,列空间"塌了一维",\(X^\top X\) 行列式归零——这就是课文易错框里"特征共线 → 求逆数值爆炸"的根源,也是岭回归 \(+\lambda I\) 来救场的理由。
import numpy as np
x = np.array([0., 1., 2., 3.])
X_ok = np.column_stack([np.ones_like(x), x])
print("正常两列 det(X^T X) =", round(np.linalg.det(X_ok.T @ X_ok), 6))
X_bad = np.column_stack([np.ones_like(x), x, 2 * x]) # 第3列 = 第2列的2倍
print("含共线列 det(X^T X) =", round(np.linalg.det(X_bad.T @ X_bad), 6))
动手练习
- 把 \(b=[1,2,2]\) 投影到 \(a=[2,0,0]\)。手算 \(\operatorname{proj}_a(b)\) 与残差,并用代码核对残差与 \(a\) 正交。
import numpy as np a = np.array([2., 0., 0.]); b = np.array([1., 2., 2.]) # TODO: 算 coef、proj、resid,并 print(resid @ a) - 验证 \(\|x\|_\infty\le\|x\|_2\le\|x\|_1\):随机生成 1000 个五维向量,统计这条不等式是否全部成立。
import numpy as np rng = np.random.default_rng(0) X = rng.standard_normal((1000, 5)) # TODO: 逐行算三种范数, 用布尔数组检查 Linf<=L2<=L1 是否 .all() - 把第 9 节的拟合改成二次曲线 \(y=w_0+w_1x+w_2x^2\):在 \(X\) 里加一列 \(x^2\),重解正规方程,比较残差是否更小。
import numpy as np x = np.array([0., 1., 2., 3.]); y = np.array([1., 3., 4., 6.]) X = np.column_stack([np.ones_like(x), x, x**2]) # TODO: w = inv(X.T@X)@X.T@y ; 打印 w 和残差范数 - 实现 Gram-Schmidt:对 \(a_1=[1,1,0],\,a_2=[1,0,1],\,a_3=[0,1,1]\) 正交化,用代码验证结果矩阵 \(Q\) 满足 \(Q^\top Q=I\)。
import numpy as np A = np.array([[1.,1.,0.],[1.,0.,1.],[0.,1.,1.]]).T # 列为 a1,a2,a3 # TODO: 循环减去对前面各列的投影, 再归一化, 最后 print(np.round(Q.T@Q,8)) - 岭回归的 λ 扫描:在练习 3 的数据上最小化 \(\|Xw-y\|^2+\lambda\|w\|_2^2\),闭式解为 \(w=(X^\top X+\lambda I)^{-1}X^\top y\)。取一串递增的 \(\lambda\),观察权重的 L2 范数 \(\|w\|_2\) 如何随 \(\lambda\) 增大而被往零收缩。
import numpy as np x = np.array([0., 1., 2., 3.]); y = np.array([1., 3., 4., 6.]) X = np.column_stack([np.ones_like(x), x, x**2]) # TODO: for lam in [0., 0.1, 1., 10., 100.]: # w = inv(X.T@X + lam*np.eye(X.shape[1])) @ X.T @ y # print(lam, w, np.linalg.norm(w)) # 观察: lambda 越大, ||w||_2 越小 -> 权重被往零收缩(但不会精确为零)选做(思考题):L1 正则(Lasso)能把权重精确压成零,但它没有闭式解,需要坐标下降 / 次梯度等迭代方法(实践中直接用
sklearn.linear_model.Lasso),后续课程会专门讲。这里先体会"圆把权重收小、尖角把权重清零"的差别即可。
掌握自检
- 我能说出内积的三条公理,并解释"正定"为何保证长度非负。
- 给定一个向量,我能心算它的 L1 / L2 / L∞ 范数,并画出二维下三者的单位球(菱形 / 圆 / 正方形)。
- 我能解释为什么 L1 正则产生稀疏、L2 正则只是把权重收小——从单位球尖角的几何说清楚。
- 我能不查公式写出 \(\operatorname{proj}_a(b)=\dfrac{a\cdot b}{\|a\|^2}a\),并说明残差为何与 \(a\) 正交。
- 我能把"最小二乘"翻译成"把 \(b\) 投影到列空间",并推出正规方程 \(A^\top A w=A^\top b\) 来自"残差 ⊥ 列空间"。
- 我能用 NumPy 解一个直线拟合,并验证残差与每个特征列正交、投影矩阵 \(P\) 幂等 idempotent。
- 我能描述 Gram-Schmidt 的一步:减投影得残差、残差归一化,从而造出标准正交基。
要点
内积是空间的度量地基:它一手定义长度(范数),一手定义角度(正交)。投影是"沿某方向走到离目标最近的点",残差必与该方向正交;把方向换成子空间,投影矩阵 \(P=A(A^\top A)^{-1}A^\top\) 就给出最小二乘解。L2 损失、权重衰减、余弦相似度、线性回归、正交初始化——全是这一课几何的直接应用。
下一课,我们要问一个新问题:一个线性变换里,有没有某些特殊方向,被变换作用后方向不变、只被缩放?这就是特征值与特征向量 eigenvalue & eigenvector——它会揭示一个变换"骨子里"的样子。
可以先放过的点
- 内积"对第二个参数线性可由对称性白送推出"以及"双线性"这套形式化论证——现在只要会用标准点积就够,等你真的遇到非标准内积时再回来抠它。
- 投影矩阵的幂等 \(P^2=P\) 和对称 \(P^\top=P\) 的证明,不必现在手推。先记住"影子再投影还是它自己"这个直觉,第 9 节代码会帮你眼见为实。
- Gram-Schmidt 和它埋的那根 QR 分解的线,第 8 节看个大概即可——这是后面专门一课的内容,现在卡在这里不值得,先把投影和最小二乘吃透。
- L1 正则为什么"没有闭式解、要靠坐标下降",纯属预告。你只需体会几何上的稀疏现象,具体算法等讲优化时再说。