前阵子帮一位转行做算法的朋友做技术面模拟,连续追问了他几个问题:为什么分类任务几乎都用交叉熵损失,而回归任务几乎都用均方误差?这两个损失函数是怎么来的?他公式背得很熟,代码也能跑通,但被问到"这两个东西的源头其实是同一个数学工具"时,明显卡住了。
这个工具就是极大似然估计(Maximum Likelihood Estimation,MLE)。它绝不只是概率论课本里的抛硬币习题,而是从线性回归、逻辑回归到深度神经网络的共同地基。你在PyTorch里写的nn.CrossEntropyLoss()、nn.MSELoss(),追根溯源都是某个概率假设下的负对数似然。这篇文章我想用一线开发者的视角,把这个地基从直觉到推导、从推导到工程实践中的坑,一次性讲透。不管你是刚入门机器学习,还是已经写了段时间模型但总觉得数学底子发虚,这篇文章都值得你静下心看完。
1. 抛硬币背后的数学直觉:MLE到底在求什么
要理解极大似然估计,最简单的入口就是抛硬币。假设我们手里有一枚材质未知的硬币,想估计它正面朝上的概率θ。我们连续抛了10次,结果有7次正面、3次反面。直觉告诉我们,θ的估计值应该是0.7。这个直觉当然没错,但我想让你回答一个更深的问题:为什么是0.7?为什么不是0.65,不是0.75?这时候,极大似然估计给出了一个看起来很绕、但逻辑上无懈可击的答案:在所有可能的θ取值中,我们选择那个"让已经发生的结果以最大概率出现"的数值。
也就是说,我们把"结果已经发生"这件事当成给定事实,反过来质问:到底是什么样的θ,让这次结果最可能发生?这个"反过来质问"的过程,就是"似然"(likelihood)二字的本质。
1.1 一个朴素但核心的提问方式
先把10次抛硬币的结果写成一个简单的事件:7次正面、3次反面。如果已知正面概率是θ,那么出现这个结果的概率是:
$$P(\text{7正3反} \mid \theta) = C_{10}^{7} \theta^{7} (1-\theta)^{3}$$
这里的$C_{10}^{7}$是从10次中选出哪7次为正面的组合数,它只依赖于抛掷次数,跟θ无关。现在,我们把θ当作自变量,把这个概率看成θ的函数,于是定义似然函数:
$$L(\theta) = C_{10}^{7} \theta^{7} (1-\theta)^{3}$$
极大似然估计要做的,就是找到让$L(\theta)$最大的那个θ。如果你还记得高数里的求极值步骤,对这个函数取对数再求导,令导数等于0,就能解出来。但先别急着算,我想先强调一个认知上的关键转变:**概率和似然,用的是完全相同的公式,但自变量和因变量互换了位置。**概率是已知θ,预测数据;似然是已知数据,反推θ。同一个公式,视角一转,意义完全不同。
1.2 似然与概率:同一种公式的两个视角
这个"视角互换"恰恰是很多初学者过不去的坎。具体来说:
- 概率:给定模型参数θ,计算某个事件发生的可能性。这里θ是固定的,事件是变化的。
- 似然:给定已经观测到的事件结果,评估不同θ值对这个结果的支持程度。这里事件是固定的,θ是变化的。
一个特别容易踩的坑是:$L(\theta)$这个函数对θ的积分并不等于1,所以它不是θ的概率分布。别把似然函数误会成"θ的概率密度"。在频率学派的视角下,θ是一个未知的固定值,没有概率分布可言,只有"哪个值看起来更合理"的问题。这一点想通了,后面理解贝叶斯方法时就不会打架。
1.3 为什么一个"细节"被丢掉了:C(n,k)的去留
回到刚才的式子。你会发现,在求"让L(θ)最大"的过程中,$C_{10}^{7}$这个组合数其实不重要。它是一个正的常数,不随θ变化,所以在求导时直接消失。这在数学上叫"常数因子不影响最大化问题的解"。但这个问题背后有一个更实用的工程隐喻:在真实AI项目里,数据量是百万、千万级别的,如果你把每个样本的组合权重都写进似然里,不仅毫无必要,还会让代码变得特别蠢。MLE真正在乎的,是数据中每种模式出现的相对频率,而不是这些模式在历史上具体的排列方式。这个道理,在你后面看语言模型、看自监督学习的损失函数时,会反复遇到。
我再留一个悬念供你思考:上面这个例子中,我们假设"正面出现概率是θ且每次独立",这个假设本身对不对?每次抛硬币真的相互独立吗?现实项目中几乎没有完全独立的数据,但MLE的先验假设仍然构成了几乎所有浅层模型的基础。这个假设何时成立、何时不成立,到第5章我会专门展开。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 似然函数的两种形态:离散与连续
讲完单个例子的直觉,我们把问题推广到一般情况。假设我们有一组独立同分布(i.i.d.)的观测样本$x_1, x_2, \dots, x_N$,它们服从某个带参数θ的概率分布。联合概率可以写成每个样本概率的乘积:
$$L(\theta) = \prod_{i=1}^{N} p(x_i \mid \theta)$$
这句话看起来只是概率论的连锁法则,但它是整个极大似然估计的枢纽。独立同分布假设一旦成立,复杂的高维联合概率就被拆解成简单的一维乘积,这是MLE在工程上可行的根本原因。
2.1 离散场景:伯努利分布的完整手推
我们还是用抛硬币,但这次把场景一般化:观测到N次独立抛掷,其中正面次数是$m$。写出似然:
$$L(\theta) = \prod_{i=1}^{N} \theta^{x_i} (1-\theta)^{1-x_i}$$
其中$x_i$取1表示第i次是正面,取0表示反面。取对数:
$$\ell(\theta) = \ln L(\theta) = \sum_{i=1}^{N}\left[x_i \ln\theta + (1-x_i)\ln(1-\theta)\right]$$
这个对数似然求导:
$$\frac{d\ell}{d\theta} = \sum_{i=1}^{N}\left[\frac{x_i}{\theta} - \frac{1-x_i}{1-\theta}\right] = 0$$
解这个方程,你会得到:
$$\hat{\theta}{\text{MLE}} = \frac{1}{N}\sum^{N} x_i$$
也就是说,正面概率的极大似然估计恰好就是样本均值——正面次数占总次数的比例。这个结论看似朴素,但它的意义重大:"频率等于概率"这个直觉,不是凭空成立的,它是MLE推导出来的结果。
2.2 连续场景:概率密度函数参与的微妙之处
离散场景下,每个观测值都对应一个大于零的概率,事情很干净。但进入连续随机变量后,问题来了:一个具体的连续值,比如身高175.00001厘米,它的准确概率是0。你没法直接代入某个"点的概率",怎么办?
这里就需要引入概率密度函数(PDF)的概念。观测值落在某个无穷小区间$[x, x+dx]$内的概率近似等于$f(x|\theta)dx$。由于所有样本共享同一个$dx$,而且这个因子不依赖θ,最大化密度乘积和最大化真实概率乘积,结论是等价的。所以在连续场景下,我们直接写:
$$L(\theta) = \prod_{i=1}^{N} f(x_i \mid \theta)$$
这看起来只是把$p$换成了$f$,但概念上是一次跨越:我们不是在说某个点出现"概率大",而是在说某个点附近的"概率密度高"。密度高的地方,样本落进去的可能性才大。这也是为什么高斯分布能在连续建模中占据统治地位——它的密度函数形式优美,对数后变成二次函数,求导友好。
2.3 为什么几乎所有教程都在优化"对数似然"
你可能已经注意到,我每一步都在把乘积取对数。这不是为了方便做题,而是有三个实打实的理由。
第一个理由是数学上的:$\ln$是严格单调递增函数,所以最大化$L(\theta)$和最大化$\ln L(\theta)$等价。第二个理由是计算上的:N个概率连乘很容易出现数值下溢。假设每个概率是0.1,一万个连乘就是$10^{-10000}$,这在任何浮点精度下都直接变成0。但只要取对数,就变成一万个$-2.3$相加,结果是负的几千,完全在可计算的范围内。
第三个理由则更深层:负对数似然(NLL)天然对应着信息论中的交叉熵。当你把最小化负对数似然看作"最小化模型分布与真实分布之间的差异"时,MLE和分类任务的联系就浮出水面了。这个连接我在第4章会详细推给你看。
3. 亲手推一遍:正态分布与最小二乘的等价性
现在我们进入这篇文章第一个"原来如此"时刻:为什么回归任务的损失函数是均方误差(MSE)?大多数人第一次接触MSE时,得到的解释是"它衡量预测与真实的欧氏距离",但这只说了表象。从MLE的角度看,MSE根本不是人为设计的巧合,而是"噪声服从高斯分布"这一假设下的必然结果。
考虑一个线性回归模型:
$$y_i = w^{\top} x_i + \epsilon_i$$
其中$\epsilon_i$是噪声项。我们假设$\epsilon_i \sim \mathcal{N}(0, \sigma^2)$,即零均值、方差$\sigma^2$的高斯分布。这个假设在物理测量、经济学数据、传感器信号等场景中非常常见,依据来自中心极限定理——大量微小且独立的误差叠加后,整体趋向正态分布。
3.1 高斯噪声假设的含义
在这个假设下,给定输入$x_i$时,$y_i$的条件分布也是高斯分布,均值是$w^{\top} x_i$,方差是$\sigma^2$:
$$y_i \mid x_i \sim \mathcal{N}(w^{\top} x_i, \sigma^2)$$
于是单个样本的密度函数是:
$$f(y_i \mid x_i; w) = \frac{1}{\sqrt{2\pi}\sigma} \exp\left(-\frac{(y_i - w^{\top} x_i)^2}{2\sigma^2}\right)$$
注意这里我把参数$w$写进了条件里。对N个独立样本,联合密度就是N个这样的函数相乘。这个乘积中,$\frac{1}{\sqrt{2\pi}\sigma}$是常数,真正跟$w$有关的部分全在指数里面。
3.2 最大似然如何"恰好"导出MSE
取对数后,所有指数项都变成线性项。对数似然写作:
$$\ell(w) = -\frac{N}{2}\ln(2\pi) - N\ln\sigma - \frac{1}{2\sigma^2}\sum_{i=1}^{N}(y_i - w^{\top} x_i)^2$$
我们想最大化$\ell(w)$。第一项和第二项跟$w$无关,可以丢掉。前面的系数$-\frac{1}{2\sigma^2}$也是负常数,同样不影响求$w$的极值。于是问题变成:
$$\max_w ; -\sum_{i=1}^{N}(y_i - w^{\top} x_i)^2 \quad \Longleftrightarrow \quad \min_w ; \sum_{i=1}^{N}(y_i - w^{\top} x_i)^2$$
右边这个式子,就是MSE损失。也就是说,当你用均方误差作为回归损失时,你其实默认了一个前提:预测值与真实值之间的误差服从高斯分布。 你不是在"选择一个方便的损失函数",而是在"接受一个关于数据生成过程的假设"。
3.3 换一种损失函数,等价于换一种假设
这个等价关系最大的工程启示是:如果数据的真实噪声性质跟高斯假设不符,MSE就不是最优选择。举个例子,当数据中有大量离群点(outlier)时,高斯分布那条又细又长的尾巴会被离群点严重拉偏。这时候如果把噪声假设换成拉普拉斯分布,MLE推导出来的损失函数就成了L1损失,也就是绝对误差。L1损失的优点是它对离群点没那么敏感,因为它惩罚误差的绝对值而不是平方。
实际操作中,很多团队处理含有离群点的回归问题时,会直接换用Huber损失——它在误差较小时表现为L2,误差大时表现为L1。从MLE的视角看,这相当于在一个"近处像高斯、远处像拉普拉斯"的混合噪声假设下做了近似推断。理解了这层关系,你在调loss的时候就不会只是上网搜"哪个loss好用",而是会想"我的数据的噪声到底是什么样的分布"。
4. 深度学习里的MLE:交叉熵损失的本质来源
如果说线性回归是MLE的"小试牛刀",那么深度神经网络就是MLE在工程上最庞大的应用场景。你天天写的nn.CrossEntropyLoss(),从数学根源上讲,就是多分类问题下的负对数似然。
4.1 分类模型输出的是条件概率分布
在分类任务中,模型的任务不再是预测一个连续数值,而是预测样本属于各个类别的概率。假设有K个类别,模型输出一个K维向量,其中第c个分量表示样本属于类别c的概率。理想情况下,这个输出应该构成一个合法的概率分布——所有分量非负且求和为1。
这就解释了为什么神经网络分类头的最后一层几乎总是softmax。softmax的作用就是把任意实数向量"压"成一个概率分布:
$$p(y=c \mid x; \theta) = \frac{\exp(z_c)}{\sum_{j=1}^{K}\exp(z_j)}$$
其中$z_c$是网络最后一层logits的第c个分量。没有softmax,你得到的只是一堆凌乱的实数,谈不上"概率",自然也谈不上"极大化样本出现的概率"。
4.2 softmax + 交叉熵:一次干净的推导
给定N个独立样本$(x_i, y_i)$,其中$y_i$是类别标签。模型对第i个样本输出的条件概率是$p(y_i \mid x_i; \theta)$。联合似然是:
$$L(\theta) = \prod_{i=1}^{N} p(y_i \mid x_i; \theta)$$
取负对数得到损失函数:
$$\mathcal{L}(\theta) = -\sum_{i=1}^{N} \log p(y_i \mid x_i; \theta)$$
这正好是交叉熵损失。如果你把$p(y_i|x_i; \theta)$展开成softmax形式,然后对logits $z_c$求导,会得到一个干净得让人怀疑人生的结果:
$$\frac{\partial \mathcal{L}}{\partial z_c} = p_c - \mathbb{1}(y = c)$$
也就是说,logits的梯度就是"模型预测概率"减去"真实标签的one-hot编码"。 这个结果在纯数学推导里往往一笔带过,但它是深度学习反向传播高效稳定的关键之一。预测对了($p_c$接近1),梯度接近0,参数更新缓慢;预测错了($p_c$很小),梯度很大,模型被推动着往正确的方向走。你去看Guiding Gradient、知识蒸馏、标签平滑等论文时,会发现很多技巧本质上都是在调整这个梯度形式。
4.3 一套视角看遍所有监督损失
现在我们把前两章连起来,你会有一种"众多个损失函数原来是一家人"的通透感:
| 任务类型 | 概率假设 | 损失函数 | MLE推导等价形式 |
|---|---|---|---|
| 回归 | 高斯分布 | MSE | 最大化高斯似然 |
| 二分类 | 伯努利分布 | BCE | 最大化伯努利似然 |
| 多分类 | 类别分布 | Cross-Entropy | 最大化类别分布的似然 |
| 计数数据 | 泊松分布 | Poisson NLL | 最大化泊松似然 |
为什么讲这个统一视角?因为实际做项目时,你会遇到一些"非标准"任务。比如预测一个电影票房,数值可能很分散甚至粗略到小数点后一位,这时你用MSE未必最佳;如果你观察到的数据是明显的重尾分布,那么换成Gamma分布的NLL哪怕训练麻烦一些,最终效果也可能显著提升。理解了MLE这个源头,你就不再是"会用别人设计好的损失函数",而是"能从数据分布出发自己设计目标函数"。
5. 优化MLE时避不开的数值与工程问题
理论推导是一回事,把MLE落实成代码是另一回事。这一章是我个人在工程项目里踩坑最多的地方,也是很多人从"看得懂公式"到"跑得通模型"之间的那道坎。
5.1 连乘溢出:为什么训练代码里全是对数
刚才反复提到,连乘的概率会迅速下溢成0。在100万条样本的大规模训练中,即便每条样本的概率只有0.5,连乘结果也是$0.5^{1000000}$,在双精度浮点数下直接变成0。更麻烦的是,一旦连乘变成0,取对数就变成负无穷,整个训练过程直接崩溃。
所以任何实现负对数似然的代码,都必须在这个"乘积"之前做对数变换。你可以写一个最简单的高斯NLL实现:
python复制def gaussian_nll(y_true, y_pred, sigma=1.0):
# 等价于MSE,但显式写出了对数密度
const = 0.5 * np.log(2.0 * np.pi)
se = (y_true - y_pred) ** 2
nll = 0.5 * se / (sigma ** 2) + np.log(sigma) + const
return np.mean(nll)
注意加上的1e-12之类的小常数,是为了防止对数值为0的概率取对数。这个细节在写自定义损失函数时高频出现,尤其当你处理长尾分布或极端类别时。
5.2 log-sum-exp的陷阱
在多分类交叉熵里,$p(y_i|x_i)$是softmax的输出,它分数形式的对数需要小心展开:
$$\log p(y=c \mid x) = z_c - \log\left(\sum_{j=1}^{K}\exp(z_j)\right)$$
右边第二项是个典型的log-sum-exp表达式。直接按公式写,np.sum(np.exp(z))会面临两个问题:如果$z_j$特别大,exp(z_j)溢出成无穷大;如果$z_j$特别小,exp(z_j)下溢成0。好在log-sum-exp有一个人尽皆知但值得反复强调的技巧:先把所有$z_j$减去它们的最大值$a = \max_j z_j$,再exp。
python复制def logsumexp(z):
a = np.max(z)
return a + np.log(np.sum(np.exp(z - a)))
这样做为什么有效?因为减去最大值后,指数里最大的数是0,其他都是负数,exp的结果被牢牢压在0到1之间,数值完全可控。这个技巧在聚类算法、概率图模型、语言模型解码中到处出现,已经被视为"数值计算的基本修养"。
5.3 i.i.d.假设与mini-batch的真实关系
MLE的第一个等号就依赖于独立同分布假设。但现实中的训练数据真的独立同分布吗?图片数据中相邻像素高度相关,文本数据中前后token有明显依赖,时间序列更是天然带自相关。严格来说,真实数据几乎都不满足i.i.d.。
那为什么我们还能在深度学习里安心使用基于MLE的交叉熵、MSE?答案是mini-batch训练提供了一个近似视角。随机从数据集中抽取一批样本,这个抽样过程本身就是一种"使样本近似独立同分布"的操作。它基于的假设是:经验分布能够近似总体分布,而batch内的样本可以被视为来自该经验分布的独立抽样。这就是为什么训练前必须做shuffle——破坏掉数据中的顺序依赖,让batch更接近i.i.d.。
当你处理的时间序列模型必须保留时间顺序时,i.i.d.假设就彻底失效了,这时需要采用诸如时序条件似然、teacher forcing等替代目标。理解了MLE的假设边界,你会明白这些复杂架构为何要从"联合分布建模"退而求其次,改为"逐时刻条件分布建模"。
6. MLE的边界:过拟合、不可识别性与贝叶斯视角
任何强大的工具都有它的适用范围。MLE也不例外。这一章我们聚焦三个常见的"翻车现场",顺便引出正规化这项AI工程中离不开的技术。
6.1 小样本下MLE的"过度自信"
MLE的目标是把观测数据上的似然最大化。当样本量很小、而模型参数很多时,MLE会做什么?它会拼尽全力拟合每一个训练样本,包括噪声。比如你用10个样本去训练一个9次多项式回归,模型可以通过9个多项式系数把所有样本点完美穿过,残差降到0。这时候,高斯似然密度函数里的指数项变成$\exp(0)=1$,似然达到最大值。
这看起来是好事,但换来的代价是:模型对没见过的数据毫无泛化能力。这就是过拟合的本质——在最大化"训练集上的似然"与"测试集上的似然"之间出现严重背离。MLE只管前者,不管后者。
你可能会问:那我把模型拿出去做推理时,数据分布不变,测试集上的似然也应该高才对啊?问题是,模型的拟合能力太强后,它学到的不是分布规律,而是训练样本自身的噪声模式。这些噪声模式在测试集中是随机的,不可能复现。
6.2 不是所有参数都"可识别"
第二个坑更隐蔽:有时候,多个不同的参数取值会给出一模一样的似然值。在这些情况下,MLE无法区分哪个参数才是"真正"的参数。在统计上,这叫不可识别性。
举一个神经网络里最常见的例子:假设一个两层全连接网络,第一层有100个神经元。你把第一层的第37个神经元和第二层的对应权重同时乘以-1,因为激活函数通常是奇对称的(比如tanh),网络输出完全不变。也就是说,参数空间里存在大量等价的对称路径,它们对应同一函数。MLE的解在哪个位置,完全取决于初始化。这解释了为什么深度学习训练要精心设计随机种子——不是玄学,而是MLE本身在这个非凸、多对称的损失面上就有无数个等价解。
6.3 从MLE到MAP:正则项的贝叶斯解释
既然MLE只盯着数据,那怎么把"对复杂度惩罚"的偏好引入进来?答案是把视角从频率学派切换到贝叶斯学派。贝叶斯公式说:
$$p(\theta \mid D) = \frac{p(D \mid \theta), p(\theta)}{p(D)}$$
其中$p(\theta)$是参数的先验分布,$p(\theta|D)$是后验分布。如果我们最大化后验分布,得到的是最大后验估计(MAP)。由于分母$p(D)$不依赖于θ,我们可以直接最大化分子:
$$\hat{\theta}{\text{MAP}} = \arg\max{\theta} ; \log p(D \mid \theta) + \log p(\theta)$$
左边是MLE,右边多出来一项先验的对数。这一项,就是所有深度学习中正则化的贝叶斯源头。
具体对应关系非常直观:如果你对权重设定一个均值为0、方差为$\lambda$的高斯先验,那么$\log p(\theta)$正比于$-\frac{1}{2\lambda}|\theta|^2$,地图估计的目标就变成"原本的负对数似然 + $\frac{1}{2\lambda}|\theta|^2$",这就是L2正则化(weight decay)。如果你用的是拉普拉斯先验,得到的则是L1正则化。
很多工程师一直把weight decay当作"防止过拟合的工程小把戏",但从贝叶斯角度看,它其实是你对参数取值先天的"怀疑"——你相信权重不太可能取特别大的值,所以人为压低它们。这种先验观点还能解释另一个直观现象:当数据量非常大时,似然项越来越强,先验的影响逐渐减弱,正则化效果也会随时间衰减。这就是为什么大数据集上可以调低正则化系数。
再往深走一步,这个概念还能延伸到Dropout、数据增强等一切约束模型假设空间的手段——它们本质上都是对"什么参数组合更可能产生好模型"的一种先验表达。我在具体项目里有一条经验:如果你发现在调参过程中无论怎么调weight decay都压不住过拟合,先回头审视你的数据增强与模型容量是否匹配,往往比单纯加大正则化系数效果更好。
最后再分享一个我自己的体会:MLE的美妙之处在于,它给你提供了一种通用的"反推"思维——面对任何任务,先假设数据生成机制,写出似然,再推导目标函数。这套流程几乎可以套用到所有机器学习建模问题上,同时也是你理解贝叶斯推断、变分推断、因果推断这些进阶理论的地基。当你把MLE真正内化之后,再去看各种模型和损失函数,你看到的就不再是一堆孤立公式,而是一整棵逻辑树。
