跳转至

P2-5.4 用小数据确认概率与统计

Section ID: P2-5.4 Version: v2026.07.20

在 P2-5.1 中,我们把概率(probability)看作处理不确定性的数字语言。在 P2-5.2 中,我们把分布(distribution)、均值(mean)、方差(variance)看作读取一组数据形状的工具。在 P2-5.3 中,我们把样本(sample)、估计(estimation)、误差(error)看作“用部分去谈整体”。

这里会把一小列数据放在桌上,按顺序确认均值、偏差、方差、样本均值变化。

这里不是去背大量统计公式,而是去确认数字和代码怎样把前几节的概念显示出来。

这里会把 小数据均值(mean)中位数(median)方差(variance)样本均值(sample mean) 连同代码一起再整理一次。如果说 5.2 和 5.3 讲的是读取概念,那么这一节讲的是这些概念在实际数字和输出里怎样出现。

这里并不想广泛学习统计库的用法,而是把重点放在:用小数据和代码重新确认概率与统计的基本概念。如果先把均值、方差、样本均值变化用眼睛看一遍,后面再看数据集统计或评估数字时,概念和输出就不会各走各的路。

在小数据上区分原始数据、中心、扩散与样本估计的流程

核心判断标准:用小数据确认概率与统计

  • 能从一组小数据里计算 均值(mean)
  • 能区分 均值(mean)中位数(median)
  • 能检查每个值离均值有多远。
  • 能把 方差(variance) 解释为“均值周围的扩散”。
  • 能说明总体方差(population variance)与样本方差(sample variance)可能采用不同的计算设置。
  • 能通过代码确认 样本均值(sample mean) 会随着样本变化而变化。
  • 能把代码输出和概念说明连起来读。

三个判断标准

标准 为什么重要 这里需要的理解层次
代码会通过数字和输出把概念显示出来 只有看到均值、方差、样本均值在实际计算里怎样出现,概念和输出才会真正连起来。 理解统计概念会在小数字数据上表现成具体的计算与输出。
均值和中位数要一起看 它们都在谈中心,但碰到极端值时反应不同。 理解均值和中位数都和中心有关,但性格不同。
方差会补上扩散信息 只看中心,无法把数据的性格讲完整。 理解方差是在告诉我们数值围绕均值分散了多少。

执行环境

本节代码使用 NumPy。

执行环境请按 P2-3.5 的 先区分执行环境 来确认。这里不再重复说明 Python 的安装方法,而是把重点放在通过小代码确认统计概念。

如果使用 Google Colab,可以先在代码单元里像下面这样准备 NumPy。

问题场景:在 Colab 中运行本节的统计示例之前,先准备 NumPy。 输入(input):笔记本代码单元中的 %pip install numpy 命令。 期待输出(output):NumPy 被安装到当前 Colab 内核中。 要确认的概念:在运行统计示例之前,包准备步骤和计算步骤是分开的。

# 这条命令是在 Colab/Jupyter 代码单元里安装 NumPy。
%pip install numpy

如果使用本地 PC,可以在自己的终端里使用下面的命令。

python -m pip install numpy

本节完整示例代码也可以在下面这个文件中查看。

如果从项目根目录运行,可以使用下面的命令。

python docs/assets/part-02/chapter-05/p2_5_4_small_statistics.py

先创建一组小数据

先用一组小数据列表开始计算。

问题场景:先准备一组用来确认均值和方差的小型数字数据。 输入(input):包含 8 个值的 NumPy 数组 data。 期待输出(output):打印出整组数据,以及元素个数 8。 要确认的概念:统计计算总要先确认自己是基于哪一组数据来做的。

# 这个例子导入 NumPy,为小数据的平均值、中位数和方差计算做准备。
import numpy as np

# data 是用来确认平均值、中位数和方差的小型分数数据。
data = np.array([42, 55, 48, 63, 52, 50, 47, 70])

print(data)

# size 表示这个数据里有多少个值。
print(data.size)

输出可以像下面这样阅读。

[42 55 48 63 52 50 47 70]
8

这里的 data 不是现实的全部。它只是我们观察到的一小组数据。用前一节的说法,它可以被读成一个 样本(sample)

在这一步,最重要的问题是:这些数字记录的是什么、它们是通过什么方式收集来的、以及它们能不能代表整体。

代码会帮你计算,但数据究竟意味着什么,仍然要由人来决定。

均值把中心总结成一个数字

均值(mean) 会把数据的中心总结成一个数字。

问题场景:确认准备好的数据里,均值实际会算成什么数字。 输入(input):上面创建的数组 data。 期待输出(output):打印均值 53.375。 要确认的概念:均值是把很多值压缩成一个代表数字的计算。

1
2
3
# mean_value 是把 data 中所有值概括成一个中心值的平均值。
mean_value = np.mean(data)
print(mean_value)

输出是 53.375

这个数字代替的是下面这个计算。

\[ \frac{42 + 55 + 48 + 63 + 52 + 50 + 47 + 70}{8} = 53.375 \]

均值很方便,但只看一个均值并不能把数据的全部形状都讲出来。均值告诉我们中心,但数值分散得有多开,还得另外看。

而且,均值会被一个特别大或特别小的值拉动。这时可以一起看的一个代表值就是 中位数(median)

中位数是在排序后位于中间的值

中位数(median) 是把数值按大小排序之后,落在中间位置的那个值。

下面这组数据里,有一个值特别大。

问题场景:比较存在极端值时,均值和中位数会怎样不同地反应。 输入(input):包含大值 100 的数组 skewed_data。 期待输出(output):打印均值 30.0 和中位数 13.0。 要确认的概念:均值会被极端值拉动,而中位数相对更不容易被拉动。

1
2
3
4
5
# skewed_data 包含极端值 100,用来比较平均值和中位数的反应差异。
skewed_data = np.array([10, 12, 13, 15, 100])

print(np.mean(skewed_data))
print(np.median(skewed_data))

输出是 30.013.0

均值因为受到 100 的强烈影响而变成 30.0。但中位数是排好序后正中间的 13.0

均值要把所有值都加起来再计算中心,所以容易被一个特别大或特别小的值拉动。相比之下,中位数只看排序后的中间位置,因此对 极端值(outlier) 相对不那么敏感。

在现实数据里,经常会出现一边拖得很长的分布。像用户使用时长、等待时间、响应延迟、收入这类数据里,有些值可能特别大。如果只看均值,就很容易误读数据“通常是什么样子”。

这里不会深入讨论中位数。像中位数、标准差、置信区间这类均值之外的摘要值,会在 P2-5.5 的补充学习里再整理一次。不过,当你看均值时,也要同时记住:均值是否真的把中心说明清楚、均值是否被极端值拉向一边、以及如果把中位数一起看,解释是否会改变。

既然均值和中位数是在看中心,那么下一步就要看:数值在这个中心周围散开了多少。这就是方差要做的事。

方差看的是离均值有多远

方差(variance) 是用来观察数值在均值周围扩散了多少的数字。

先从每个值里减去均值。

问题场景:直接确认每个数据离均值有多远。 输入(input):数组 data 及其均值。 期待输出(output):打印出偏差数组,并保留到小数点后三位。 要确认的概念:在看方差之前,可以先把每个值表示成“离均值多远”的偏差。

1
2
3
# centered 表示每个值距离平均值有多远。
centered = data - np.mean(data)
print(np.round(centered, 3))

输出可以像下面这样阅读。

[-11.375   1.625  -5.375   9.625  -1.375  -3.375  -6.375  16.625]

这些值告诉我们,每个数据离均值有多远。比如 42 比均值低 11.375,70 比均值高 16.625,55 比均值高 1.625。

接下来把这些距离平方。

问题场景:把离均值的差平方,好让扩散程度能在没有负号干扰的情况下比较。 输入(input):上面算出的偏差数组 centered。 期待输出(output):打印平方偏差数组。 要确认的概念:方差的流程不是把偏差直接相加,而是先平方再求平均。

1
2
3
# squared_deviations 会把偏差平方,让负向和正向差距都作为离散程度来读。
squared_deviations = centered ** 2
print(np.round(squared_deviations, 3))

输出可以像下面这样阅读。

[129.391   2.641  28.891  92.641   1.891  11.391  40.641 276.391]

方差可以看作这些平方距离再取平均之后得到的值。

问题场景:把平方偏差压缩成一个数字,并计算方差。 输入(input):数组 data。 期待输出(output):打印方差值 72.984375。 要确认的概念:方差是把均值周围的扩散总结成一个数字的值。

# np.var(data) 会把 data 的离散程度概括成一个方差值。
print(np.var(data))

输出是 72.984375

这里重要的不是公式本身,而是解释方式。均值看中心,离均值的差看每个值离中心多远,而方差则把这些距离整体总结起来。

总体方差和样本方差可能使用不同设置

NumPy 的 np.var(data) 默认会把整组数据当作一个总体来计算方差。这时,它是用 \(N\) 这个值的个数去做除法。

但在统计里,当我们用样本去估计总体方差时,经常会使用除以 \(N - 1\)样本方差(sample variance)。在 NumPy 里,可以通过指定 ddof=1 来检查。

问题场景:比较同一组数据在总体方差和样本方差设置下,为什么会得到不同结果。 输入(input):数组 data 以及两种 ddof 设置。 期待输出(output):依次打印总体方差和样本方差。 要确认的概念:不是代码错了,而是计算设置不同,所以值会不同。

1
2
3
# ddof=1 是计算样本方差时使用的设置。
print(np.var(data))
print(np.var(data, ddof=1))

输出是 72.98437583.41071428571429

两个值会不同。这并不表示代码错了,而是说明:我们把这组数据看成整体,还是看成样本,会影响计算设置。

计算 代码 工作性解释
总体方差 np.var(data) 把这组数据当作整体来计算扩散。
样本方差 np.var(data, ddof=1) 把这组数据当作样本,用来估计总体的扩散。

这里与其死记 ddof,不如先问清楚:你手里的数据到底是整体,还是为了估计整体而拿到的样本。

样本一变,均值也可能跟着变

这次我们先造一组更像“接近整体”的小数值集合,再从里面挑几份不同的样本出来。

问题场景:直接确认换不同样本时,样本均值会怎样变化。 输入(input):接近总体的值集合 population_like 与三个样本数组 samples。 期待输出(output):依次打印整体均值和各个样本均值。 要确认的概念:样本均值会随着抽样方式不同而变化,这就是抽样波动的基本感觉。

# population_like 是被当作接近整体的参考数据。
population_like = np.array([42, 45, 47, 48, 50, 52, 55, 58, 61, 63, 66, 70])

# samples 是用来模拟只观察到 population_like 一部分的样本集合。
samples = np.array([
    [42, 47, 50, 55],
    [48, 52, 63, 70],
    [45, 55, 58, 66],
])

print(np.mean(population_like))

# 依次确认每个样本的平均值是否会变化。
for sample in samples:
    print(sample, np.mean(sample))

输出可以像下面这样阅读。

1
2
3
4
54.75
[42 47 50 55] 48.5
[48 52 63 70] 58.25
[45 55 58 66] 56.0

这组接近整体的值,其均值是 54.75。但样本怎么抽,样本均值就可能变成 48.558.2556.0

这就是 P2-5.3 里提到的 抽样波动(sampling variation) 的一个小例子。整体均值只有一个,但样本均值会随着样本变化而变化,所以样本均值是对整体均值的估计值。

代码输出是材料,不是判断

代码可以很快算出均值和方差。但怎样解释这些数字,是另一件事。

例如,看到均值是 53.375,如果马上下结论说“这个服务全部用户的平均值就是 53.375”“这组数据完美代表整体”“方差大,所以数据不好”,就会很危险。

更谨慎的说法会更接近:“在这组数据里,均值是 53.375”“这些值在均值周围有一定程度的扩散”“这组数据能否代表整体,还要结合收集方式和样本构成一起看”。

AI 数据也需要同样的态度。训练数据的均值,是在训练数据集内部算出来的摘要值;测试数据的分数,是从测试样本上得到的评估值;而现实表现,则要通过另外的样本、部署后的观察、持续评估来确认。

用案例来看

案例 1. 只用一小列分数,也能把均值和方差的感觉找回来吗

假设学习者在阅读统计公式时似乎能理解,但一看到实际数字,感觉就又变模糊了。这时,与其从大数据集开始,不如先拿出一小列分数,亲手去算均值、中位数、方差,反而更容易把概念差异看清楚。

例如,把八个分数摆出来之后,先算均值,中心会被压缩成一个数字。但如果立刻再把中位数、离均值的差、平方偏差、方差一起看,就会发现 中心极端值影响扩散 其实是在回答不同的问题。

再进一步,如果换几份不同样本重新算均值,就能用眼睛确认:即使这些值都来自某个类似同一总体的集合,样本均值还是会轻微摇动。这就是前一节所说 抽样波动(sampling variation) 的最小实验版。

这个案例说明了为什么需要小数据练习。统计概念如果只读公式,往往显得抽象;但如果亲手改几个数字,再看输出怎样变化,它就会具体得多。

检查清单

  • 能把一组小数据做成 NumPy array
  • 能用 np.mean 计算 均值(mean)
  • 能用 np.median 计算 中位数(median)
  • 能说明均值会被 极端值(outlier) 拉动。
  • 能检查每个值离均值有多远。
  • 能用 np.var 计算 方差(variance)
  • 能说明 ddof=1 可以用于样本方差计算。
  • 能说明 样本均值(sample mean) 会随着样本变化而变化。
  • 能把代码输出和数据收集方式、样本代表性、解释问题区分开来看。
  • 能说明统计代码输出是解释的起点,而不是判断的终点吗?

来源与参考资料

  • NumPy Developers, numpy.array, NumPy Reference, 确认日期: 2026-07-20。用于确认把小型数字列表创建成 NumPy 数组的示例。
  • NumPy Developers, numpy.ndarray.size, NumPy Reference, 确认日期: 2026-07-20。用于确认通过 data.size 读取数组元素个数的示例。
  • NumPy Developers, numpy.mean, NumPy Reference, 确认日期: 2026-07-20。用于确认算术均值和数组均值计算。
  • NumPy Developers, numpy.median, NumPy Reference, 确认日期: 2026-07-20。用于确认中位数是排序副本的中间值,或在偶数个值时取中间两个值的平均。
  • NumPy Developers, numpy.var, NumPy Reference, 确认日期: 2026-07-20。用于确认方差、ddof、总体方差与样本方差计算设置的差异。
  • Barbara Illowsky, Susan Dean, Introductory Statistics, 1.2 Data, Sampling, and Variation in Data and Sampling, OpenStax, 确认日期: 2026-07-20。用于确认样本应代表总体,以及抽样方式可能带来波动这一统计背景。