Files
maths-cs-ai-compendium-zh/chapter 04: statistics/02. measures.md
T
flykhan 2536c937e3 feat: 完整中文翻译 maths-cs-ai-compendium(数学·计算机科学·AI 知识大全)
翻译自英文原版 maths-cs-ai-compendium,共 20 章全部完成。

第01章 向量 | 第02章 矩阵 | 第03章 微积分
第04章 统计学 | 第05章 概率论 | 第06章 机器学习
第07章 计算语言学 | 第08章 计算机视觉 | 第09章 音频与语音
第10章 多模态学习 | 第11章 自主系统 | 第12章 图神经网络
第13章 计算与操作系统 | 第14章 数据结构与算法
第15章 生产级软件工程 | 第16章 SIMD与GPU编程
第17章 AI推理 | 第18章 ML系统设计
第19章 应用人工智能 | 第20章 前沿人工智能

翻译说明:
- 所有数学公式 $...$ / $$...$$、代码块、图片引用完整保留
- mkdocs.yml 配置中文导航 + language: zh
- README.md 已翻译为中文(兼 docs/index.md)
- docs/ 目录包含指向各章文件的 symlink
- 约 29,000 行中文内容,排除 .cache/ 构建缓存
2026-05-03 10:23:20 +08:00

179 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 统计量
*统计量用单个数值概括数据,捕捉其离散程度、位置、形状和关联。本节涵盖方差、标准差、四分位数、偏度、峰度、协方差、相关和 z 分数——这是探索性数据分析和机器学习特征工程的基础工具集。*
- 在上一节中,我们介绍了矩作为一组概括性统计量家族。在此,我们展开讨论从矩中衍生出的实用工具:度量离散程度、位置、形状和关联的统计量。
- **离散程度**回答了这样一个问题:数据的分布有多分散?两个班级的平均考试成绩可能相同,但其分散程度却可能大相径庭。
![均值相同但离散程度不同的两个分布](../images/variance_spread.svg)
- 窄(蓝色)分布的方差较小:大部分数值紧密聚集在均值周围。宽(红色)分布的方差较大:数值散布得更远。
- **方差**是距均值距离的平方的平均值。取平方是为了避免正负偏差相互抵消。
$$\sigma^2 = \frac{1}{N} \sum_{i=1}^{N} (x_i - \mu)^2$$
- 当处理样本(而非整个总体)时,我们用 $N - 1$ 而不是 $N$ 来除。这种修正(称为**贝塞尔校正**)是因为样本往往会低估真实的变异性:
$$s^2 = \frac{1}{N-1} \sum_{i=1}^{N} (x_i - \bar{x})^2$$
- **标准差**是方差的平方根:$\sigma = \sqrt{\sigma^2}$。它将度量单位恢复为原始单位。如果数据的单位是厘米,方差的单位是 cm$^2$,而标准差的单位又回到了 cm。
- **平均绝对偏差(MAD)**是一个更简单的替代方案。它不取平方,而是取每个偏差的绝对值:
$$\text{MAD} = \frac{1}{N} \sum_{i=1}^{N} |x_i - \mu|$$
- MAD 对方差而言对异常值更稳健,因为它不会通过平方来放大大的偏差。然而,方差在数学上更便利(在证明和机器学习优化中更容易分解)。
- **位置**回答了一个不同的问题:特定数值相对于其余数据的位置在哪里?
- **四分位数**将排序后的数据分成四个相等的部分。Q1(第 25 百分位数)是低于该值的数据占 25% 的值。Q2 是中位数(第 50 百分位数)。Q3 是第 75 百分位数。
- **四分位距(IQR**是 $Q3 - Q1$。它捕捉了中间 50% 数据的离散程度,排除了极端值。
![显示 Q1、中位数、Q3、IQR、须线和异常值的箱线图](../images/quartiles_boxplot.svg)
- **箱线图**是统计学中最有用的可视化工具之一。箱体从 Q1 延伸到 Q3,中间的线为中位数,须线延伸到最远的非异常值,而须线之外的点则为异常值。
- **百分位数**是四分位数的推广。第 $p$ 百分位数是低于该值的观测值占 $p\%$ 的值。Q1 是第 25 百分位数,中位数是第 50 百分位数,Q3 是第 75 百分位数。
- **z 分数**告诉你一个值距均值有多少个标准差:
$$z = \frac{x - \mu}{\sigma}$$
- z 分数为 2 表示该值高于均值 2 个标准差。z 分数为 $-1.5$ 表示低于均值 1.5 个标准差。这也称为**标准化**,在机器学习中广泛用于特征缩放,因为它将任何分布变换为均值为 0、标准差为 1。
- **形状**描述了分布超出其中心和离散程度之外的几何特征。
- **偏度**(上一节中的标准化三阶矩)衡量不对称性。像正态曲线这样完全对称的分布,其偏度为零。正偏度表示右尾较长(如收入分布)。负偏度表示左尾较长(如退休年龄分布)。
$$\text{偏度} = \frac{1}{N} \sum_{i=1}^{N} \left(\frac{x_i - \mu}{\sigma}\right)^3$$
- **峰度**(标准化四阶矩)衡量尾部厚度。正态分布的峰度为 3。尾部更厚(更容易出现异常值)的分布的峰度大于 3。
$$\text{峰度} = \frac{1}{N} \sum_{i=1}^{N} \left(\frac{x_i - \mu}{\sigma}\right)^4$$
- **相关**衡量两个变量之间关系的强度和方向。它回答了:当一个变量上升时,另一个变量倾向于上升、下降,还是基本不变?
![三个散点图,分别显示正相关、无相关和负相关](../images/correlation_scatter.svg)
- **皮尔森相关**($r$)衡量*线性*关联。其取值范围从 $-1$(完全负相关)到 $0$(无相关)再到 $+1$(完全正相关)。
$$r = \frac{\sum_{i=1}^{N} (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum (x_i - \bar{x})^2} \cdot \sqrt{\sum (y_i - \bar{y})^2}}$$
- 如果你还记得第 1 章中的点积,皮尔森相关本质上就是 $\mathbf{x}$ 和 $\mathbf{y}$ 均值中心化之后的余弦相似度。
- **斯皮尔曼相关**($\rho$)衡量*单调*关联。它不使用原始值,而是先对它们进行排序,然后在排序上计算皮尔森相关。这使得它对异常值稳健,并且即使关系是非线性的,只要是一致递增或递减的,也能正常工作。
- **几何平均数**是当数值相互乘除时(如增长率)合适的平均值。如果你的投资分别增长了 10%、20% 和 30%,那么平均增长因子并不是这些增长率的算术平均数。而是:
$$\bar{x}_{\text{geo}} = \left(\prod_{i=1}^{N} x_i\right)^{1/N}$$
- 具体到增长率,先将百分比转换为因子(1.10、1.20、1.30),计算几何平均数,再减去 1。
- **指数移动平均(EMA)**赋予最近观测值更高的权重。与简单移动平均中窗口内所有点权重相等不同,EMA 呈指数衰减:
$$\text{EMA}_t = \alpha \cdot x_t + (1 - \alpha) \cdot \text{EMA}_{t-1}$$
- 平滑因子 $\alpha$(介于 0 和 1 之间)控制旧观测值失去影响的速度。$\alpha$ 越大,对近期变化的响应越灵敏;$\alpha$ 越小,曲线越平滑。在机器学习中,EMA 被用于 Adam 等优化器以及批归一化的运行统计中。
- **异常值检测**识别出与其余数据异常遥远的数点。两种常用方法:
- **IQR 法**:如果一个点低于 $Q1 - 1.5 \times \text{IQR}$ 或高于 $Q3 + 1.5 \times \text{IQR}$,则为异常值
- **Z 分数法**:如果 $|z| > 3$(距均值超过 3 个标准差),则为异常值
- IQR 法更稳健,因为它不假设正态分布。Z 分数法在数据近似正态时效果良好,但当分布高度偏斜时可能失效。
## 编程练习(使用 CoLab 或 notebook
1. 计算数据集的方差、标准差和 MAD,并进行比较。观察添加极端异常值时发生的变化。
```python
import jax.numpy as jnp
data = jnp.array([4, 8, 6, 5, 3, 7, 9, 5, 6, 7], dtype=jnp.float32)
mean = jnp.mean(data)
variance = jnp.var(data)
std = jnp.std(data)
mad = jnp.mean(jnp.abs(data - mean))
print("原始数据:")
print(f" 方差:{variance:.3f},标准差:{std:.3f}MAD{mad:.3f}")
# 添加一个异常值并重新计算
data_outlier = jnp.append(data, 100.0)
mean2 = jnp.mean(data_outlier)
print(f"\n添加异常值(100)后:")
print(f" 方差:{jnp.var(data_outlier):.3f},标准差:{jnp.std(data_outlier):.3f}MAD{jnp.mean(jnp.abs(data_outlier - mean2)):.3f}")
```
2. 计算两个变量之间的皮尔森相关和斯皮尔曼相关。尝试不同的关系。
```python
import jax
import jax.numpy as jnp
# 完全线性关系
x = jnp.array([1, 2, 3, 4, 5, 6, 7, 8], dtype=jnp.float32)
y = 2 * x + 1 # 试试修改这个!
def pearson(a, b):
a_c = a - jnp.mean(a)
b_c = b - jnp.mean(b)
return jnp.sum(a_c * b_c) / (jnp.sqrt(jnp.sum(a_c**2)) * jnp.sqrt(jnp.sum(b_c**2)))
def spearman(a, b):
rank_a = jnp.argsort(jnp.argsort(a)).astype(jnp.float32)
rank_b = jnp.argsort(jnp.argsort(b)).astype(jnp.float32)
return pearson(rank_a, rank_b)
print(f"皮尔森 r {pearson(x, y):.4f}")
print(f"斯皮尔曼 ρ:{spearman(x, y):.4f}")
```
3. 分别使用 IQR 和 Z 分数方法实现异常值检测,然后比较它们在偏斜数据上的结果。
```python
import jax.numpy as jnp
data = jnp.array([2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 50], dtype=jnp.float32)
# IQR 方法
q1, q3 = jnp.percentile(data, 25), jnp.percentile(data, 75)
iqr = q3 - q1
lower, upper = q1 - 1.5 * iqr, q3 + 1.5 * iqr
iqr_outliers = data[(data < lower) | (data > upper)]
print(f"IQR 边界:[{lower:.1f}, {upper:.1f}]")
print(f"IQR 异常值:{iqr_outliers}")
# Z 分数方法
z_scores = (data - jnp.mean(data)) / jnp.std(data)
z_outliers = data[jnp.abs(z_scores) > 3]
print(f"\nZ 分数:{z_scores}")
print(f"Z 分数异常值(|z| > 3):{z_outliers}")
```
4. 在不同平滑因子下计算并绘制带噪声数据的指数移动平均。
```python
import jax.numpy as jnp
import matplotlib.pyplot as plt
# 生成带噪声的数据
key = __import__("jax").random.PRNGKey(0)
noise = __import__("jax").random.normal(key, shape=(50,))
signal = jnp.linspace(0, 5, 50) + noise
def ema(data, alpha):
result = jnp.zeros_like(data)
result = result.at[0].set(data[0])
for t in range(1, len(data)):
result = result.at[t].set(alpha * data[t] + (1 - alpha) * result[t - 1])
return result
plt.figure(figsize=(10, 4))
plt.plot(signal, "o", alpha=0.3, label="原始数据", color="#999")
for alpha, color in [(0.1, "#e74c3c"), (0.3, "#3498db"), (0.7, "#27ae60")]:
plt.plot(ema(signal, alpha), label=f"α={alpha}", color=color, linewidth=2)
plt.legend()
plt.title("不同平滑因子下的 EMA")
plt.show()
```