最大似然估计(Maximum Likelihood Estimation, MLE)大概是统计学里最常用、也最容易被误解的一个估计方法。很多人学了公式会套,但真换一个场景就懵了,不知道为什么这么做,更不知道结果为什么可信。这篇我想从直觉讲起,带你一步步把MLE的底层逻辑、推导过程和实战细节捋清楚。不管你是做数据分析、机器学习,还是搞科研处理实验数据,只要涉及“根据观测数据反推参数”,MLE都是绕不开的核心工具。
我会用大量具体例子和可直接复现代码来讲,尽量少堆数学符号,但关键的推导过程会保留——毕竟只看结论的话,遇到问题你还是不会举一反三。
1. 从抛硬币说起:MLE到底在干什么
1.1 概率和似然:同一个式子,不同的读法
MLE的核心就一句话:在给定观测数据的前提下,找到一组参数,使得这组数据出现的“可能性”最大。
听起来很好理解,但很多人卡在“可能性”这三个字上,因为概率和似然在数学形式上几乎一样,含义却完全不同。
举个例子。你手里有一枚硬币,不知道它是否公平,假设正面朝上的概率是 θ。你抛了 10 次,结果 7 次正面、3 次反面。那么:
- 概率视角:如果 θ = 0.5,问“抛10次出现7次正面”的概率是多少。这个好算,二项分布公式套进去就行。
- 似然视角:已知结果就是“7正3反”,问“θ 是多少时,这个结果最可能发生”。这时θ是未知的,我们要把它当成一个变量,去看不同θ下同一个结果的概率值。
看出来区别了吗?概率是已知参数、预测结果;似然是已知结果、反推参数。
严格一点说,似然函数写作 L(θ | data),读作“给定数据下参数θ的似然”,本质上就是在 θ 已经给定的条件下得到这组数据的概率密度(或质量函数)值,但我们关注的是它作为 θ 的函数时在哪个位置取得最大值。
记住这个视角转换,后面所有公式都不会再让你头晕。
1.2 最大化似然:我们猜的那个参数
继续抛硬币的案例。假设我们设正面概率为 θ,抛了 n 次,其中 k 次正面。似然函数为:
L(θ) = θ^k · (1 - θ)^(n-k)
这个函数在 θ 取不同值时,对应的“出现该数据”的可能性大小不同。我们要找的估计值 θ̂ 就是让 L(θ) 最大的那个 θ。
直接把 L(θ) 对 θ 求导等于0就行了。但是这里有个实操小技巧:乘积形式求导非常麻烦,所以通常对似然函数取对数,变成求和形式。因为对数函数是单调递增的,取对数不会改变最大值的位置,但能大幅简化计算。这就是“对数似然”的由来。
对数似然写出来是:
ℓ(θ) = k·ln(θ) + (n-k)·ln(1-θ)
求导:
dℓ/dθ = k/θ - (n-k)/(1-θ) = 0
解出来就是 θ̂ = k/n。也就是说,根据MLE,我们对正面概率的最佳估计就是样本中正面的比例。
这个结果非常直观,也是 MLE 的第一个“让你觉得废话”的例子。但别小看它,这个最简单的框架,是一切复杂模型的起点。
注意:这里隐含了一个假设——每次抛硬币是独立的,且正面概率恒定。如果硬币被人动了手脚,或者抛掷方式不同导致概率不固定,那模型假设本身就需要重新思考。MLE 再强大,也是建立在模型假设之上的。
2. 经典推导实战:从离散到连续的完整流程
2.1 离散案例:伯努利分布下的MLE
上面已经用二项分布算了一次,但实际建模中更常见的是把每次抛硬币当成伯努利试验,也就是对每一个观测值 x_i(0表示反面、1表示正面),写出它的概率质量函数:
P(x_i | θ) = θ^(x_i) · (1-θ)^(1-x_i)
然后 n 个独立样本的联合概率就是每个样本概率的乘积:
L(θ) = ∏ θ^(x_i) · (1-θ)^(1-x_i)
取对数:
ℓ(θ) = Σ [x_i·ln(θ) + (1-x_i)·ln(1-θ)]
这个求和形式特别好用,因为它把指数变成了乘积、把乘积变成了求和。求导:
dℓ/dθ = Σ x_i/θ - (n - Σ x_i)/(1-θ) = 0
设 Σx_i = k,解出来的结果还是 θ̂ = k/n。
你可能觉得绕了一大圈结果没变,但这个推导过程很重要,因为它是“从样本概率乘积到对数求和再求导”的标准范式。以后遇到任何分布,只要写出似然函数,走这套流程就不会出错。
2.2 连续案例:正态分布均值和方差的MLE
离散情况解决后,我们把同样思路用到连续分布。最常见、也最实用的是正态分布 N(μ, σ²) 的参数估计。
设我们有 n 个独立同分布的样本 x_1, x_2, ..., x_n,来自正态分布。每个样本的概率密度为:
f(x_i | μ, σ²) = (1/√(2πσ²)) · exp(-(x_i-μ)²/(2σ²))
联合密度(也就是似然函数)是这些密度的乘积。取对数后:
ℓ(μ, σ²) = -n/2·ln(2π) - n/2·ln(σ²) - (1/(2σ²))·Σ(x_i-μ)²
现在有两个参数,需要分别求偏导并令其为0。
对 μ 求偏导:
∂ℓ/∂μ = (1/σ²)·Σ(x_i-μ) = 0
解得 μ̂ = (1/n)·Σx_i,也就是样本均值。
对 σ² 求偏导:
∂ℓ/∂σ² = -n/(2σ²) + (1/(2σ⁴))·Σ(x_i-μ)² = 0
解得 σ̂² = (1/n)·Σ(x_i-μ̂)²。
看出来了吗?正态分布下,均值的MLE是样本均值,方差的MLE是“除以n”的样本方差,而不是教科书里常说的除以(n-1)的无偏方差。
这个细节每年能坑一批人。MLE 给出的是渐近无偏的估计量,在小样本下方差估计会系统性偏低。所以如果你在做小样本统计推断,直接用 σ̂² 做 t 检验、F 检验,误差会偏大。实际处理中小样本场景通常会改用无偏修正版本,但你要清楚两者来源的区别:一个是 MLE 优化结果,一个是无偏性要求下的修正。
提示:在做正态分布参数估计时,均值直接用 MLE 没问题,方差记得考虑样本量大小。n 很大时两者几乎没差别;n 只有十几个时,优先用无偏修正版本。
3. 为什么MLE值得信任:三个关键性质
3.1 不变性:估计出来的参数换形式也方便
这是 MLE 一个非常实用的优点:如果 θ̂ 是 θ 的MLE,那么对于任意函数 g(θ),g(θ̂) 就是 g(θ) 的MLE。换句话说,你不需要重新推导,直接把估计值代进变换函数就行。
举个例子。你在做方差分析,假设数据服从指数分布,参数是 λ(率参数)。MLE 估计出来 λ̂ = 1/x̄。如果你关心的是均值 μ = 1/λ,那么 μ 的MLE 直接就是 x̄,不需要再搞一套优化。
另一个例子是逻辑回归中的几率(odds)。如果模型估计出概率 p̂,那么 odds 的MLE 就是 p̂/(1-p̂),你直接代入计算即可,不用再跑一次优化。
这个性质在实战中特别省事,因为很多业务指标是参数的复杂函数:比如金融领域的 VaR(在险价值)、可靠性工程中的MTBF(平均故障间隔时间)。只要参数估计出来了,这些指标的MLE就是直接把估计值代入函数。
3.2 相合性与渐近正态性
相合性说的是:当样本量 n 趋于无穷大时,MLE 估计值会依概率收敛到参数的真实值。也就是“数据越多,估计越准”,这个性质让 MLE 在理论上成为可靠的大样本方法。
渐近正态性更实用:当 n 足够大时,θ̂ 的分布近似为正态分布,均值是真实 θ,方差是 Cramér-Rao 下界(也就是所有无偏估计量中可能达到的最小方差)。这意味着在大样本下,MLE 不仅准,而且“有效率”——它的方差逼近理论极限。
这个性质也直接导出了实践中常用的置信区间构造方法:
θ̂ ± z_(α/2) · se(θ̂)
其中标准误 se(θ̂) 可以通过 Fisher 信息量来计算。Fisher 信息量就是对数似然函数二阶导数的负期望值,直观理解是“似然函数在峰值附近有多尖锐”——越尖锐,说明参数辨识度越高,标准误越小。
这就是为什么我们在论文里经常看到“基于MLE的置信区间”,因为只要样本量够大,不需要做复杂的模拟,直接用正态近似就能给出足够准确的区间。
3.3 为什么效率高:与 Cramér-Rao 下界的关系
Cramér-Rao 下界是一个理论基准。它告诉我们:在满足一定正则条件时,任何无偏估计量的方差都不可能低于某个值,而这个值由 Fisher 信息量决定。
MLE 在样本量趋于无穷时可以逼近这个下界,也就是说,在大样本场景下,你很难找到比 MLE 方差更小的无偏估计量。这解释了为什么很多高级模型的默认估计方法都是MLE——不是因为它计算简单,而是因为它的统计性质确实优秀。
当然,这不是说 MLE 在所有场景下都最好。如果你的样本量很小,MLE 可能方差大、偏差大,这时候贝叶斯估计(加上先验)或者收缩估计(比如 James-Stein 估计)可能表现更好。但如果你没有特别强的先验信息,样本量又还可以,MLE 是一个非常稳妥的选择。
4. 当解析解不存在时:数值求解方法
4.1 logistic回归的MLE为什么没有闭式解
到目前为止我们举的例子都能解出解析解,但现实模型很多不行,最典型的就是 logistic 回归。
logistic 回归中,每个样本属于类别1的概率为:
p_i = 1/(1+exp(-(β₀+β₁x_i)))
似然函数是各样本概率的乘积:
L(β) = ∏ p_i^(y_i) · (1-p_i)^(1-y_i)
取对数后,你需要对 β 求导并令其为0。但问题是 p_i 本身是 β 的非线性函数,求导之后得到的方程包含多项 exp 项,不可能写成 β = 某个表达式的形式。所以必须用数值方法迭代求解。
这是一个在应用时经常让人困惑的点:理论上MLE没问题,但实际执行要靠优化算法。理解这点你就明白为什么机器学习库中训练逻辑回归模型,底层都跑的是迭代优化,而不是像线性回归那样直接算闭式解。
4.2 牛顿法和梯度上升法
求解MLE的数值方法有很多,常用的两种是梯度上升法和牛顿法。
梯度上升法适用于任何可微的似然函数。思路是沿着对数似然函数的梯度方向迭代更新参数:
β_new = β_old + α · ∇ℓ(β_old)
其中 α 是学习率,需要手动调节。太大容易震荡甚至发散,太小收敛很慢。这个方法实现简单,但收敛速度一般,尤其接近最优值时可能出现来回震荡。
牛顿法利用了二阶导数信息,迭代公式是:
β_new = β_old - [H(β_old)]⁻¹ · ∇ℓ(β_old)
其中 H 是 Hessian 矩阵(对数似然的二阶偏导)。因为利用了曲率信息,牛顿法通常收敛更快,而且不需要调学习率。但代价是每步都要计算和求逆 Hessian 矩阵,样本量大、特征多时计算成本很高。
实际工程中还有各种变体:拟牛顿法(BFGS、L-BFGS)、随机梯度下降(SGD)、Adam 等。它们本质上是在收敛速度、每步计算成本和稳定性之间做权衡。
实操心得:我平时做MLE数值求解,首选 BFGS 或 L-BFGS,因为它们不需要精确 Hessian 矩阵,但保留了超线性收敛速度。除非是深度学习那种百万级参数的场景,否则 L-BFGS 通常够用且稳定。
4.3 实操注意事项
数值求解MLE时,有几个细节值得留意。
第一,加负号变最小化。大多数优化库默认做的是最小化,所以你需要定义负对数似然函数,然后交给优化器去最小化。这个过程在代码里很容易漏,漏了结果会发散到无穷。
第二,梯度计算建议解析推导,不要用数值差分。向前差分、中心差分在参数维度高时误差大、速度慢,还可能因为步长选择不当导致优化过程不稳定。能用解析梯度就用解析梯度,推导有困难时可以用自动微分(比如 PyTorch、TensorFlow、JAX 自带的能力)。
第三,对数域计算防止下溢。当样本量大时,似然函数的值可能小到超出浮点数精度下限。比如一万个概率相乘,每个0.5,结果就是 0.5^10000 ≈ 10^(-3010),这在双精度浮点数下直接变成0。但取对数后就是 -3010,完全没问题。所以永远不要直接乘概率,必须取对数。
第四,初值选择很关键。多参数模型的目标函数往往有多个局部极值,不同初值可能收敛到不同结果。常见做法是从多个随机初值启动优化,选择似然最大的那个结果。也可以用矩估计作为MLE迭代的初值,这样可以少走弯路。
5. 用Python亲手实现一个MLE
5.1 模拟数据与模型设定
理论说再多,不如跑一次代码。我们模拟一个正态分布数据,然后用MLE反推出真实参数。
假设真实分布是 N(μ=2, σ²=9),我们抽取 n=200 个样本。然后写下负对数似然函数,用 scipy.optimize.minimize 求解参数。
import numpy as np from scipy.optimize import minimize # 设定随机种子,结果可复现 np.random.seed(42) # 真实参数 mu_true = 2.0 sigma_true = 3.0 # 生成样本 n = 200 data = np.random.normal(mu_true, sigma_true, size=n) # 负对数似然函数 def neg_log_likelihood(params): mu, sigma = params # 防止sigma出现非正数 if sigma <= 0: return 1e10 n = len(data) ll = -n/2 * np.log(2*np.pi) - n * np.log(sigma) - np.sum((data - mu)**2) / (2 * sigma**2) return -ll # 初值 init_params = np.array([0.0, 1.0]) # 优化求解 result = minimize(neg_log_likelihood, init_params, method='BFGS') print("真实参数:mu =", mu_true, "sigma =", sigma_true) print("MLE估计:mu =", result.x[0], "sigma =", result.x[1])这段代码跑出来的结果应该非常接近 mu=2.0, sigma=3.0。因为 BFGS 默认是拟牛顿法,一般几十步就能收敛。
5.2 构建负对数似然与优化
步骤拆分一下。
第一步,定义参数向量。这里有两个参数 μ 和 σ,我们把它们打包成一个向量 params。
第二步,写负对数似然函数。注意两点:一是用 np.log 而不是 math.log,因为后者不支持数组运算;二是要加 sigma <= 0 的判断,否则优化器可能在搜索过程中尝试负的sigma,导致log(σ²)出错。
第三步,交给 minimize。method 我用的是 BFGS,如果你用 L-BFGS-B 也可以,后者还能加边界约束,比如把sigma限制在(0, +∞)区间,这样更保险。
5.3 结果解读与对比
跑完代码后,你可以看看估计值和真实值的偏差,并计算出标准误。标准误可以从优化结果的 hess_inv 中得到。
# 用Hessian矩阵的逆估计标准误 hessian_inv = result.hess_inv # scipy的BFGS结果中hess_inv是近似逆Hessian # 标准误 = sqrt(diag(H^-1)) 的对角线 se = np.sqrt(np.diag(hessian_inv)) print("标准误:mu =", se[0], "sigma =", se[1])这里的理论依据就是前面讲的渐近正态性:在大样本下,MLE估计量的协方差矩阵可以用负对数似然的Hessian矩阵的逆来近似。如果你求的是对数似然的最大化,那对应的是负对数似然最小化,所以 Hessian 的逆就是协方差矩阵的估计。
在实际项目中,我习惯把这段封装成一个函数,输入数据和概率密度函数(或对数概率密度函数),自动返回参数估计、标准误和收敛信息。这样后续换模型只需要改密度函数就行。
实操心得:不要盲目相信 optimize 的默认收敛判断。我的习惯是同时输出梯度范数和迭代次数,如果梯度范数接近0且迭代次数不多,才算收敛正常。如果优化器达到最大迭代次数还没收敛,先检查是不是初值问题,再检查似然函数是否有 NaN。
6. 实战中容易踩的坑
6.1 多个极值点与初值敏感性
前文提过,很多模型的似然函数不是单峰的。以混合模型为例,两个高斯混合的似然函数通常有多个局部极大值,其中某些峰值对应的参数组合本身没有实际意义。
解决思路有几种。一是全局优化方法,比如模拟退火、遗传算法,但速度慢。二是多重起点法,随机生成几十组初值,分别优化,取似然最大的。这是实用中性价比最高的方案。三是为初值提供领域知识,比如先用 KMeans 聚类结果作为混合模型参数的初始估计,这会极大提升收敛到全局最优的概率。
6.2 参数不可识别
这是一个容易被忽略的陷阱。当不同参数组合产生完全相同的似然值时,MLE 无法从数据中区分它们,这时候估计结果没有唯一性。
典型例子是线性回归中两个特征完全相关(多重共线性)。此时系数 β₁ 和 β₂ 可以一个增大一个减小,但预测值完全不变,似然也完全不变。这种情况下,数值优化会变得不稳定,Hessian矩阵接近奇异,标准误会爆炸。
处理方法通常是对参数施加约束、合并特征,或者使用正则化(如岭回归)。在纯MLE框架下,也可以用 profile likelihood,把感兴趣的参数固定在一个网格上,其他参数最大化,观察似然剖面是否平坦来判断可识别性。
6.3 样本量带来的偏差问题
MLE 的优良性质大多基于大样本。小样本时,MLE 可能偏差明显。拿正态分布方差估计来说,n=10 时 MLE 方差平均会低估约10%。如果 n=5,这个偏差会到约20%。
所以当你手头样本量很小时,可以考虑用无偏修正版本,或者用 Bootstrap 来评估 MLE 的不确定性。Bootstrap 的做法是重采样数据,对每个重采样样本重新做MLE,得到估计值的分布。这比单纯依赖渐近正态区间更靠谱。
6.4 数值稳定性技巧
最后分享几个数值计算上的实用技巧。
一是所有概率密度计算统一在 log 域操作,最后如果需要概率再 exp 回去,但通常不需要。
二是在密度函数中加上极小值保护。比如计算正态分布密度时,尾部的 exp 项可能下溢到0,此时 log 会变成负无穷,需要直接舍弃这项或返回一个非常大的负数。
三是浮点数精度问题。当数据量很大时,对数似然的值可能是 -1e6 量级,优化器对这样大的值的梯度可能失去精度。常见做法是对对数似然除以样本量,变成平均对数似然,再优化。这样数值量级更稳定,也不影响最优参数的位置。
7. MLE与矩估计的选择:我的一点使用体会
7.1 矩估计是什么
矩估计(Method of Moments, MoM)是比 MLE 更古老的方法。思路粗暴:用样本矩代替总体矩,然后解方程。
比如正态分布,总体一阶矩是 μ,样本一阶矩是 x̄,所以 μ 的矩估计就是 x̄。总体二阶矩是 σ²+μ²,样本二阶矩是 (Σx_i²)/n,解方程得到 σ² 的矩估计。你看,对正态分布来说,矩估计和MLE结果一致。
但对很多分布,两者结果不一样。比如均匀分布 U(0, θ),矩估计解出来 θ̂_MoM = 2·x̄,而MLE解出来 θ̂_MLE = max(x_i)。哪个更合理?显然是 θ̂_MLE,因为你观测到的最大样本值一定小于θ,用它作为边界估计更贴近真实;而2倍均值在数据分布偏斜时误差往往很大。
7.2 两者对比
| 维度 | 最大似然估计 (MLE) | 矩估计 (MoM) | |------|-------------------|-------------| | 求解难度 | 可能需要数值优化 | 通常直接解方程,计算简单 | | 统计效率 | 大样本下逼近最优方差 | 一般效率较低 | | 小样本表现 | 可能有偏差 | 无偏性要看具体分布 | | 适用场景 | 数据分布明确、需要精确推断 | 快速估计、分布不明确时 | | 模型约束 | 需要写出似然函数 | 只需要写出矩条件 |7.3 选择建议
我的经验是:如果数据生成机制相对明确,优先用MLE;如果只是做初步探索,或者分布假设难以验证,矩估计能更快给出一个不算太离谱的结果。
有时候两者可以结合,比如用矩估计结果作为MLE迭代的初值,既能利用矩估计的快速,又能获得MLE的高效。这种做法在估计混合模型参数时特别有用。
另外一个容易被忽视的点:矩估计在某些分布下可能根本无解。比如 t 分布的自由度参数,矩估计依赖于高阶矩存在性,如果自由度小于2,连方差都不存在,矩估计直接失效。这时候MLE反而更稳健。
最后再分享一个小技巧:当你构建好一个MLE模型并准备用于业务决策,可以顺手做一个简单的模型诊断。把估计参数代回模型,重新模拟一批数据,看模拟数据的关键统计量(均值、方差、分位数)是否与真实数据接近。如果差距明显,说明模型假设可能有问题,这时候问题往往不在MLE本身,而是在于你选错了概率分布。
MLE这个工具,入门容易,用明白需要时间。多动手推导几个分布,多跑几次数值实验,踩过几次坑之后,你对它的理解会比看十篇教程都深刻。