别再死记硬背了!用Python模拟帮你彻底搞懂样本均值与方差的无偏性

张开发
2026/4/17 21:59:25 15 分钟阅读

分享文章

别再死记硬背了!用Python模拟帮你彻底搞懂样本均值与方差的无偏性
用Python模拟实验为什么样本方差的分母是n-1记得第一次学统计学时老师讲到样本方差公式分母用n-1而不是n教室里顿时一片哗然。我当时盯着黑板上的公式S²Σ(Xi-X̄)²/(n-1)怎么也想不明白——明明有n个数据点为什么要除以n-1直到后来用Python做了几次模拟实验才真正理解了其中的奥妙。今天我们就用Jupyter NotebookNumPy通过代码和可视化把这个问题彻底讲清楚。1. 准备实验环境我们先在Jupyter Notebook中搭建实验环境。这个实验只需要NumPy和Matplotlib两个基础库import numpy as np import matplotlib.pyplot as plt plt.style.use(seaborn) # 使用更美观的绘图样式 np.random.seed(42) # 固定随机种子保证结果可复现为了理解无偏性我们需要明确几个关键概念总体参数真实但通常未知的分布特征样本统计量从样本数据计算得到的估计值无偏估计统计量的期望等于总体参数重要提示在实验中我们会反复生成样本并计算统计量这种抽样-计算的重复过程是理解抽样分布的关键。2. 构建模拟总体让我们假设一个灯泡寿命的案例。假设某品牌灯泡寿命服从正态分布N(1000,50²)即平均寿命1000小时标准差50小时。虽然现实中我们不知道这些真实参数但模拟实验中我们可以设定上帝视角的总体true_mu 1000 # 总体均值 true_sigma 50 # 总体标准差 population np.random.normal(true_mu, true_sigma, 100000) # 生成大容量总体 plt.hist(population, bins50, densityTrue) plt.title(灯泡寿命总体分布) plt.xlabel(寿命(小时)) plt.ylabel(概率密度);这个分布将作为我们后续抽样实验的数据母体。虽然现实中无法获取全体数据但模拟中我们可以用它来验证各种估计方法的准确性。3. 样本均值的无偏性验证先从简单的样本均值开始。理论上样本均值X̄是总体均值μ的无偏估计即E(X̄)μ。让我们用实验验证这一点。定义抽样函数def sample_mean(size30): 从总体中抽取样本并计算均值 sample np.random.choice(population, sizesize, replaceTrue) return np.mean(sample)进行10000次抽样实验sample_means [sample_mean() for _ in range(10000)]分析结果print(f样本均值均值{np.mean(sample_means):.2f}) print(f总体均值{true_mu}) print(f样本均值标准差{np.std(sample_means):.2f}) print(f理论标准误{true_sigma/np.sqrt(30):.2f})你会看到样本均值的平均值非常接近真实均值1000样本均值的波动标准误符合σ/√n的理论预期这个实验直观展示了为什么说样本均值是总体均值的无偏估计。4. 样本方差的无偏性探究现在来到核心问题为什么样本方差的分母是n-1我们设计对比实验定义两种方差计算方式def variance_biased(sample): 有偏方差估计分母n return np.sum((sample - np.mean(sample))**2) / len(sample) def variance_unbiased(sample): 无偏方差估计分母n-1 return np.sum((sample - np.mean(sample))**2) / (len(sample)-1)进行10000次抽样实验samples [np.random.choice(population, 30) for _ in range(10000)] biased_vars [variance_biased(s) for s in samples] unbiased_vars [variance_unbiased(s) for s in samples]结果分析print(f有偏方差均值{np.mean(biased_vars):.2f}) print(f无偏方差均值{np.mean(unbiased_vars):.2f}) print(f总体真实方差{true_sigma**2})你会发现有偏估计的系统性低估了约3.3%正好是(30-1)/30的比例无偏估计的均值几乎等于真实方差25005. 数学原理的可视化解释为什么会出现这种差异关键在于样本均值X̄本身也是从数据估计得来的它吸收了一部分变异自由度。用二维数据可以更直观理解。假设我们只有两个数据点fig, ax plt.subplots(figsize(8,8)) ax.set_xlim(0,6); ax.set_ylim(0,6) ax.set_aspect(equal) # 绘制均值线 ax.axline((3,0), (3,6), cred, linestyle--, label真实均值μ) ax.axline((0,3), (6,3), cred, linestyle--) # 模拟多个样本 for _ in range(20): x1, x2 np.random.normal(3, 1, 2) sample_mean (x1 x2)/2 ax.scatter(x1, x2) ax.axline((x1, x1), (x2, x2), cblue, alpha0.3) ax.axline((sample_mean,0), (sample_mean,6), cgreen, alpha0.3) ax.axline((0,sample_mean), (6,sample_mean), cgreen, alpha0.3)这个图形显示数据点总是沿着yx这条线对称分布样本均值完全由数据点位置决定实际上只有一个点的位置可以自由变化自由度n-16. 自由度损失的数学证明从代数角度看当使用样本均值X̄计算离差平方和时n个离差(Xi-X̄)之间存在一个线性约束Σ(Xi - X̄) 0这就导致实际上只有n-1个离差可以自由变化。严谨的数学期望推导如下E[Σ(Xi-X̄)²] E[Σ(Xi-μ μ-X̄)²] E[Σ(Xi-μ)²] nE[(X̄-μ)²] - 2E[Σ(Xi-μ)(X̄-μ)] nσ² n(σ²/n) - 2σ² (n-1)σ²因此要使E[S²] σ²必须除以n-1而非n。7. 不同样本量的影响实验为了更全面理解我们考察不同样本量下的偏差情况sample_sizes range(5, 101, 5) ratio_biased [] ratio_unbiased [] for n in sample_sizes: samples [np.random.choice(population, n) for _ in range(5000)] biased np.mean([variance_biased(s) for s in samples]) unbiased np.mean([variance_unbiased(s) for s in samples]) ratio_biased.append(biased / true_sigma**2) ratio_unbiased.append(unbiased / true_sigma**2) plt.plot(sample_sizes, ratio_biased, label有偏估计) plt.plot(sample_sizes, ratio_unbiased, label无偏估计) plt.axhline(1, colorred, linestyle--) plt.xlabel(样本量) plt.ylabel(估计方差/真实方差) plt.legend();这个实验清晰地展示有偏估计的系统偏差随样本量增大而减小当n30时有偏估计约为真实值的97%当n100时差异缩小到99%无偏估计在各种样本量下都保持准确8. 实际应用建议在数据分析实践中关于方差估计需要注意软件默认行为Python的np.var默认计算有偏估计使用ddof1参数获得无偏估计Pandas的.var()默认就是无偏估计sample np.random.choice(population, 30) print(fNumPy有偏方差{np.var(sample):.2f}) print(fNumPy无偏方差{np.var(sample, ddof1):.2f}) print(fPandas无偏方差{pd.Series(sample).var():.2f})机器学习中的特殊处理在极大样本下(n1000)两种方法差异可忽略但在小样本特征工程中建议使用无偏估计某些集成算法内部会做自动调整其他统计量的自由度校正协方差矩阵估计同样需要自由度调整多元统计量如马氏距离也有类似修正时间序列分析中的自相关函数估计9. 扩展实验其他分布的表现为了验证这个结论的普适性我们可以测试其他分布类型distributions { 均匀分布: np.random.uniform(0, 100, 100000), 指数分布: np.random.exponential(10, 100000), 泊松分布: np.random.poisson(5, 100000) } results [] for name, dist in distributions.items(): true_var np.var(dist) samples [np.random.choice(dist, 20) for _ in range(5000)] biased np.mean([variance_biased(s) for s in samples]) unbiased np.mean([variance_unbiased(s) for s in samples]) results.append((name, true_var, biased, unbiased)) pd.DataFrame(results, columns[分布, 真实方差, 有偏估计, 无偏估计])实验结果表明无论原始分布形态如何n-1修正都能保证方差估计的无偏性。这证实了该方法的分布无关特性。

更多文章