Skip to content

Statistical Measures(统计度量)

统计度量用单个数字汇总数据,捕捉数据的分散性、位置、形状和关联性。本节涵盖方差、标准差、四分位数、偏度、峰度、协方差、相关性和 z-score——这是 ML 探索性数据分析和特征工程的工具集。

  • 在上一节我们将矩作为一类汇总统计量来介绍。本节将深入探讨由此衍生的实用工具:离散度、位置、形状和关联性的度量。

  • 离散度(dispersion)回答这个问题:数据的分散程度如何?两个班级可能有相同的平均考试成绩,但分散程度截然不同。

两个均值相同但分散程度不同的分布

  • 窄(蓝色)分布的方差低:大多数值紧密聚集在均值附近。宽(红色)分布的方差高:值更分散。

  • 方差(variance)是与均值的平均平方距离。平方是为了避免正负偏差相互抵消。

\[\sigma^2 = \frac{1}{N} \sum_{i=1}^{N} (x_i - \mu)^2\]
  • 处理样本(而非整体总体)时,用 \(N - 1\) 而非 \(N\) 做分母。这一修正(称为 Bessel 修正)考虑了样本往往低估真实变异性这一事实:
\[s^2 = \frac{1}{N-1} \sum_{i=1}^{N} (x_i - \bar{x})^2\]
  • 标准差(standard deviation)是方差的平方根:\(\sigma = \sqrt{\sigma^2}\),将度量单位还原为原始单位。若数据单位为厘米,则方差单位为 cm\(^2\),但标准差单位回到 cm。

  • 平均绝对偏差(MAD, Mean Absolute Deviation)是更简单的替代方案。不平方,而是对每个偏差取绝对值:

\[\text{MAD} = \frac{1}{N} \sum_{i=1}^{N} |x_i - \mu|\]
  • MAD 对异常值比方差更鲁棒,因为它不通过平方放大大偏差。但方差在数学上更方便(在证明和 ML 优化中分解性质更好)。

  • 位置(position)回答另一个问题:某个特定值相对于其余数据处于什么位置?

  • 四分位数(quartiles)将排序后的数据分为四等份。Q1(第 25 百分位)是 25% 的数据低于它的值。Q2 是中位数(第 50 百分位)。Q3 是第 75 百分位。

  • 四分位距(IQR, Interquartile Range)\(Q3 - Q1\),捕捉数据中间 50% 的分散程度,忽略极端值。

箱线图显示 Q1、中位数、Q3、IQR、须线和异常值

  • 箱线图是统计学中最有用的可视化之一。箱体从 Q1 延伸到 Q3,内部线为中位数,须线延伸到最远的非异常值,须线之外的点是异常值。

  • 百分位数(percentiles)是四分位数的推广。第 \(p\) 百分位是 \(p\%\) 的观测值低于它的值。Q1 是第 25 百分位,中位数是第 50 百分位,Q3 是第 75 百分位。

  • z-score 告诉你某个值距均值有多少个标准差:

\[z = \frac{x - \mu}{\sigma}\]
  • z-score 为 2 表示该值比均值高 2 个标准差。z-score 为 \(-1.5\) 表示低 1.5 个标准差。这也称为标准化(standardisation),在 ML 特征缩放中大量使用,它将任意分布变换为均值 0、标准差 1 的分布。

  • 形状(shape)描述分布在中心和分散程度之外的几何特性。

  • 偏度(skewness)(上一节的标准化第 3 阶矩)度量不对称性。正态曲线等完全对称分布的偏度为零。正偏度意味着右尾更长(如收入分布)。负偏度意味着左尾更长(如退休年龄分布)。

\[\text{Skewness} = \frac{1}{N} \sum_{i=1}^{N} \left(\frac{x_i - \mu}{\sigma}\right)^3\]
  • 峰度(kurtosis)(标准化第 4 阶矩)度量尾部厚重程度。正态分布的峰度为 3。尾部更重(更易出现异常值)的分布峰度大于 3。
\[\text{Kurtosis} = \frac{1}{N} \sum_{i=1}^{N} \left(\frac{x_i - \mu}{\sigma}\right)^4\]
  • 相关性(correlation)度量两个变量之间关系的强度和方向,回答:当一个变量增大时,另一个是倾向于增大、减小还是无关?

三个散点图分别显示正相关、无相关和负相关

  • Pearson 相关系数\(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 章的点积(dot product),Pearson 相关系数本质上是 \(\mathbf{x}\)\(\mathbf{y}\) 去中心化版本之间的余弦相似度。

  • Spearman 相关系数\(\rho\))度量单调关联。它先对数据排名,再对排名计算 Pearson 相关系数。这使其对异常值更鲁棒,即使关系非线性,只要单调递增或递减即可有效。

  • 几何平均数(geometric mean)适用于乘法组合的量,如增长率。若投资依次增长 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, Exponential Moving Average)给近期观测值更高的权重。不同于简单移动平均中窗口内所有点权重相等,EMA 按指数衰减:

\[\text{EMA}_t = \alpha \cdot x_t + (1 - \alpha) \cdot \text{EMA}_{t-1}\]
  • 平滑因子 \(\alpha\)(取值 0 到 1 之间)控制旧观测值失去影响的速度。\(\alpha\) 越大,对近期变化响应越灵敏;\(\alpha\) 越小,曲线越平滑。在 ML 中,EMA 用于 Adam 等优化器以及 batch normalization 的运行统计中。

  • 异常值检测(outlier detection)识别距其余数据异常远的数据点。两种常用方法:

    • IQR 法:数据点落在 \(Q1 - 1.5 \times \text{IQR}\) 以下或 \(Q3 + 1.5 \times \text{IQR}\) 以上时为异常值
    • z-score 法\(|z| > 3\) 时为异常值(距均值超过 3 个标准差)
  • IQR 法更鲁棒,因为它不假设正态分布。z-score 法在数据近似正态时效果好,但分布严重偏斜时可能失效。

编程练习(使用 CoLab 或 notebook)

  1. 计算一个数据集的方差、标准差和 MAD 并进行比较。观察添加一个极端异常值后发生的变化。

    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("Original data:")
    print(f"  Variance: {variance:.3f}, Std: {std:.3f}, MAD: {mad:.3f}")
    
    # 添加异常值并重新计算
    data_outlier = jnp.append(data, 100.0)
    mean2 = jnp.mean(data_outlier)
    print(f"\nWith outlier (100):")
    print(f"  Variance: {jnp.var(data_outlier):.3f}, Std: {jnp.std(data_outlier):.3f}, MAD: {jnp.mean(jnp.abs(data_outlier - mean2)):.3f}")
    

  2. 计算两个变量之间的 Pearson 和 Spearman 相关系数。尝试不同的关系形式。

    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"Pearson r:  {pearson(x, y):.4f}")
    print(f"Spearman ρ: {spearman(x, y):.4f}")
    

  3. 用 IQR 法和 z-score 法实现异常值检测,并在偏斜数据上比较结果。

    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 bounds: [{lower:.1f}, {upper:.1f}]")
    print(f"IQR outliers: {iqr_outliers}")
    
    # z-score 法
    z_scores = (data - jnp.mean(data)) / jnp.std(data)
    z_outliers = data[jnp.abs(z_scores) > 3]
    print(f"\nZ-scores: {z_scores}")
    print(f"Z-score outliers (|z| > 3): {z_outliers}")
    

  4. 用不同平滑因子对含噪数据计算指数移动平均(EMA)并绘图。

    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="raw data", 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 with different smoothing factors")
    plt.show()