首页 / 模块 1 · 线性代数与微积分 / 第 3 课(共 10 课)

内积、范数与投影

从零到前沿 ML 自学课程 · 阶段0:数学与工具基础 · 能力点:度量与正则化的几何——L2 损失、权重衰减、余弦相似度、最小二乘

读完这一课,你将能够

  • 说出内积的三条公理,并解释长度 \(\|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 / L2 / L∞ 单位球对比:菱形 ⊂ 圆 ⊂ 正方形x₁x₂O1-11-1L₁ 尖角恰落在坐标轴上 → 稀疏解L₁ / L₂ / L∞ 单位球:菱形 ⊂ 圆 ⊂ 正方形‖x‖₁ = 1‖x‖₂ = 1‖x‖∞ = 1
二维 L1 / L2 / L∞ 单位球对比:L1 是顶点落在坐标轴上的菱形,L2 是光滑的圆,L∞ 是边平行坐标轴的正方形;三者呈嵌套关系 菱形 ⊂ 圆 ⊂ 正方形。图中标出 L1 的尖角恰在坐标轴上(解释稀疏性来源)。

一个稳定的包含关系:\(\|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. \]

无需画图、无需算角度——点积为零就是垂直。两个推广概念:

为什么人人都爱标准正交基?因为在它下面,向量 \(b\) 沿第 \(i\) 个基方向的坐标就是简单的点积 \(q_i^\top b\),不用解方程组。坐标提取从"求逆"退化成"做内积"——这就是后面投影公式会变得无比干净的原因。

6. 投影:把一个向量压到另一个方向上

给定方向 \(a\) 和目标 \(b\),我们想找 \(b\) 落在 \(a\) 这条直线上的"影子"。把 \(b\) 分解成两部分:沿 \(a\) 的分量 + 垂直于 \(a\) 的残差 residual

向量投影分解:b 沿 a 分解为投影向量 proj 与垂直残差 r11234512345xyOa = [2,1]b = [3,4]proj_a(b) = [4,2]r = b − proj = [−1,2]方向直线 a标量投影 = a·b / ‖a‖ = 10 / √5 = 2√5 (即影子长度)
向量投影分解:把 b 沿方向 a 分解为投影向量 proj_a(b) 与残差 r=b-proj_a(b),残差与 a 垂直(直角标记)。标量投影是影子的长度。以例题数值 a=[2,1], b=[3,4], proj=[4,2], r=[-1,2] 作图。

标量投影 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\)。直觉拆解:

投影矩阵有两个漂亮性质:幂等 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\),正好是上一节的投影矩阵。最小二乘 = 投影到列空间,两件事是同一件事的代数面与几何面。

最小二乘的几何:残差垂直于列空间的正规方程列空间 col(A)Oa₁a₂Aw = Pbb残差 b − Aw残差 ⊥ 列空间⇒ Aᵀ(b − Aw) = 0⇒ 正规方程
最小二乘的几何:标签向量 b 悬在列空间(A 各列张成的平面)之外,最近的平面内点是 b 的投影 Pb=Aw,误差向量 b-Aw 垂直于整个列空间——这就是正规方程 Aᵀ(b-Aw)=0 的几何含义。

例题:用正规方程拟合一条直线

四个点 \((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.solvelstsq)。行列式 \(\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))

动手练习

  1. 把 \(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)
    
  2. 验证 \(\|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()
    
  3. 把第 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 和残差范数
    
  4. 实现 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))
    
  5. 岭回归的 λ 扫描:在练习 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),后续课程会专门讲。这里先体会"圆把权重收小、尖角把权重清零"的差别即可。

掌握自检

要点

内积是空间的度量地基:它一手定义长度(范数),一手定义角度(正交)。投影是"沿某方向走到离目标最近的点",残差必与该方向正交;把方向换成子空间,投影矩阵 \(P=A(A^\top A)^{-1}A^\top\) 就给出最小二乘解。L2 损失、权重衰减、余弦相似度、线性回归、正交初始化——全是这一课几何的直接应用。

下一课,我们要问一个新问题:一个线性变换里,有没有某些特殊方向,被变换作用后方向不变、只被缩放?这就是特征值与特征向量 eigenvalue & eigenvector——它会揭示一个变换"骨子里"的样子。