上一课我们建立了贝叶斯三件套:先验(动手前对参数的信念)、似然(参数对数据的解释力)、后验(看完数据后更新的信念)。这一课我们把它们用起来,回答一个训练神经网络时天天遇到、却很少被讲清的问题:损失函数到底是从哪儿冒出来的?为什么回归用 MSE、分类用交叉熵,而不是别的式子?答案出奇地干净——你只要写下"数据是怎么生成的"这一个假设,损失函数就被唯一地推导出来了,不是凑的。
读完这一课,你将能够
- 把"数据生成假设"翻译成似然函数,再用"取对数 + 加负号"机械地得到对应的损失函数(NLL)。
- 亲手推出:高斯噪声假设 → MSE;伯努利/类别假设 → 交叉熵。
- 解释 MAP 与 MLE 的区别,并把 L2 正则 = 高斯先验、L1 正则 = 拉普拉斯先验 这件事讲给别人听,包括 L1 为什么会"逼出 0"。
- 说清小样本下 MLE 为什么会"自信地犯错"(某类计数为 0),以及拉普拉斯平滑如何补救。
- 用 numpy 验证 \(\hat p=k/n\)、\(\hat\mu=\) 样本均值,以及"MLE 闭式解 = 最小二乘正规方程解"。
一、似然:把"参数"当成"对数据的解释力"
先建立一个最基本的视角转换。在贝叶斯那一课,\(p(x\mid\theta)\) 我们读作"给定参数 \(\theta\),数据 \(x\) 的取值情况"——这时 \(x\) 是变量,\(\theta\) 固定。现在反过来:数据 \(x\) 已经摆在桌上(已经观测到了,是常数),我们让 \(\theta\) 变化,问"哪个 \(\theta\) 让这批数据显得最不意外?"
同一个表达式 \(p(x\mid\theta)\),盯着 \(x\) 看叫概率(密度)(probability / density),盯着 \(\theta\) 看叫似然(likelihood)。似然不是 \(\theta\) 的概率分布(它对 \(\theta\) 积分不一定等于 1),它衡量的是"这个参数把已观测数据解释得多好"。一句话:似然是参数的"考试成绩",数据是考卷。
真正让似然好用的,是一个朴素到容易被忽略的建模假设——i.i.d.(独立同分布,independent and identically distributed):我们假设 \(n\) 个样本 \(x_1,\dots,x_n\) 是从同一个分布里各自独立抽出来的。独立 ⇒ 联合概率等于各自概率连乘;同分布 ⇒ 每个 \(p\) 用同一个 \(\theta\)。于是整批数据的似然就是一长串乘积:
\[ L(\theta)\;=\;p(x_1,\dots,x_n\mid\theta)\;\overset{\text{i.i.d.}}{=}\;\prod_{i=1}^{n} p(x_i\mid\theta). \]把它当成 \(\theta\) 的函数画出来,通常是一条有单峰的曲线:某个 \(\theta\) 处似然最大,那就是最能解释数据的参数。
二、MLE:站到似然曲线的峰顶
最大似然估计(Maximum Likelihood Estimation, MLE)就是字面意思——挑出让似然最大的那个参数:
\[ \theta^{*}\;=\;\arg\max_{\theta}\;L(\theta)\;=\;\arg\max_{\theta}\;\prod_{i=1}^{n} p(x_i\mid\theta). \]但这个连乘很难直接优化:成百上千个介于 0 和 1 之间的小数相乘,结果会小到计算机直接下溢成 0(比如 \(0.1^{400}\) 在浮点里就是 0,连数值本身都存不下来,更别说在它上面做优化)。解决办法是取对数。
这里说的"下溢"指似然数值本身归零,和后面深层网络里"梯度消失"(vanishing gradient,反向传播时梯度逐层变小)是两件不同的事,别被它们都带"消失"色彩的描述混淆——一个是数值表示问题,一个是优化信号问题。
为什么取对数是"免费的好处"
对数 \(\ln\) 有两个性质,恰好治好连乘的所有毛病:
- 把连乘变连加:\(\ln\prod_i a_i=\sum_i\ln a_i\)。连加不会下溢,且每一项独立,天然适合按样本/按 batch 累加——这正是训练时 loss 对 batch 求和的由来。
- 单调递增,不改变峰的位置:\(\ln\) 是严格单调函数,所以 \(\arg\max L(\theta)=\arg\max \ln L(\theta)\)。峰移不了,只是曲线被"压平"得更好优化(见下图)。
于是定义对数似然 \(\ell(\theta)=\ln L(\theta)=\sum_i\ln p(x_i\mid\theta)\)。优化里习惯"最小化"而非"最大化",再加个负号,得到本课的主角——负对数似然(Negative Log-Likelihood, NLL):
\[ \boxed{\;\mathrm{NLL}(\theta)\;=\;-\sum_{i=1}^{n}\ln p(x_i\mid\theta)\;} \qquad\Longrightarrow\qquad \theta^{*}=\arg\min_{\theta}\;\mathrm{NLL}(\theta). \]关键结论:最大化似然 ⟺ 最小化负对数似然。NLL 就是损失函数的本体。你平时写的 loss,几乎都是某个数据生成假设下的 NLL。接下来两节,我们换两种 \(p(x_i\mid\theta)\) 的假设,分别"变"出 MSE 和交叉熵。
为什么对数和 \(\exp\) 这么搭?很多常见分布(高斯、伯努利、泊松……)的密度都能写成 \(p(x)\propto \exp(\text{某个关于 }\theta\text{ 的式子})\) 这一类形状。取 \(\ln\) 正好把 \(\exp\) 抵消,指数里的东西变成了关于参数的简单(常是二次或线性)函数——优化瞬间变容易。这不是巧合,是对数和指数互为反函数的红利。(这一大类分布有个正式名字,下一阶段再正式学,这里不必记。)
三、高斯噪声假设 → MSE(最小二乘)
现在做一个回归任务。假设标签由某个函数 \(f(x)\)(比如线性模型 \(f(x)=w^\top x\))加上高斯噪声生成:
\[ y_i\;\sim\;\mathcal{N}\!\big(f(x_i),\,\sigma^2\big) \qquad\Longleftrightarrow\qquad p(y_i\mid x_i,\theta)=\frac{1}{\sqrt{2\pi\sigma^2}}\exp\!\left(-\frac{(y_i-f(x_i))^2}{2\sigma^2}\right). \]这里有个该说清的细节:密度不是概率。前面伯努利/类别那种离散标签里,\(p(y\mid\theta)\) 是货真价实的概率(取值在 0 和 1 之间)。但这里 \(y\) 是连续的,\(p(y_i\mid x_i,\theta)\) 是概率密度(PDF):它有量纲、数值可以大于 1,而且任何单个连续观测点的概率严格等于 0。似然在连续情形下比较的不是"概率高低",而是"密度值高低"——哪个 \(\theta\) 让观测点落在密度更高的地方。顺带一提,这也正是下面 MSE 能把 \(1/\sqrt{2\pi\sigma^2}\) 这种纯归一化因子丢掉的原因:它只是把密度积分归一的常数,不影响哪个 \(\theta\) 让密度更高。
这句假设的现实含义是:模型的预测 \(f(x_i)\) 是"真值",实际观测在它周围呈钟形抖动,离得越远越罕见。把它代进 NLL(先只看权重 \(\theta\) 这个参数,把 \(\sigma\) 当成已知常数;为什么能这样,下面立刻交代):
\[ \mathrm{NLL}(\theta)=-\sum_i\ln p(y_i\mid x_i,\theta) =\sum_i\left[\frac{(y_i-f(x_i))^2}{2\sigma^2}+\underbrace{\tfrac12\ln(2\pi\sigma^2)}_{\text{与}\,\theta\,\text{无关,常数}}\right]. \]常数项不影响 \(\arg\min\),\(1/(2\sigma^2)\) 是正的缩放因子也不影响最优 \(\theta\) 的位置,全部丢掉:
\[ \boxed{\;\theta^{*}=\arg\min_{\theta}\sum_{i=1}^{n}\big(y_i-f(x_i)\big)^2\;} \]"为什么能把 \(\sigma\) 当常数丢掉?"高斯其实有两个参数:均值侧的 \(\theta\)(即 \(\mu\) 或权重 \(w\))和噪声方差 \(\sigma^2\)。关键事实是:对 \(\theta\) 求 \(\arg\min\) 时,\(\sigma\) 只以"正缩放因子 + 加常数"的形式出现,不影响 \(\theta\) 的最优位置——所以求 \(w\) 时可以把它当常数。\(\sigma\) 自己当然也能估,它的 MLE 就是样本残差的方差 \(\hat\sigma^2=\frac1n\sum_i(y_i-f(x_i))^2\)(解出 \(\hat\theta\) 后回代即可,先解 \(\theta\) 不依赖 \(\sigma\))。本课主线只关心 \(\theta\),\(\sigma\) 的细节放进文末 skip。
高斯噪声假设直接给出 MSE。你每次用均方误差,背后都在悄悄假设"标签噪声是高斯的、方差恒定的"。MSE 不是天经地义的"距离",它是一个具体概率假设的产物。
例题:高斯 MLE 的 \(\hat\mu\) 就是样本均值
取最简单的 \(f(x)\equiv\mu\)(常数模型,无输入),即 \(y_i\sim\mathcal{N}(\mu,\sigma^2)\)。NLL 去掉常数后要最小化 \(g(\mu)=\sum_i(y_i-\mu)^2\)。求导置零:
\[ g'(\mu)=\sum_i 2(y_i-\mu)(-1)=-2\sum_i(y_i-\mu)=0 \;\Longrightarrow\;\sum_i y_i=n\mu \;\Longrightarrow\;\boxed{\hat\mu=\tfrac1n\sum_i y_i.} \]"高斯 MLE 的均值 = 样本均值",并且这等价于最小化 \(\sum(y-\mu)^2\)——这就是 MSE 在一维上的样子。二阶导 \(g''=2n>0\),确认是极小值。
ML 和 ML 的联系
把 \(f(x_i)=w^\top x_i\) 代入,最小化 \(\sum_i(y_i-w^\top x_i)^2\) 就是线性回归。对 \(w\) 求导置零得到正规方程 \(X^\top X\,w=X^\top y\)(你在模块1 矩阵求导那课推过 \(\nabla_w\|y-Xw\|^2=-2X^\top(y-Xw)\))。所以"最小二乘的闭式解"和"高斯线性模型的 MLE"是同一个解——本课代码会让它们逐位对齐。
四、伯努利 / 类别假设 → 交叉熵
换成二分类。每个标签 \(y_i\in\{0,1\}\),模型吐出"预测为 1 的概率" \(\hat y_i=\hat y_i(\theta)\in(0,1)\)。这等于假设 \(y_i\) 服从伯努利分布 \(\mathrm{Bernoulli}(\hat y_i)\)(这里 \(y\) 离散,\(p\) 是真概率,不是密度)。伯努利的概率可以写成一个紧凑的式子(指数当开关):
\[ p(y_i\mid\theta)=\hat y_i^{\,y_i}\,(1-\hat y_i)^{\,1-y_i} =\begin{cases}\hat y_i,& y_i=1\\[2pt] 1-\hat y_i,& y_i=0.\end{cases} \]取负对数并对样本求和:
\[ \mathrm{NLL}=-\sum_i\Big[y_i\ln\hat y_i+(1-y_i)\ln(1-\hat y_i)\Big]. \]这正是二元交叉熵(binary cross-entropy)。推广到 \(K\) 类(Categorical 分布),把真实标签写成 one-hot 向量 \(y_i\)(只有正确类是 1),预测为概率向量 \(\hat y_i\),得到逐点交叉熵:
\[ \boxed{\;\mathrm{NLL}=-\sum_i\sum_{c=1}^{K} y_{i,c}\,\ln\hat y_{i,c}\;=\;-\sum_i\ln\hat y_{i,\text{正确类}}\;} \]因为 \(y_i\) 是 one-hot,内层求和只剩"正确那一类的预测概率的对数"这一项。所以分类的交叉熵损失 = −ln(模型给正确答案的概率):模型对正确答案越自信,loss 越小;给正确答案分配的概率趋于 0 时,loss 趋于 \(+\infty\)(被狠狠惩罚)。下一课会用信息论给"交叉熵"这个名字一个更深的解释。
例题:伯努利 MLE 推出 \(\hat p=\) 正例比例
抛硬币 \(n\) 次,正面 \(k\) 次(每次 \(\mathrm{Bernoulli}(p)\),没有输入特征,模型就是单个参数 \(p\))。对数似然为
\[ \ell(p)=\sum_i\big[y_i\ln p+(1-y_i)\ln(1-p)\big]=k\ln p+(n-k)\ln(1-p). \]求导置零:
\[ \ell'(p)=\frac{k}{p}-\frac{n-k}{1-p}=0 \;\Longrightarrow\;k(1-p)=(n-k)p \;\Longrightarrow\;\boxed{\hat p=\frac{k}{n}.} \]最大似然给出的最优 \(p\) 就是样本里正面的比例——和直觉完全一致。注意这和上面高斯例题的结构一模一样:写似然 → 取对数 → 求导置零 → 得到一个"样本统计量"。MLE 的套路是统一的。
五、MAP:给似然配上先验
MLE 只听数据的,这在数据少时很危险。极端例子:投 3 次硬币全是正面,MLE 笃定地宣布 \(\hat p=3/3=1\)("这枚硬币永远不会出反面")。这显然过拟合了——它把"恰好没观测到"当成了"不可能"。我们需要把"先验信念"(硬币大概接近公平)加回来。
这就是上一课的后验 ∝ 似然 × 先验。最大后验估计(Maximum A Posteriori, MAP)取的是后验的峰,而不是似然的峰:
\[ \theta_{\mathrm{MAP}}=\arg\max_{\theta}\;\underbrace{p(\theta\mid \text{data})}_{\text{后验}} =\arg\max_{\theta}\;\underbrace{p(\text{data}\mid\theta)}_{\text{似然}}\,\underbrace{p(\theta)}_{\text{先验}}. \]分母 \(p(\text{data})\) 不含 \(\theta\),求 \(\arg\max\) 时可丢弃。照例取对数把乘积拆成加法:
\[ \boxed{\;\theta_{\mathrm{MAP}}=\arg\max_{\theta}\;\big[\,\underbrace{\ln L(\theta)}_{\text{数据项}}+\underbrace{\ln p(\theta)}_{\text{先验项}}\,\big] =\arg\min_{\theta}\;\big[\,\mathrm{NLL}(\theta)-\ln p(\theta)\,\big].\;} \]看右边这个式子:它就是 "原损失 + 一个只跟参数有关的额外项"。先验把后验的峰从似然峰往先验中心拉了一点——数据越少,似然越"软",先验拉得越动;数据越多,似然越尖,先验几乎拉不动(数据淹没先验)。这正是我们想要的行为。
把"3 投全正"的悬念闭环
回到开头那枚硬币:\(n=3\)、\(k=3\)。给 \(p\) 配一个温和的对称先验("事先各假装看到 1 正 1 反",即 Beta(1,1) 加 add-one 平滑),MAP 解是
\[ \hat p_{\mathrm{MAP}}=\frac{k+1}{n+2}=\frac{3+1}{3+2}=\frac{4}{5}=0.8. \]于是先验把 MLE 的"硬 1"拉回到了合理的 0.8——既承认"目前都是正面",又拒绝断言"反面绝不可能"。记住这个动作:第七节会看到同一个先验把另一头的"硬 0"也抬离零点。先验做的事前后呼应:既不让概率冲到 1,也不让它塌到 0。
六、先验 = 正则项:把"权重衰减"看穿
现在揭开一个让很多人恍然大悟的等价关系。回到高斯线性回归,给权重 \(w\) 加一个零均值高斯先验 \(w_j\sim\mathcal{N}(0,\tau^2)\),意思是"我事先相信权重应该小、应该靠近 0"。它的负对数为
\[ -\ln p(w)=\sum_j\frac{w_j^2}{2\tau^2}+\text{const}=\frac{1}{2\tau^2}\|w\|_2^2+\text{const}. \]代入 MAP 目标(NLL 是高斯的 \(\tfrac{1}{2\sigma^2}\sum(y_i-w^\top x_i)^2\)),整理出
\[ \theta_{\mathrm{MAP}}=\arg\min_{w}\;\sum_i(y_i-w^\top x_i)^2+\lambda\|w\|_2^2, \qquad \lambda=\frac{\sigma^2}{\tau^2}. \]加 L2 正则(权重衰减 / Ridge / weight decay)= 假设权重服从零均值高斯先验。正则强度 \(\lambda\) 就是"噪声方差 / 先验方差"之比:先验越强(\(\tau\) 越小,越坚信权重该小)⇒ \(\lambda\) 越大 ⇒ 那个把权重往 0 拉的"二次碗"越陡。
换个先验就换个正则。拉普拉斯先验 \(p(w_j)\propto\exp(-|w_j|/b)\)(形状是0 处一个尖顶、两侧重尾)的负对数是 \(\frac1b\sum_j|w_j|\),于是
\[ \text{拉普拉斯先验}\;\Longrightarrow\;\lambda\|w\|_1\;=\;\textbf{L1 正则(Lasso)}. \]为什么 L1 会"逼出 0"(稀疏),L2 只会"压小"?看惩罚项在 \(w_j\) 接近 0 时的梯度:
· L2 的惩罚是 \(w_j^2\),梯度 \(2w_j\) 在 \(w_j\to 0\) 时自己也趋于 0——越靠近 0,往 0 推的力气越小,所以只能把权重压得很小却不会真正归零。
· L1 的惩罚是 \(|w_j|\),梯度是 \(\pm1\)(绝对值在 0 处尖、不可导),大小不随 \(w_j\) 减小而衰减——只要这个权重对拟合的贡献撑不过这股恒定的"往 0 推"的力,它就会被推到正好等于 0。
几何上:拉普拉斯先验的尖顶把最优点"钉"在坐标轴上,于是一堆不重要的权重直接变成 0,得到稀疏解。这就是 L1 做特征选择的来历。
| 数据生成 / 先验假设 | 等价的损失 / 正则 |
|---|---|
| 高斯噪声 \(y\sim\mathcal N(f(x),\sigma^2)\) | MSE / 最小二乘 |
| 伯努利 / Categorical | 交叉熵 |
| 权重零均值高斯先验 | L2 正则(权重衰减) |
| 权重拉普拉斯先验 | L1 正则(稀疏) |
ML 和 ML 的联系
这张表是深度学习损失函数的"户口本":你在 PyTorch 里写的 MSELoss、CrossEntropyLoss、weight_decay,没有一个是凭空规定的,全都是"某个生成假设/先验"下的 MAP 目标。理解了这层,你以后看到新损失(如泊松回归的 loss、带 L1 的稀疏模型)就能反推它在假设什么——这是设计损失函数的钥匙。
七、小样本的陷阱与拉普拉斯平滑
MLE 在小样本下会"自信地犯错"。设想用词频估计一个 3 类分布,观测计数为 \([8,0,2]\):第 2 类恰好没出现。MLE 给出概率 \([0.8,\,0,\,0.2]\)——它断言第 2 类概率为 0,永远不可能出现。一旦测试集真的来了一个第 2 类样本,交叉熵 \(-\ln 0=+\infty\),模型彻底崩溃。
救法就是 MAP:给类别分布配一个对称的狄利克雷先验(相当于"假装每类先各看到 \(\alpha\) 个样本"),MAP 解变成
\[ \hat p_c=\frac{n_c+\alpha}{N+\alpha K},\qquad K=\text{类别数}. \]这就是拉普拉斯平滑(Laplace / add-one smoothing,\(\alpha=1\))。对上面的例子:\([8,0,2]\to[\tfrac{9}{13},\tfrac{1}{13},\tfrac{3}{13}]\approx[0.69,0.08,0.23]\)——那个危险的 0 被先验抬离了零点,模型不再"把没见过当成不可能"。注意这和第五节"3 投全正→拉回 0.8"是同一件事的两面:先验既不让概率冲到 1,也不让它塌到 0。
易错点:(1) 对数似然不是似然——只在比较 \(\arg\max\) 时能随意丢常数/正缩放因子;如果你要的是似然本身的数值(如做模型比较算证据),就不能乱丢。(2) MAP 给的是后验的众数(峰),不是后验均值,二者在偏斜分布下不同(完整贝叶斯要对后验积分,那是更贵的事)。(3) MLE/MAP 都依赖 i.i.d. 假设——数据有时间相关、有分布漂移时,直接套连乘的似然是错的。
调一调,观察现象
下面每个小实验都只改一个量,先猜结果,再运行验证。所有代码只用 numpy + print,几秒跑完。
调一调①:样本量如何"锁定"似然峰
改什么:把伯努利样本量 n 从 20 调到 2000(真值 0.3)。预期现象:对数似然曲线的峰会越来越尖——用 seed=0 实跑,峰宽(格数)大致是 29 → 9 → 3,也就是对参数的不确定性越来越小。峰的位置则始终等于 k/n,并在真值 0.3 附近抖动、抖动幅度随 n 减小:小 n 时受抽样波动影响可能偏离 0.3(方向随机,本种子下 n=20 给约 0.35),单次随机不保证逐 n 单调逼近,但 n 越大估计越可靠。为什么:样本越多,似然对参数越"挑剔",等价于后验越集中、先验越来越拉不动它。
import numpy as np
rng = np.random.default_rng(0)
for n in [20, 200, 2000]:
data = (rng.random(n) < 0.3).astype(float)
p = np.linspace(0.01, 0.99, 99)
ll = np.array([(data*np.log(pi)+(1-data)*np.log(1-pi)).sum() for pi in p])
pk = p[ll.argmax()]
# 用"峰附近高出 1 个单位的宽度"粗略量峰的尖锐度(越小越尖、越确定)
width = (ll >= ll.max()-1.0).sum()
print(f"n={n:5d} argmax p={pk:.3f} k/n={data.mean():.3f} 峰宽(格数)={width}")
调一调②:正则强度 λ 就是"先验有多强"
改什么:把岭回归里的 lam 从 0 增大到 100。预期现象:\(\lambda=0\) 时解就是普通最小二乘解;\(\lambda\) 越大,权重范数 \(\|w\|\) 越小、越被压向 0(本种子下 \(\|w\|\) 单调下降,约 0.92 → 0.90 → 0.73 → 0.30)。为什么:\(\lambda=\sigma^2/\tau^2\),调大 \(\lambda\) 等于把高斯先验调窄(\(\tau\) 变小),先验把权重往 0 拉得更狠。
import numpy as np
rng = np.random.default_rng(1)
N, d = 60, 5
X = rng.normal(size=(N, d)); w_true = rng.normal(size=d)
y = X @ w_true + rng.normal(0, 0.5, size=N)
for lam in [0.0, 1.0, 10.0, 100.0]:
w = np.linalg.solve(X.T@X + lam*np.eye(d), X.T@y)
print(f"lam={lam:6.1f} ||w||={np.linalg.norm(w):.3f}")
调一调③:零计数如何让交叉熵爆炸,平滑如何救场
改什么:对比 MLE 概率与拉普拉斯平滑概率在"遇到未见类别"时的交叉熵。预期现象:MLE 对第 2 类给 0 概率,一旦测试样本属于第 2 类,-log(0)=inf;平滑后给出有限的、合理的损失(这里 \(-\ln(1/13)\approx2.565\))。为什么:先验把概率从硬 0 抬起来,避免了"把没见过当成不可能"。
import numpy as np
counts = np.array([8, 0, 2]); K = len(counts); N = counts.sum()
p_mle = counts / N
p_smooth = (counts + 1) / (N + K) # 拉普拉斯平滑 alpha=1
print("MLE :", np.round(p_mle, 3))
print("smooth:", np.round(p_smooth, 3))
# 测试样本恰好属于第 2 类(索引1)
with np.errstate(divide='ignore'):
print("CE(MLE, 第2类) =", -np.log(p_mle[1])) # inf
print("CE(smooth, 第2类)=", round(-np.log(p_smooth[1]), 3))
动手练习
- 网格验证伯努利 MLE。合成
n=300的伯努利数据(真值 0.3),在 0.01–0.99 上扫描对数似然,print 出网格 argmax 与k/n,确认两者一致(到网格精度)。import numpy as np rng = np.random.default_rng(0) data = (rng.random(300) < 0.3).astype(float) p = np.linspace(0.01, 0.99, 99) ll = np.array([(data*np.log(pi)+(1-data)*np.log(1-pi)).sum() for pi in p]) print("grid argmax =", round(p[ll.argmax()],3), " k/n =", round(data.mean(),3)) - 验证高斯 MLE \(\hat\mu=\) 样本均值。合成
n=300的 \(\mathcal N(\mu=2,\sigma^2)\) 数据,在 \(\mu\) 网格上扫描对数似然,确认网格 argmax 与data.mean()一致(到网格精度)。这就是 goals 里承诺的"\(\hat\mu=\) 样本均值"的可跑验证。import numpy as np rng = np.random.default_rng(7) data = rng.normal(2.0, 1.0, size=300) mu = np.linspace(0.0, 4.0, 401) # 高斯对数似然去掉与 mu 无关的常数后 ∝ -Σ(y-mu)^2 ll = np.array([-((data - m)**2).sum() for m in mu]) print("grid argmax =", round(mu[ll.argmax()],3), " mean =", round(data.mean(),3)) - MLE 闭式解 vs 正规方程解。合成线性回归数据,分别用
np.linalg.solve(X.T@X, X.T@y)(正规方程)和np.linalg.lstsq(X, y)(最小二乘/MLE),print 两组权重并用np.allclose验证它们数值一致。import numpy as np rng = np.random.default_rng(2) N = 100 X = np.column_stack([np.ones(N), rng.normal(size=N), rng.normal(size=N)]) y = X @ np.array([1.0,-2.0,0.5]) + rng.normal(0,0.5,size=N) w_ols = np.linalg.solve(X.T@X, X.T@y) w_mle = np.linalg.lstsq(X, y, rcond=None)[0] print("OLS:", np.round(w_ols,4)) print("MLE:", np.round(w_mle,4)) print("一致?", np.allclose(w_ols, w_mle)) - 把 L2 正则拼出来。在上一题基础上加入
lam*I,实现岭回归闭式解solve(X.T@X+lam*I, X.T@y)。验证lam=0时回到 OLS,lam增大时||w||单调减小。 - (推导题)泊松 MLE。设 \(x_i\sim\mathrm{Poisson}(\lambda)\),\(p(x\mid\lambda)=e^{-\lambda}\lambda^{x}/x!\)。写出对数似然,对 \(\lambda\) 求导置零,证明 \(\hat\lambda=\) 样本均值。(提示:\(\ell(\lambda)=-n\lambda+(\sum_i x_i)\ln\lambda-\sum_i\ln(x_i!)\),与本课的高斯/伯努利例题同套路。)
- (思考题)如果你把回归的 MSE 换成平均绝对误差(MAE,\(\sum|y_i-f(x_i)|\)),这对应假设标签噪声服从哪种分布?(提示:哪种分布的负对数密度长成 \(|y-\mu|\)?回看第六节拉普拉斯先验那个"0 处尖顶"的形状。)
掌握自检
- 有人问"为什么回归用 MSE",你能在 30 秒内从"高斯噪声假设 → NLL → 去常数(含归一化因子 \(1/\sqrt{2\pi\sigma^2}\))"讲到 MSE,而不是只说"因为它是距离"。
- 给你一个数据生成假设 \(p(x\mid\theta)\),你能机械地写出对应损失:取 \(\ln\)、加负号、对样本求和。
- 你能说清"离散标签里 \(p\) 是概率、连续标签里 \(p\) 是密度(可>1、单点概率为 0)",以及这为什么让 MSE 能丢掉归一化常数。
- 你能解释 \(\lambda\|w\|_2^2\) 里的 \(\lambda\) 在贝叶斯视角下是什么(\(\sigma^2/\tau^2\),噪声与先验方差之比),以及它变大时几何上发生什么(先验"碗"变陡)。
- 你能用"惩罚梯度在 0 附近衰不衰减"解释为什么 L1 稀疏(梯度恒定→推到 0)而 L2 不稀疏(梯度趋 0→只压小)。
- 你能说出 MLE 在什么时候会出事(小样本 / 零计数),以及 MAP(拉普拉斯平滑)如何补救,并写出 \(\hat p_c=(n_c+\alpha)/(N+\alpha K)\)。
- 你能区分"丢常数只在求 argmax 时合法"和"似然本身的数值不能乱丢常数"。
可以先放过的点
- 完整贝叶斯(对后验积分求期望):本课只取后验的峰(MAP)。把整个后验分布算出来、做贝叶斯预测,要用到共轭先验或采样/变分——等到学概率编程或扩散模型的变分下界时再回来。
- 噪声方差 \(\sigma^2\) 的联合估计:本课求 \(\theta\) 时把 \(\sigma\) 当常数。它自己的 MLE 是样本残差方差,先解 \(\theta\) 再回代即可,本课不展开。
- "指数族"的系统理论:本课只用到"很多分布密度都能写成 \(\exp(\text{关于 }\theta\text{ 的式子})\)、取 log 抵消 exp 后优化变简单"这一点,够用了;它的正式名字和完整理论(把数据浓缩成少量有用统计量、把参数换成更好算的形式等)等到专门讲这一族分布时再补。
- MLE 的渐近性质(一致性、渐近正态、Cramér–Rao 下界):这些保证"样本够多时 MLE 收敛到真值",是理论保障,现在不必吃透,等做统计推断或评测理论时再补。
- 非凸 NLL 的优化:高斯/伯努利的 NLL 是凸的、有闭式解;神经网络的 NLL 非凸,要靠梯度下降——那是模块后面最优化部分的主题。
下一课预告:我们已经看到 NLL 神奇地"长成"了各种损失。下一课用信息论(熵、交叉熵、KL 散度)从根上解释"损失为什么长这样",并把这一课的"最小化 NLL"、信息论的"最小化交叉熵"、以及"让模型分布逼近数据分布(最小化 KL)"三条线汇合证明成同一件事;那里会专门讲清 KL 散度不对称(forward 与 reverse KL 不是一回事)这个关键直觉。