在学习概率论与数理统计时,几乎每一个人都曾产生过强烈的困惑:

计算**总体方差(Population Variance)**时,分母是总数 NN; 但当我们从总体中抽取 nn 个样本去估计整体离散度时,**样本方差(Sample Variance)**的分母却莫名其妙地变成了 n1n - 1

很多教材往往只用一句轻描淡写的“因为损失了一个自由度”带过,但这并没有解答工程师心中的疑问:为什么偏偏是减 1?如果不管它继续除以 nn,究竟会发生什么?

而在计算机工程与数据科学的落地代码中,还有一个更为致命的隐藏陷阱:教科书上为了手算方便而推导的“平方和展开公式”,如果直接写进程序里,会在特定数据分布下发生灾难性的浮点精度雪崩,甚至算出一个极其荒谬的负数方差!

本站的描述统计计算器同时提供了总体方差 σ2\sigma^2 与无偏样本方差 s2s^2 的精确计算。这篇文章详细拆解背后的数学推导与工业级算法实现。


1. 核心直觉:样本均值比真实均值“更贴近数据”

方差衡量的是一组数据相对于其均值的离散程度(平方距离的平均值)。

设总体的真实均值为 μ\mu,真实方差为 σ2\sigma^2。 如果我们幸运地知道真实的总体均值 μ\mu,那么样本对真实均值的离散度计算为:

1ni=1n(Xiμ)2\frac{1}{n} \sum_{i=1}^{n} (X_i - \mu)^2

这个估计量的期望值恰好就等于 σ2\sigma^2,无需任何修正。

但在实际抽样调查中,真实的总体均值 μ\mu 是未知的!我们手中唯一的参考锚点,是用这组样本自己算出来的样本均值 Xˉ\bar{X}

Xˉ=1ni=1nXi\bar{X} = \frac{1}{n} \sum_{i=1}^{n} X_i

关键数学事实:二次函数的极值点

根据微积分极值定理,对于任意一组固定的数值 X1,X2,,XnX_1, X_2, \dots, X_n,使得二次距离和 (Xic)2\sum (X_i - c)^2 取得最小值的实数 cc恰恰就是样本本身的平均数 Xˉ\bar{X}

这意味着:对于任何不是 Xˉ\bar{X} 的常数(包括真实的总体均值 μ\mu),必定有:

i=1n(XiXˉ)2i=1n(Xiμ)2\sum_{i=1}^{n} (X_i - \bar{X})^2 \le \sum_{i=1}^{n} (X_i - \mu)^2

由于样本均值 Xˉ\bar{X} 是完全根据手头这几个样本计算出来的,它天然会向这几个样本点“靠拢”,导致每个样本点到 Xˉ\bar{X} 的距离,系统性地小于它们到真实总体均值 μ\mu 的距离。

如果你依然用 nn 作为分母,算出来的离散度必定会系统性低估总体的真实离散程度(偏小)。


2. 贝塞尔修正(Bessel’s Correction)的严格代数推导

我们来严格证明:直接除以 nn 的有偏样本方差 Sn2S_n^2,其期望值到底比真实方差 σ2\sigma^2 小了多少?

X1,,XnX_1, \dots, X_n 为独立同分布(i.i.d.)的样本,期望 E[Xi]=μE[X_i] = \mu,方差 Var(Xi)=σ2\text{Var}(X_i) = \sigma^2。 样本均值 Xˉ\bar{X} 的方差为:

Var(Xˉ)=E[(Xˉμ)2]=σ2n\text{Var}(\bar{X}) = E[(\bar{X} - \mu)^2] = \frac{\sigma^2}{n}

展开平方项:

(XiXˉ)2=((Xiμ)(Xˉμ))2=(Xiμ)22(Xiμ)(Xˉμ)+(Xˉμ)2\begin{aligned} (X_i - \bar{X})^2 &= \big((X_i - \mu) - (\bar{X} - \mu)\big)^2 \\ &= (X_i - \mu)^2 - 2(X_i - \mu)(\bar{X} - \mu) + (\bar{X} - \mu)^2 \end{aligned}

对全部 nn 个样本求和:

i=1n(XiXˉ)2=i=1n(Xiμ)22(Xˉμ)i=1n(Xiμ)+n(Xˉμ)2\sum_{i=1}^{n} (X_i - \bar{X})^2 = \sum_{i=1}^{n} (X_i - \mu)^2 - 2(\bar{X} - \mu) \sum_{i=1}^{n} (X_i - \mu) + n(\bar{X} - \mu)^2

由于 i=1n(Xiμ)=n(Xˉμ)\sum_{i=1}^{n} (X_i - \mu) = n(\bar{X} - \mu),中间项可以化简合并:

i=1n(XiXˉ)2=i=1n(Xiμ)2n(Xˉμ)2\sum_{i=1}^{n} (X_i - \bar{X})^2 = \sum_{i=1}^{n} (X_i - \mu)^2 - n(\bar{X} - \mu)^2

两边取数学期望:

E[i=1n(XiXˉ)2]=i=1nE[(Xiμ)2]nE[(Xˉμ)2]=nσ2n(σ2n)=nσ2σ2=(n1)σ2\begin{aligned} E\left[ \sum_{i=1}^{n} (X_i - \bar{X})^2 \right] &= \sum_{i=1}^{n} E[(X_i - \mu)^2] - n E[(\bar{X} - \mu)^2] \\ &= n\sigma^2 - n \cdot \left(\frac{\sigma^2}{n}\right) \\ &= n\sigma^2 - \sigma^2 = (n - 1)\sigma^2 \end{aligned}

结论极其清爽漂亮: 样本偏差平方和的期望值,恰好只有总体方差的 (n1)(n - 1) 倍,而不是 nn 倍!

因此,若要构造一个无偏估计量(Unbiased Estimator),使得其期望严格等于 σ2\sigma^2,分母必须除以 n1n - 1

s2=1n1i=1n(XiXˉ)2    E[s2]=σ2s^2 = \frac{1}{n - 1} \sum_{i=1}^{n} (X_i - \bar{X})^2 \implies E[s^2] = \sigma^2

这就是统计学中著名的贝塞尔修正


3. 工程大坑:灾难性消除(Catastrophic Cancellation)

在教科书中,为了简化笔算,通常会给出方差的展开变形公式:

s2=1n1(i=1nXi21n(i=1nXi)2)s^2 = \frac{1}{n - 1} \left( \sum_{i=1}^{n} X_i^2 - \frac{1}{n}\left(\sum_{i=1}^{n} X_i\right)^2 \right)

这个公式看起来非常诱人:只需要维护两个累加器(元素和、平方和),一趟遍历就能算完。

但在计算机浮点数体系下,这是极其危险的反模式代码!

浮点数灾难实测

假设我们输入三个极其接近的大数: [1000000001, 1000000002, 1000000003]

理论上,它们的方差极其简单:均值为 10000000021000000002,离差分别为 1,0,1-1, 0, 1,方差严格等于 1

但如果按展开公式用计算机的 64 位浮点数来算:

  1. Xi23×1018\sum X_i^2 \approx 3 \times 10^{18},这个数字已经逼近 2532^{53} 的有效数字上限,低位有效位被粗暴截断;
  2. (Xi)2/33×1018(\sum X_i)^2 / 3 \approx 3 \times 10^{18},同样被截断;
  3. 将两个被严重截断、几乎相等的巨大浮点数进行相减!

两个接近的极大浮点数相减,高位的有效数字全部抵消归零,剩下的完全是随机的浮点截断噪声。在实际运行中,计算结果可能会变成 01024,甚至算出一个极其荒谬的负数方差(开方求标准差时直接抛出 NaN 崩溃!)。

在数值分析中,这种现象被称为灾难性消除(Catastrophic Cancellation)


4. 工业级解法:单趟在线 Welford 算法

1962 年,统计学者 B. P. Welford 提出了一种数值稳定性极高、且仅需单趟流式遍历的在线均值与方差更新算法。

它维护三个状态量:已读样本数 kk、当前均值 MkM_k、离差平方和 SkS_k。 当新数据流 xx 到达时,通过差值递推更新:

kk+1δ=xMk1MkMk1+δkδ2=xMkSkSk+δ×δ2\begin{aligned} k &\leftarrow k + 1 \\ \delta &= x - M_{k-1} \\ M_k &\leftarrow M_{k-1} + \frac{\delta}{k} \\ \delta_2 &= x - M_k \\ S_k &\leftarrow S_k + \delta \times \delta_2 \end{aligned}

遍历结束后:

  • 样本方差为:s2=Snn1s^2 = \frac{S_n}{n - 1}
  • 总体方差为:σ2=Snn\sigma^2 = \frac{S_n}{n}

Welford 算法的核心优势

  1. 彻底消除大数截断误差:算法每一步运算的是新数据与当前均值的微小差值 δ=xM\delta = x - M,参与计算的数字规模极小,绝不会发生两个上百亿浮点数的高位碰撞消除;
  2. 零内存流式计算(One-pass streaming):不需要在内存中缓存全部历史数据数组,特别适合大数据流水线或实时统计监控。