qinghuan
← 数学语言与概率基础 / 全部笔记

单元 06 / 数学语言与概率基础

P0 · 必会主线L0 · 零基础

期望、方差与蒙特卡洛估计

用期望看平均水平,用方差看波动,再估计样本均值的误差,并在数据逐条到来时更新统计结果。

本篇目录 · 按需要跳转

读完这篇,你能做什么

能计算总体与样本方差,运行固定种子的蒙特卡洛估计,并实现常数额外空间的在线统计。

学习理由、准备要求与知识点

为什么学它

两次训练的平均损失或奖励相同,波动也可能很不同。一起看平均与波动,才更容易判断结果。

先读这些内容

知识点清单

  • 随机变量与取值分布
  • 离散期望
  • 总体方差
  • 样本方差与n-1
  • 均值标准误
  • 蒙特卡洛估计
  • 独立样本假设
  • Welford在线更新

运行前先确认Java 17;Python 3.14 CPU 教学实验,无外部数据、预训练权重、GPU 或多机训练。源代码基线与局限见源码模块。

01先弄懂它是什么

一次随机结果不一定能代表整体表现,所以我们常想知道平均会怎样。随机变量就是用一个数记录随机结果,例如 X 记录公平骰子的点数,取值为一到六。把各个数按出现概率加权平均,得到期望 E[X],这里是三点五。骰子不可能掷出三点五;期望描述的是整个分布的平均水平,不是对下一次结果的保证。

只看平均数还不够:两个策略平均奖励相同,一个可能每次都差不多,另一个可能忽高忽低。方差 Var(X)=E[(X-E[X])^2] 用偏离均值的平方来衡量这种波动,标准差是它的平方根,单位与原来的数一致。平方会去掉正负方向,也让极端值影响更大。对极端值出现得较频繁的重尾分布,还要先确认期望和方差是否存在。

样本统计量从有限观测估计总体性质。给定 n 个数,样本均值为 sum(x_i)/n;把这一批数据当完整总体时方差除以 n,估计未知总体方差时常用除以 n-1 的样本方差。在独立同分布且二阶矩存在等条件下,后一种对总体方差无偏,不能把这个结论直接推广到任意相关轨迹。

文中这几个词,先认一认

期望
把每个可能的数乘以它出现的概率,再加起来,得到分布的平均水平。
标准误
如果反复抽样并重复估计,估计结果会波动多大。它描述估计值的波动,不是原始数据本身的波动。
蒙特卡洛
用许多次随机抽样来近似计算平均结果或积分。例如反复模拟试验,再汇总结果。

还有陌生词?到术语小抄里看一个具体例子 ↗

02看看它怎么工作

平均值相加与波动相加,要分开看。只要相关期望存在,就有 E[X+Y]=E[X]+E[Y],不要求 X、Y 独立;但 Var(X+Y) 还包含两倍协方差,不能随手把两个方差直接相加。如果 n 个样本独立同分布,样本均值的方差是原方差除以 n,标准误是标准差除以 sqrt(n)。因此想让典型估计误差减半,通常需要把样本数增加到约四倍。

蒙特卡洛可以把积分转为期望。例如 U 在零到一之间均匀取样,E[U^2]=积分0到1的u^2=1/3。抽 n 次并平均平方值,就得到一个随机估计。每次运行可能不同,固定随机种子便于复现具体序列,却不会让估计自动无偏或代表所有种子。

用样本标准差除以 sqrt(n) 可以估计均值标准误,但依赖样本相关结构。相邻训练步骤的损失、同一任务的多次尝试或同一用户的数据往往相关,直接当作独立样本会低估不确定性。应按真正独立的单位抽样,必要时使用分组、时间块或其他适合依赖结构的方法。

直接用 mean(x^2)-mean(x)^2 计算方差,在数值上可能把两个很大的近似数相减,丢失真正很小的波动。例如数据都接近一万亿,但只相差几个单位,两个大平方很接近。Welford 更新维护样本数 n、当前均值 mean 和离差平方和 M2,避免显式形成两个巨大平方的差。

新值 x 到来时,令 delta=x-oldMean,newMean=oldMean+delta/newN,再令 newM2=oldM2+delta*(x-newMean)。第二个差使用更新后的均值,而不是再用旧 delta 平方;这个修正考虑了均值更新后,各数据相对均值的偏差也会变化。总体方差为 M2/n,样本方差为 M2/(n-1),空数据和单样本应按对应定义处理。

先跑通一个最小例子

Python stdlib 对照统计库,并用固定种子估计 E[U^2]。误差断言只检查这个受控实验,不能作为一般置信保证。

experiment.py · python
import math, random, statistics
data=[1.,2.,3.,4.]
assert statistics.mean(data)==2.5
assert statistics.pvariance(data)==1.25
assert math.isclose(statistics.variance(data),5/3)
assert statistics.pvariance([7.,7.,7.])==0.
rng=random.Random(2026)
draws=[rng.random()**2 for _ in range(20000)]
estimate=statistics.mean(draws)
se=statistics.stdev(draws)/math.sqrt(len(draws))  # 本实验抽样独立,均值标准误才使用此式。
assert abs(estimate-1/3)<0.02
assert se>0
same=random.Random(2026)
assert draws[:3]==[same.random()**2 for _ in range(3)]  # 固定种子提供序列可重复性。
print("PASS 7; estimate =",round(estimate,6),"estimated_se =",round(se,6))

核对运行结果打印 PASS 7,估计应接近 1/3,标准误为正;这不是训练收益或总体显著性的证明。

正在加载流程图…

统计量的计算公式与抽样假设共同决定结果能解释什么。
查看流程图源码(Mermaid)
flowchart LR
 A["抽样单位与分布假设"] --> B["输入一个观测值"]
 B --> C["更新计数和均值"]
 C --> D["更新离差平方和"]
 D --> E["输出方差与估计误差"]
 E --> F["说明独立性和有限样本边界"]

按顺序看,每一步做了什么

  1. 确定随机变量和独立抽样单位。
  2. 区分总体方差与样本估计。
  3. 用稳定更新维护均值和 M2。
  4. 按估计目标选择分母。
  5. 用多样本与误差说明解释蒙特卡洛结果。

03对照实现代码

CPython 3.14:statistics._ss 的离差平方和 (新标签页)↗

CPython v3.14.0;Lib/statistics.py · statistics._ss

以下为原创精简教学实现,不是原样库源码;只演示本文说明的机制,省略真实实现的优化、调度和完整兼容边界。

核心机制代码 · python
from fractions import Fraction
def exact_spread(values):
    data=[Fraction(x) for x in values]  # 原创有理数模型,保留给定有限数的精确比值。
    if not data:
        raise ValueError("empty")
    mean=sum(data)/len(data)
    squared=sum((x-mean)**2 for x in data)  # 精确算术中离差平方和不受浮点大数相消影响。
    return mean,squared

CPython v3.14.0 的 _ss 在未给中心值时,将数据转换成精确比值并按分母累计,形成精确的和与平方和,然后计算离差平方和与均值。源码特别说明某个表达式对普通浮点数数值性质较差,但在 Fraction 精确算术下成立;不能脱离表示方式只复制公式。

这个实现不是 Welford 浮点在线算法。它利用 Python 数值类型和有理数运算获得更精确的统计结果,代价与数值表示大小有关。Java 教学算法选择固定宽度在线状态,是另一种工程方案;两者解决相似统计问题,不能冒称具有相同内部机制或成本。

源码允许传入中心值 c,并走不同的平方偏离累计路径;如果 c 不是所需均值,结果含义会改变。调用者不能为了省一次计算随意传入近似中心,再把返回值无条件当成正确样本方差。公开 statistics 接口的错误处理和类型转换还位于更外层。

原创模型直接使用 Fraction 计算中心化平方差,只保留精确算术如何避免浮点相消的核心思想,未复制分母分组优化、混合数值类型和非有限值处理。读者可以用这个小模型核对简单输入,再对照 Welford 的近似误差和常数状态成本。

代码先调用谁,再调用谁

  1. statistics 方差接口取得数据
  2. _ss 转换精确数值比值
  3. 累计和与平方和或指定中心离差
  4. 返回均值和离差平方和
  5. 上层按总体或样本分母形成方差

04动手写一个例子

Welford 在线均值与方差

逐个接收有限 double,维护计数、均值与 M2;总体方差要求至少一个值,样本方差至少两个。输入或中间计算非法时不提交新状态。

输入 1
[1,2,3,4]
输出 1
mean=2.5,population=1.25,sample=5/3
输入 2
[7,7,7]
输出 2
variance=0

状态只保存三个数,不需要保留全部历史数据。每次输入先计算新的计数、均值和 M2 到局部变量,检查其有限性,再写回字段。这样失败的输入不会留下部分更新状态,便于继续诊断或按调用方策略中止。

Welford 的修正项使用旧均值计算 delta,再使用新均值计算第二个差,体现所有旧样本相对新中心移动的影响。若误用 delta*delta,计算得到的不是目标离差平方和;测试 [1,2,3,4] 可以直接暴露这一错误。

单样本的总体方差为零,但样本方差的 n-1 分母为零,不能假装两者都一样。高偏置、小波动数据检查数值稳定性,常量数据检查零方差,空输入和非有限输入检查接口边界。在线算法改善常见相消问题,但不保证任意极值下所有中间结果都可表示。

为什么这样写是对的每次成功更新后,n 是已接受值数量,mean 为其在线均值,M2 为围绕该均值的离差平方和近似。

时间 每个值 O(1),处理 n 个值 O(n)。额外空间 O(1) 状态。

更新只做固定次数的 double 和 long 运算;历史数据不存储,误差仍受输入尺度和顺序影响。

保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。

Main.java · 完整可运行程序 · Java
public class Main {
  static final class Stats {
    long n;double mean,m2;
    void add(double x){
      if(!Double.isFinite(x))throw new IllegalArgumentException("finite");
      long next=Math.addExact(n,1);
      double delta=x-mean,newMean=mean+delta/next;
      double newM2=m2+delta*(x-newMean); // 第二个差必须使用新均值。
      if(!Double.isFinite(newMean)||!Double.isFinite(newM2))throw new ArithmeticException("range");
      n=next;mean=newMean;m2=newM2; // 检查通过后再提交完整状态。
    }
    double population(){if(n==0)throw new IllegalStateException("empty");return m2/n;}
    double sample(){if(n<2)throw new IllegalStateException("need two");return m2/(n-1);}
  }
  static Stats of(double... x){Stats s=new Stats();for(double v:x)s.add(v);return s;}
  static void near(double a,double b){if(!Double.isFinite(a)||Math.abs(a-b)>1e-9)throw new AssertionError(a+" != "+b);}
  static void fails(Class<? extends Throwable> type,Runnable r){try{r.run();}catch(Throwable e){if(type.isInstance(e))return;throw new AssertionError(e);}throw new AssertionError();}
  public static void main(String[] args){
    Stats s=of(1,2,3,4);near(s.mean,2.5);near(s.population(),1.25);near(s.sample(),5.0/3);
    near(of(7,7,7).sample(),0);
    near(of(1e12+1,1e12+2,1e12+3,1e12+4).population(),1.25); // 大偏置、小波动。
    fails(IllegalStateException.class,()->new Stats().population());
    fails(IllegalStateException.class,()->of(1).sample());
    fails(IllegalArgumentException.class,()->s.add(Double.NaN));if(s.n!=4)throw new AssertionError("partial update");
    System.out.println("PASS 6");
  }
}

这些特殊情况也要试一试

  • 空数据均值方差没有本题定义。
  • 单样本不能计算样本方差。
  • 失败输入不改变状态。
  • 数值稳定改进不等于无限精度。
进阶选读 · 分块统计与相关样本

场景数据分布在多个文件或工作节点,或者观测具有时间相关性。

做法用包含均值差修正的合并公式组合块统计;相关样本另按组或时间块估计不确定性,不把块数与原始条数混淆。

复杂度独立块合并每块 O(1),统计含义仍取决于抽样结构。

好处与代价合并均值与方差便于扩展,但仅合并数值不能修复错误的独立性假设。

05项目里怎么用

实验报告至少同时说明样本单位、样本数、均值和波动指标。标准差描述观测分散,标准误描述均值估计的不确定性;把两者混用会让误差条意义不清。若同一任务重复运行多次,应区分任务间差异和同一任务内部随机性,避免以重复次数制造过大的有效样本量。

蒙特卡洛算得多准,取决于样本数、结果波动和抽样方法。对独立样本取均值,增加样本通常能减小估计方差;但特别罕见的事件,普通抽样可能试了很多次仍没见到。重要性采样等方法会改变抽样分布并配套调整权重,才可能提高效率;它们还要求覆盖需要估计的范围,不能随意只挑看起来更有利的样本。

数据处理过程中要保留非有限值策略。直接跳过 NaN 会改变统计对象,按零填充也可能系统性偏移均值;若采用过滤,应报告过滤数量与原因。小型 CPU 实验用于验证公式和实现,对真实训练轨迹需要另行检查相关性、漂移和异常点,不应将固定种子结果视为稳定收益。

容易踩的坑

  • 把期望当成下一次必然出现的结果。
  • 样本方差与总体方差分母混用。
  • 把相关观测当成独立样本计算标准误。
  • 直接用两个大平方相减而忽略数值相消。

几种做法,怎么选

表格有四列,窄屏可左右滑动查看代价和适用条件。

方案优势代价与限制适用条件
保留全部数据两遍计算便于复核和复杂统计存储随数据量增长离线小中型分析
Welford 在线状态单遍、常数额外空间浮点误差与顺序有关流式监控
精确有理数统计给定可表示数值下精确数值位数和运算成本可能增长小数据参考核对

06检验是否读懂了

先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。

先用自己的话解释

01期望三点五是否意味着骰子能掷出三点五?

展开参考答案与推导

不是。期望是分布的加权平均,不必属于随机变量的可能取值集合。它描述长期平均层面的性质,而非单次保证。

02标准差和标准误有什么不同?

展开参考答案与推导

标准差描述原始观测波动,标准误描述估计量在重复抽样中的波动。独立样本均值的标准误约为标准差除以样本数平方根。

03均值标准误总能除以 sqrt(n) 吗?

展开参考答案与推导

不能。该形式依赖独立同分布等条件;相关观测包含协方差项,直接使用原始条数可能低估不确定性。

换个情况,还会处理吗

01均值一样但一个策略极不稳定如何报告?

展开参考答案与推导

同时展示离散程度、分位数和相关失败模式,明确样本数与独立单位。单个均值无法表达尾部风险或跨任务差异。

02样本翻倍为何误差没有减半?

展开参考答案与推导

独立均值的典型误差按样本数平方根缩小,翻倍约缩小到原来的零点七零七。实际一次误差还会随机波动,不要求严格遵循该比例。

03固定种子是否足够证明方法稳定?

展开参考答案与推导

不够。固定种子便于重现同一序列,稳定性需要多个种子或合理重复设计,并区分数据变化与算法随机性。

写代码试一试

01计算总体方差。

输入 / 条件
[1,2,3,4]
输出 / 预期
1.25

提示 均值为2.5。

展开参考答案与推导

离差平方和为五,除以四得到一点二五;若使用样本方差,则分母为三,结果为五除以三。首先要明确这批数据是完整总体,还是用于估计更大总体的样本。

02选择 Welford 修正项。

输入 / 条件
旧均值 m,输入 x,新均值 m'
输出 / 预期
(x-m)*(x-m')

提示 两个中心不同。

展开参考答案与推导

先由旧均值计算 delta,再乘 x 与新均值的差。直接加 delta 的平方没有考虑中心移动,不能维护正确的离差平方和。

03估算增加样本的效果。

输入 / 条件
希望均值标准误约减半
输出 / 预期
约4倍独立样本

提示 平方根收敛。

展开参考答案与推导

标准误与 sqrt(n) 成反比,因此把 n 乘四才使分母乘二。若样本相关或方差变化,这个估算需要重新检查。

读完之后,独立完成

课后作业:自己做一遍

本篇共 10 道作业,先完成 8 道基础与综合任务,再按前置知识挑战进阶题。其中包含 1 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。

这次练什么

能计算总体与样本方差,运行固定种子的蒙特卡洛估计,并实现常数额外空间的在线统计。

本篇重点加练

标准误依赖抽样单位与独立性,增加观测行数不必然增加独立信息。

  • 均值标准误
  • 独立样本假设

重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。

先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。

基础必做

  1. 作业 01代码推演

    离散回报取 -2、1、5,概率为 0.25、0.5、0.25。计算期望、总体方差及回报超过期望的概率,并区分随机变量与统计量。

    提交内容
    手算分布表
    怎样算完成
    • 概率使用一致
    • 期望与样本观测不混淆

    练到的知识点随机变量与取值分布 · 离散期望 · 总体方差

  2. 作业 02原理问答

    对样本 [1,2,2,7] 分别定义总体描述方差、样本方差和均值标准误,注明各自何时可被用于推断。

    提交内容
    统计量表与假设说明
    怎样算完成
    • 分母与用途配套
    • 独立性条件明确

    练到的知识点样本方差与n-1 · 均值标准误 · 独立样本假设

  3. 作业 03原理问答

    同一批十位参与者各贡献十次观测。为“新参与者的均值”与“这十人的后续均值”分别定义估计对象和可用样本单位。

    提交内容
    两份统计目标与依赖图
    怎样算完成
    • 目标总体明确
    • 相关重复不被默认独立

    练到的知识点均值标准误 · 独立样本假设

综合应用

  1. 作业 04编程实践

    仅用 Python 标准库实现流式均值方差统计,按不同分块顺序处理同一份 1000 个数的固定种子数据,并与独立批量实现比较误差。

    提交内容
    CPU 脚本与核对记录
    怎样算完成
    • 在线状态定义完整
    • 误差容差有依据

    练到的知识点样本方差与n-1 · Welford在线更新

  2. 作业 05排错实验

    用蒙特卡洛估计区间 [0,1] 上 x² 的积分,比较 100、1000、10000 次采样,各重复 30 次;报告误差分布而非仅一次结果。

    提交内容
    实验脚本、结果表与图
    怎样算完成
    • 每轮随机源可追踪
    • 成本与误差同时记录

    练到的知识点均值标准误 · 蒙特卡洛估计 · 独立样本假设

  3. 作业 06面试场景

    同一测试题重复运行 100 次与独立生成 100 道题,哪一种支持对新题表现的推断?为两种数据分别设计可报告的统计摘要。

    提交内容
    实验单位说明与报告样式
    怎样算完成
    • 相关性来源明确
    • 推断范围不过度扩张

    练到的知识点样本方差与n-1 · 均值标准误 · 独立样本假设

  4. 作业 07编程实践

    用 Python 标准库生成 100 组实验,每组含 20 个独立随机值及其各复制四次的版本;比较两种数据上的均值和按行计算的标准误。

    提交内容
    CPU 实验与汇总表
    怎样算完成
    • 复制过程保持身份
    • 重复实验参数可重现

    练到的知识点均值标准误 · 独立样本假设

  5. 作业 08面试场景

    两种测量设备的单次噪声不同、单次成本也不同。自行给定独立噪声方差和预算,计算可采样次数并评审均值精度的比较依据。

    提交内容
    带假设的预算与精度表
    怎样算完成
    • 成本单位一致
    • 精度推断条件明确

    练到的知识点均值标准误

进阶挑战 · 掌握前置后选做

  1. 作业 09设计评审

    评审“复用同一随机样本比较两个估计器”的实验设计;构造 CPU 小实验比较共享随机数与独立随机数的差值波动。

    提交内容
    实验与设计审阅意见
    怎样算完成
    • 比较预算相同
    • 结论限定在所测分布

    练到的知识点蒙特卡洛估计 · 独立样本假设

思维拓展

先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。

  1. 作业 10思维拓展 · 跨域迁移

    将标准误问题迁移到网站点击率:同一用户连续点击是否可以当独立样本?设计两种用户生成机制,在纸面或小模拟中展示推断范围如何改变。

    提交内容
    生成机制与比较计划
    怎样算完成
    • 用户和点击层级区分
    • 机制差异能被观测或模拟

    练到的知识点均值标准误 · 独立样本假设

完成后,再检验一次

给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。

继续阅读

先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。

打开资料库,找下一份学习材料 ↗