深入理解平均值与中位数:机器学习中的核心指标对比与实践

在处理数据分析和构建机器学习模型时,我们经常面临一个基础但至关重要的问题:如何准确地总结数据的中心趋势?

平均值中位数 是两个最常用的统计指标,虽然它们看似简单,但在面对真实世界的复杂数据时,选择哪一个往往直接决定了模型的鲁棒性和最终结论的可信度。在这篇文章中,我们将深入探讨这两者的定义、背后的数学原理,以及——更重要的是——如何在不同的数据分布和业务场景中做出正确的选择。

我们将通过代码示例、可视化和实际应用场景,看看这两个指标是如何影响我们的数据分析结果的。让我们开始吧!

什么是平均值?

平均值,或者我们常说的算术平均数,是衡量数据集中趋势最直观的指标。它的计算逻辑非常简单:将所有数值相加,然后除以数值的数量。在数学上,这代表数据的“重心”。

为什么平均值如此重要?

由于平均值利用了数据集中的每一个数据点,它包含的信息量最大。在统计学中,它被称为充分统计量。这也是为什么在许多经典机器学习算法中,平均值占据着核心地位。

平均值的核心应用场景

#### 1. 特征归一化和缩放

这是数据预处理中最重要的步骤之一。许多机器学习算法(如支持向量机、神经网络)对数据的尺度非常敏感。如果特征之间的尺度差异很大,模型可能会被误导。

Z-score 标准化 是最常用的技术之一,它的核心就是平均值。公式如下:

$$ z = \frac{x – \mu}{\sigma} $$

其中 $\mu$ 是平均值,$\sigma$ 是标准差。通过这个变换,我们可以将数据转化为均值为 0,标准差为 1 的分布。

代码实战:Z-score 标准化

让我们看看如何使用 Python 的 scikit-learn 来实现这一过程。在这里,我们不仅计算平均值,还利用它来“校准”我们的数据。

import numpy as np
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

# 假设我们有一个包含两个特征的数据集
# 特征1:年龄 (范围 20-60)
# 特征2:收入 (范围 50000-100000)
data = np.array([
    [25, 50000],
    [30, 60000],
    [35, 80000],
    [40, 85000],
    [50, 120000] # 收入有一个较高的值
])

print("原始数据平均值:
", np.mean(data, axis=0))

# 初始化 StandardScaler
# 它会自动计算每个列的平均值和标准差
scaler = StandardScaler()

# 拟合并转换数据
scaled_data = scaler.fit_transform(data)

print("
标准化后的数据:
", scaled_data)
print("标准化后的平均值 (应非常接近 0):
", np.mean(scaled_data, axis=0))

在上面的代码中,你可以看到,通过减去平均值,我们将数据的中心移到了原点。这是模型能够高效学习的基础。

#### 2. 正态分布下的数据插补

当数据呈现完美的正态分布(钟形曲线)时,平均值、中位数和众数是重合的。在这种情况下,平均值代表了出现概率最高的值。因此,当我们遇到缺失值时,用平均值来填补是合理的,因为它不会引入偏差。

#### 3. 损失函数的核心

你可能听说过 MSE(均方误差)MAE(平均绝对误差)。注意它们的名字都带有“平均”。

特别是线性回归,其目标函数本质上是最小化预测值与真实值之间的误差平方和。从数学上可以证明,为了最小化平方误差,最优解就是预测数据的平均值。这意味着,如果我们要用一个数字来尽可能准确地代表一组数据(在最小化平方误差的意义下),平均值是数学上的最佳选择。

#### 4. 图像处理中的像素归一化

在计算机视觉任务中,图像的像素值通常在 0 到 255 之间。为了加速神经网络的收敛,我们通常会将像素值减去平均值(例如 ImageNet 数据集的 RGB 平均值),然后除以标准差。

# 伪代码示例:图像预处理
# 假设 img 是一个 (Height, Width, 3) 的图像数组

# ImageNet 数据集的 RGB 平均值 (示例值)
mean_values = [123.68, 116.78, 103.94] 

# 我们将图像减去这个平均值
# 这相当于将图像的“亮度中心”对齐到0
normalized_img = img - mean_values 

如果不做这一步,不同的输入图片亮度差异可能会干扰模型提取特征。

平均值的软肋:异常值

虽然平均值很强大,但它有一个致命的弱点:对异常值极其敏感

举个简单的例子:假设你和比尔·盖茨在一个房间里。

  • 你的资产:10万美元
  • 比尔·盖茨的资产:1000亿美元
  • 平均值:约 500亿美元

这个“平均值”能代表你的财富状况吗?显然不能。这就是我们在分析偏态数据时必须小心的原因。在图像处理中,虽然异常值较少,但在金融欺诈检测或用户行为分析中,异常值随处可见。

什么是中位数?

中位数是数据集排序后位于中间位置的值。与平均值不同,计算中位数不需要知道具体的数值大小,只需要知道它们的排序

计算逻辑

  • 奇数个观测值:取中间的那个值。
  • 偶数个观测值:取中间两个值的平均值。

这种计算方式赋予了中位数一个独特的性质:它只关心中间位置的值,而不关心极端值到底有多大。 这使得中位数成为了一种“稳健”的统计量。

中位数在实战中的优势

#### 1. 稳健的数据插补

当数据包含噪声、错误录入或极端异常值时(例如收入数据中混入了一位亿万富翁),使用平均值填充缺失值会人为地抬高整体水平。而中位数则能保持数据的“原汁原味”,代表大多数人的真实情况。

#### 2. 抗异常值的特征缩放

除了传统的 Z-score,还有一种缩放方法叫做 Robust Scaling(鲁棒缩放)。它不使用平均值和标准差,而是使用中位数四分位距(IQR)。这对于包含离群点的数据集非常有效。

代码实战:鲁棒缩放 vs 标准缩放

让我们构造一个带有明显异常值的数据集,看看两者的区别。

from sklearn.preprocessing import RobustScaler, StandardScaler
import numpy as np

# 构造数据:大部分数据在 0-10 之间,但有一个异常值 1000
X = np.array([[1.0], [2.0], [3.0], [4.0], [5.0], [1000.0]])

# 标准化 (使用平均值)
standard_scaler = StandardScaler()
X_standard = standard_scaler.fit_transform(X)

# 鲁棒缩放 (使用中位数)
robust_scaler = RobustScaler()
X_robust = robust_scaler.fit_transform(X)

print(f"原始数据: {X.flatten()}")
print(f"标准化后 (受异常值影响,正常数据被压缩得很小): 
{X_standard.flatten()}")
print(f"鲁棒缩放后 (正常数据依然保持良好的区分度): 
{X_robust.flatten()}")

# 验证中位数的稳定性
print(f"
原始中位数: {np.median(X)}")
print(f"标准化数据的中位数: {np.median(X_standard)}") 
# 注意:标准化改变了中位数,因为标准差被异常值拉得巨大

在这个例子中,你会注意到 INLINECODE9d04cf0d 产生的结果中,原本正常的 1, 2, 3, 4, 5 变得非常接近,因为那个 1000 把标准差撑得非常大,导致模型很难区分这些正常数据。而 INLINECODEaa77271e 则很好地保留了正常数据之间的差异。

#### 3. 树模型中的决策阈值

决策树算法通过寻找最佳分割点来划分数据。虽然决策树通常基于基尼系数或熵来分割,但在某些回归树或特定的分割逻辑中,使用中位数作为分割点可以有效地减少某一分支中的方差,且不会因为异常值导致分割点偏移。

实际案例:房地产定价

在预测房价时,我们经常遇到“豪宅”现象。某个区域的房价大多在 5 万到 10 万之间,但有一两套庄园卖到了 1000 万。

  • 如果我们用平均房价来评估该区域的“典型”居住成本,这个数字会被豪宅严重拉高,导致对普通购房者产生误导。
  • 如果我们用中位数房价,豪宅的影响将被忽略,我们得到的是“位于中间位置”的那套房子的价格,这更符合大多数人的市场感知。

深入比较:平均值 vs 中位数

为了让你在面试或实际工作中能清晰地做出选择,我们总结了以下关键差异:

方面

平均值

中位数 :—

:—

:— 数学定义

所有数值之和除以数量

排序后位于中间的值 数据分布假设

假设数据呈对称分布(如高斯分布)。这是许多线性模型的理论基础。

不依赖分布假设。在偏态或长尾分布下表现更优。 异常值敏感度

极高。一个极端值可以任意改变平均值。

极低。无论异常值多大,只要它不改变排序,中位数就不变。 计算复杂度

$O(N)$。只需一次遍历求和,适合流式数据处理。

$O(N \log N)$(主要来自排序操作)。在大规模数据集上计算成本较高。 机器学习应用

线性回归、逻辑回归、K-Means、神经网络。

决策树(处理回归问题时)、基于分位数的特征工程。

数据分布的视觉化影响

理解数据分布的形状是选择平均值还是中位数的关键。

  • 对称分布:

数据像一座完美的钟形曲线。此时平均值 = 中位数。我们可以放心地使用平均值,因为它包含了所有信息且没有偏差。

  • 右偏分布:

也称为正偏分布。比如个人收入。大部分人收入一般,但少数亿万富翁将曲线的“尾巴”拉向了右边。

– 在这种情况下,平均值 > 中位数

– 平均值会被“拉”向长尾方向,高估了中心趋势。此时报告中位数更诚实。

  • 左偏分布:

比如退休年龄。大部分人集中在 60-65 岁退休,但少数人在 20 岁就因病退休(极低值)。

– 在这种情况下,平均值 < 中位数

– 平均值被向左拉低。

!Mean vs Median in Different Distributions

(图片展示了在不同偏态分布中,平均值如何被拖向“尾巴”的方向,而中位数则保持相对稳定)

代码实战:处理偏态数据

让我们通过一个 Python 脚本来模拟偏态数据,并观察两者的差异。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 设置随机种子以保证结果可复现
np.random.seed(42)

# 生成一个右偏的数据集:模拟1000个人的月薪
# 大部分人集中在 3000-8000
normal_salaries = np.random.normal(loc=5000, scale=1500, size=990)

# 添加 10 个CEO的高薪数据 (异常值)
exec_salaries = np.random.normal(loc=100000, scale=10000, size=10)

# 合并数据
salaries = np.concatenate([normal_salaries, exec_salaries])

# 计算统计量
mean_salary = np.mean(salaries)
median_salary = np.median(salaries)

print(f"平均月薪: {mean_salary:.2f}")
print(f"中位数月薪: {median_salary:.2f}")

# 解读差异
print(f"
差异分析: 平均值比中位数高出 {(mean_salary - median_salary):.2f} 元")
print("如果你用平均值来描述‘普通员工‘的工资,你会给出一个错误的过高预期。")

# 简单的可视化 (需要 matplotlib 环境)
# plt.hist(salaries, bins=50, edgecolor=‘black‘)
# plt.axvline(mean_salary, color=‘red‘, linestyle=‘dashed‘, linewidth=2, label=‘Mean‘)
# plt.axvline(median_salary, color=‘green‘, linestyle=‘dashed‘, linewidth=2, label=‘Median‘)
# plt.legend()
# plt.show()

运行这段代码,你会发现平均值可能远高于中位数。如果你正在制定针对普通员工的薪酬福利政策,依赖平均值可能会导致严重的误判。

常见错误与最佳实践

在与很多初级数据分析师交流时,我们发现了一些常见的误区。这里有几个避坑指南:

  • 盲目使用平均值填充缺失值

错误:在包含大量异常值的列(如用户消费金额)直接使用 fillna(df.mean())
正确:先检查数据的偏度。如果数据严重偏斜,使用 fillna(df.median())

  • 忽略模型对分布的假设

错误:在数据严重偏态且未做变换的情况下,直接将其输入到线性回归模型中。线性模型假设残差正态分布,严重的偏态会导致预测在极端值处偏差很大。
正确:对偏态数据进行对数变换,使其接近正态分布,然后再使用基于平均值的模型。

  • 混淆 Scale 和 RobustScaler

场景:你需要处理用户的点击率数据,其中包含一些由于爬虫造成的极端高点击。
建议:抛弃 INLINECODE58ae9226,改用 INLINECODEf80dd425。或者,在计算指标时先清洗掉明显的离群点(例如 3倍标准差之外的数据),然后再算平均值。

总结与下一步

在数据科学和机器学习的旅途中,理解平均值和中位数的区别是最基础但也最关键的一步。

回顾一下核心要点:

  • 平均值 是数学优化的宠儿,适合正态分布的数据,用于计算损失函数和归一化,但极易受异常值干扰。
  • 中位数 是现实世界的守护者,稳健、抗干扰,是处理收入、房价、用户行为等偏态数据的最佳选择。

给你的建议:

下次当你拿到一份新的数据集时,不要只看 df.describe() 里的 Mean。花一分钟时间,比较一下 Mean 和 Median。如果它们差距很大,那这就不仅仅是一个数字游戏,而是数据在向你讲述一个关于“异常值”和“偏态”的故事。你需要根据这个故事来选择合适的模型和预处理策略。

现在,打开你的 Jupyter Notebook,找一份真实的数据集(比如 Kaggle 上的房价或 Titanic 数据集),尝试分别用平均值和中位数去填补缺失值,看看这对最终模型准确率有什么影响?动手实践是最好的老师。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/39503.html
点赞
0.00 平均评分 (0% 分数) - 0