本文介绍随机变量样本均值方差和整体均值方差的关系,同时还介绍样本和均值的方差和总体方差的关系
样本方差与总体方差的关系
- 其他证明方式:
- 上式中,如果总体方差未知 ,想要用样本方差来作为总体方差的无偏估计 ,则样本方差的定义是应该是
$$ S^2 = \frac{1}{n-1}\sum_i^n(X_i-\bar{X})^2$$- 注:分母必须是 \(n-1\) 时,样本方差才是总体方差的无偏估计
- 上式中,如果总体方差未知 ,想要用样本方差来作为总体方差的无偏估计 ,则样本方差的定义是应该是
样本方差为什么要除以n-1?
- 样本方差的定义:
$$
\sigma^2 \approx S^2 = \frac{1}{n-1}\sum_i^n(X_i-\bar{X})^2
$$ - 为什么样本方差是乘以 \(\frac{1}{n-1}\) 而不是 \(\frac{1}{n}\) ?
- 因为这样使用 \(\frac{1}{n}\) 会低估总体方差,此时样本方差不是总体方差的无偏估计
- 样本方差低估了总体方差的原因是因为从总体里面抽出来的数据会更倾向于集中,极端情况下,一个样本对应的方差为0
- 换个视角想,是因为我们不知道总体的均值,所以计算方差时使用的均值也是从样本中求平均得到的,这使得我们基于该均值得到的方差不够离散(因为使用了样本均值,所以自由度需要减一),也就是低估了总体方差
- 怎么理解自由度?
- 采样一个样本以后无法计算方差,此时方差为0,因为此时均值就等于样本本身,此时自由度为0
- 采样两个样本以后得到的方差只根第二个样本到第一个样本的距离有关(样本均值与这两个样本强相关),此时自由度为1
- 当采样的样本数非常多(假设为n)时,实际上单个样本与均值的关系很小了,此时自由度为n-1
- 怎么理解自由度?
- 当已知总体均值 \(\mu\) 时(个人理解:这里的 \(\mu\) 可以是其他采样方式下获得的近似均值,只要不跟当前用于计算方差的样本相关即可),样本方差可以使用:
$$
\sigma^2 \approx S^2 = \frac{1}{n-1}\sum_i^n(X_i-\mu)^2
$$ - 样本方差经过 \(\frac{1}{n-1}\) 修正以后可以用来估计总体方差(修正以后是总体方差的无偏估计)
- 这个修正叫做贝塞尔修正
单样本均值和多样本均值的关系
问题定义
- 考虑以下采样方式
- 集合X :每次采样 B个样本 得到的样本集合
- 集合Y :每次采样 1个样本 得到的样本集合
- 问:多次采样时,集合X和B的均值和方差关系是什么?
- 即:如果我们重复多次进行这样的采样(每次采B个或1个),那么:这两种采样方式得到的样本均值的期望(即平均值的平均值)和样本均值的方差(即平均值的波动程度)之间有什么关系?
假设与符号定义
- 假设我们从一个总体中采样,总体的均值为 \(\mu\),方差为 \(\sigma^2\)
- 集合X :
- 每次采样 B个样本 :\(X_1, X_2, \dots, X_B\)
- 计算这B个样本的均值:\(\bar{X}_A = \frac{1}{B}\sum_{i=1}^B X_i\)
- 集合Y :
- 每次采样 1个样本 :\(Y_1\)
- 其“均值”就是它自己:\(\bar{X}_B = Y_1\)
- 我们重复多次这样的采样过程,得到一系列的 \(\bar{X}_A\) 和 \(\bar{X}_B\)
均值关系
- 集合X 的样本均值的期望:
$$
E[\bar{X}_A] = E\left[\frac{1}{B}\sum_{i=1}^B X_i\right] = \frac{1}{B} \sum_{i=1}^B E[X_i] = \frac{1}{B} \cdot B \mu = \mu
$$ - 集合Y 的样本均值的期望:
$$
E[\bar{X}_B] = E[Y_1] = \mu
$$ - 结论:两种采样方式得到的样本均值的期望是相同的 ,都等于总体均值 \(\mu\)
方差关系
- 集合X 的样本均值的方差:
$$
\text{Var}(\bar{X}_A) = \text{Var}\left(\frac{1}{B}\sum_{i=1}^B X_i\right) = \frac{1}{B^2} \sum_{i=1}^B \text{Var}(X_i) = \frac{1}{B^2} \cdot B \sigma^2 = \frac{\sigma^2}{B}
$$ - 集合Y 的样本均值的方差:
$$
\text{Var}(\bar{X}_B) = \text{Var}(Y_1) = \sigma^2
$$ - 结论:集合X 的样本均值的方差是 \(\frac{\sigma^2}{B}\),集合Y 的样本均值的方差是 \(\sigma^2\)
- 也就是说,集合X 的样本均值的方差更小,是集合Y 的 \(\frac{1}{B}\)
- 直观理解
- 均值方面:无论你是采1个还是采B个,平均来看,它们的中心位置(期望)都是一样的,都是总体的均值
- 方差方面:采B个样本求平均,相当于把单个样本的“噪声”给“平均掉”了,因此波动更小,方差更小;而采1个样本,没有“平均”的过程,波动就更大,方差也就更大
附录:Python 中计算标准差/方差的默认实现
- 在进行数据归一化(如 Z-score 标准化)时,计算标准差的分母是 \(n\)(总体标准差)还是 \(n-1\)(样本标准差,即无偏估计),在不同的 Python 科学计算库中默认行为是不同的
- 各 Python 库的默认行为总结:
- 1)NumPy (
np.std) :默认分母为 \(n\)(即ddof=0)- 注:这里控制分母的参数通常称为
ddof(Delta Degrees of Freedom,自由度偏差),分母的计算公式为 \(N - ddof\)
- 注:这里控制分母的参数通常称为
- 2)Pandas (
pd.Series.std/pd.DataFrame.std) :默认分母为 \(n-1\)(即ddof=1) - 3)PyTorch (
torch.std) :默认分母为 \(n-1\)(即unbiased=True或correction=1)- 注:修改
unbiased=False即可得到分母为 \(n\) 的结果
- 注:修改
- 注:各个库的默认行为不同可能会导致一些意想不到的问题
- 1)NumPy (
- 在机器学习中进行 Z-score 归一化(\(\frac{x - \mu}{\sigma}\))时,通常数据量 \(n\) 都比较大,此时 \(n\) 和 \(n-1\) 的差别微乎其微
- 但为了保证训练集和测试集处理逻辑的绝对一致性,建议在代码中显式指定参数(例如统一写死
ddof=0或unbiased=False),避免因为在不同库之间切换数据格式(如从 Pandas 转换到 PyTorch Tensor)而引入隐蔽的计算差异
- 但为了保证训练集和测试集处理逻辑的绝对一致性,建议在代码中显式指定参数(例如统一写死
测试代码
- 以下是包含 NumPy、Pandas 和 PyTorch 计算 \(n\) 和 \(n-1\) 标准差的完整测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64import numpy as np
import pandas as pd
import torch
def test_std_behaviors():
# 准备相同的测试数据
data_list = [1.0, 2.0, 3.0, 4.0, 5.0]
print("-" * 40)
print("NumPy 标准差测试")
print("-" * 40)
arr = np.array(data_list)
# NumPy 默认 ddof=0,分母为 n
np_std_n = np.std(arr)
# NumPy 设置 ddof=1,分母为 n-1
np_std_n_minus_1 = np.std(arr, ddof=1)
print(f"NumPy 默认分母 (n) : {np_std_n:.4f}")
print(f"NumPy 指定分母 (n-1) : {np_std_n_minus_1:.4f} (使用 ddof=1)")
print("\n" + "-" * 40)
print("Pandas 标准差测试")
print("-" * 40)
series = pd.Series(data_list)
# Pandas 默认 ddof=1,分母为 n-1
pd_std_n_minus_1 = series.std()
# Pandas 设置 ddof=0,分母为 n
pd_std_n = series.std(ddof=0)
print(f"Pandas 默认分母 (n-1): {pd_std_n_minus_1:.4f}")
print(f"Pandas 指定分母 (n) : {pd_std_n:.4f} (使用 ddof=0)")
print("\n" + "-" * 40)
print("PyTorch 标准差测试")
print("-" * 40)
tensor = torch.tensor(data_list)
# PyTorch 默认无偏估计 (unbiased=True),分母为 n-1
# 注:在较新版本的 PyTorch 中,也可以使用 correction=1
pt_std_n_minus_1 = torch.std(tensor)
# PyTorch 设置有偏估计 (unbiased=False),分母为 n
# 注:在较新版本的 PyTorch 中,也可以使用 correction=0
pt_std_n = torch.std(tensor, unbiased=False)
print(f"PyTorch 默认分母 (n-1): {pt_std_n_minus_1:.4f}")
print(f"PyTorch 指定分母 (n) : {pt_std_n:.4f} (使用 unbiased=False)")
if __name__ == "__main__":
test_std_behaviors()
# ----------------------------------------
# NumPy 标准差测试
# ----------------------------------------
# NumPy 默认分母 (n) : 1.4142
# NumPy 指定分母 (n-1) : 1.5811 (使用 ddof=1)
#
# ----------------------------------------
# Pandas 标准差测试
# ----------------------------------------
# Pandas 默认分母 (n-1): 1.5811
# Pandas 指定分母 (n) : 1.4142 (使用 ddof=0)
#
# ----------------------------------------
# PyTorch 标准差测试
# ----------------------------------------
# PyTorch 默认分母 (n-1): 1.5811
# PyTorch 指定分母 (n) : 1.4142 (使用 unbiased=False)