恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
机器学习必懂的统计量:均值方差协方差与Batch Normalization
首页
资讯中心
/
机器学习必懂的统计量:均值方差协方差与Batch Normalization
机器学习必懂的统计量:均值方差协方差与Batch Normalization
发布时间:2026/10/19 19:55:13
机器学习入门最容易被忽略但又最值得先搞明白的一块就是统计量。算法框架可以现成调用模型效果不好时手里却没有排查工具根本原因就是对这些底层概念理解得模棱两可。均值、方差、协方差、相关系数、标准化一直到批归一化Batch Normalization简称BN它们不只是教科书上的公式而是贯穿数据处理、特征工程、模型训练和调优全过程的工具。这篇就把这些统计量的来龙去脉、计算公式、实际用途和踩坑经验一次讲透配合可复现的代码片段争取让你看完就能直接上手用。1. 先从均值说起数据中心在哪里1.1 平均值的直觉与公式均值是所有人最早接触的统计量公式简单到不需要刻意记[ \bar{x} \frac{1}{n} \sum_{i1}^{n} x_i ]但它在机器学习里的角色比“算个平均数”要深得多。数据预处理的第一步往往就是中心化。比如在做PCA主成分分析之前官方文档和教程都会强调先对特征减去均值让每个维度的数据围绕原点分布。为什么因为PCA找的是最大方差方向如果某一维特征的均值特别大比如房价的绝对数值是几十万到几百万它天然就会主导方差计算导致降维结果被“数值大小”带偏而不是被“数据真正的结构”带偏。减去均值之后各个维度才在同一个比较基准上。均值在损失函数里也无处不在。MSE均方误差的“均值”二字就是所有样本误差先平方再取平均。这个平均操作让误差不再依赖样本数量可以在不同规模数据集上横向比较loss的大小。我刚开始调模型时有个误区以为loss越小模型越好后来发现只要样本量翻倍MSE的分子分母同步变化其实单次loss值本身并不能说明模型优劣重要的是它在验证集上的变化趋势和相对位置。1.2 均值和中位数怎么选机器学习里均值是主流选择但有一个关键的前提——数据中没有极端值污染。比如某个特征“用户年收入”绝大多数人集中在10万到50万这个区间但有个别样本是几个亿。这时候均值会被这些极端值拉高反而不能代表“典型用户”的收入水平。中位数对极端值不敏感能更稳健地描述数据中心。我的经验是做特征工程时先画箱线图或者看describe()输出。如果发现某特征的max值远远大于75%分位数建议在标准化之前先决定是否要做离群点裁剪比如只保留3个标准差以内的样本否则后续标准化也会被极端值带歪。提示均值是“敏感”的中位数是“稳健”的但深度学习里梯度计算大多基于均值因此更多时候我们选择在数据清洗阶段提前处理离群点而不是换用中位数。1.3 numpy计算均值的细节import numpy as np x np.array([1, 2, 3, 4, 100]) print(np.mean(x)) # 22.0 print(np.median(x)) # 3.0这段代码很直观一个包含极端值的数组均值22.0中位数3.0两者差异巨大。日常处理表格数据时我也常用pandas的df.describe()同时观察均值、标准差、分位数这样能快速感知数据分布是否存在异常。2. 方差和标准差衡量数据的离散程度2.1 方差公式里的自由度陷阱方差衡量的是每个样本与均值的平均偏离程度。总体方差公式是[ \sigma^2 \frac{1}{n} \sum_{i1}^{n} (x_i - \bar{x})^2 ]但实际工程中我们处理的基本都是样本所以更常用样本方差[ s^2 \frac{1}{n-1} \sum_{i1}^{n} (x_i - \bar{x})^2 ]分母是n-1而不是n这个细节很多初学者会忽略。原因是我们用样本均值(\bar{x})去估计总体均值样本均值本身也会“吸收”一部分数据波动导致离差平方和偏小。分母减1做校正得到的方差会略微放大从而更接近总体的真实方差。这个修正叫贝塞尔校正。我自己在纯Python自写算法时曾经直接用np.var(x)算方差结果和手算对不上查了半天才发现numpy默认分母是n而pandas的.var()默认分母是n-1。数据量小的时候差别肉眼可见数据量大时差距不大但在做统计推断或写论文级别的实验时这个细节必须较真。2.2 标准差回到原始量纲方差的问题在于量纲变成了平方。如果特征单位是“米”方差单位就是“平方米”解释性很差。标准差是方差的平方根让离散度回到原始单位[ s \sqrt{s^2} ]在机器学习里标准差有两个高频出现的地方。第一个是特征缩放。Z-score标准化的分母用的就是标准差。将每个值减去均值后除以标准差得到的特征均值为0、标准差为1这样不同量纲的特征之间就有了可比性。第二个是误差分析。模型预测的残差预测值减真实值如果大致服从正态分布那么约68%的残差落在1个标准差内约95%落在2个标准差内。这个经验法则可以用来判断是否存在异常预测——如果某个样本的残差超过了3个标准差我一般会单独拎出来检查看是标注错误、特征缺失还是确实属于长尾难例。data np.array([2, 4, 4, 4, 5, 5, 7, 9]) var_pop np.var(data) # 4.0 var_sample np.var(data, ddof1) # 4.5714 std_sample np.std(data, ddof1) # 2.1382.3 用方差理解“数据的形状”方差小说明数据抱团方差大说明数据分散。在无监督学习中常用的KMeans聚类的目标函数就是最小化“簇内距离平方和”本质上是把数据切分使得每个簇内的方差尽量小。所以“方差”不只是一个描述性的数字它本身就是很多算法的优化目标。理解到这一层很多算法的设计动机就通了。3. 协方差与相关系数捕捉变量之间的关系3.1 协方差的含义两个变量的协方差定义如下[ \text{Cov}(X, Y) \frac{1}{n} \sum_{i1}^{n} (x_i - \bar{x})(y_i - \bar{y}) ]协方差的符号很好理解。如果X大于均值时Y也倾向于大于均值那么乘积为正协方差为正如果X大于均值时Y反而小于均值乘积为负协方差为负。但协方差有一个实际使用的痛点它的大小受量纲影响。X以“米”为单位和以“厘米”为单位计算出的协方差数值完全不同无法跨特征比较。3.2 相关系数标准化后的协方差相关系数通常指皮尔逊相关系数就是对协方差做“归一化”把两个变量各自的标准差除掉[ r \frac{\text{Cov}(X, Y)}{s_X s_Y} ]r的取值范围是[-1, 1]。1表示完全正线性相关-1表示完全负线性相关0表示没有线性相关关系。在特征工程中相关系数是我必看的一张表。用pandas的.corr()可以快速得到特征间的相关矩阵再用seaborn热力图可视化高相关的特征对一眼就能识别。候选特征之间若相关系数超过0.9我倾向于只保留其中一个减少冗余和潜在的多重共线性问题。需要强调的是相关系数只刻画线性关系两个变量之间有明显的非线性关系比如U型曲线时相关系数可能接近0但实际它们并不独立。所以相关性矩阵只能作为筛选特征的辅助工具不能替代业务理解。import pandas as pd import numpy as np df pd.DataFrame({ 面积: [50, 60, 70, 80, 90, 100], 价格: [100, 130, 160, 190, 220, 250], 楼层: [2, 5, 1, 8, 3, 6] }) print(df.corr())输出结果里“面积”和“价格”相关系数接近1说明两者高度线性正相关“楼层”与其他特征的相关系数则基本在0附近。这种表格在建模前跑一下心里大概就有数了。3.3 协方差矩阵与PCA的关系协方差矩阵是协方差的自然延伸对于d维数据协方差矩阵是一个(d \times d)的对称矩阵第i行第j列就是第i个特征和第j个特征的协方差。PCA的输入就是协方差矩阵。它做的事情本质上是找到一组正交方向使得数据在这些方向上的投影方差依次递减。这个“投影方差最大”的方向就是协方差矩阵最大特征值对应的特征向量。想一想方差是离散度PCA要找的是数据差异最大的方向本质上就是最大化方差。统计量在这里直接变成了算法的核心引擎。所以学PCA卡住的时候回头补一下协方差矩阵的特征值分解一切都能串起来。4. 标准化与归一化把不同尺度的特征拉齐4.1 Z-score标准化在处理多特征数据时最常遇到的问题是不同特征数值范围差异过大。比如收入范围是几千到几万年龄范围是20到60如果直接把这些特征喂给模型数值范围大的特征会主导距离计算和梯度更新。Z-score标准化公式如下[ x \frac{x - \mu}{\sigma} ]这样做之后每个特征都变成均值为0、标准差为1的分布特征之间有了统一的尺度。Z-score的适用场景主要是特征分布接近正态分布、数据没有明显离群点的场景。对于线性回归、逻辑回归、SVM这类对特征尺度敏感的模型标准化几乎是必选项。4.2 Min-Max归一化另一种常见做法是Min-Max归一化[ x \frac{x - \min(x)}{\max(x) - \min(x)} ]把数据压到[0, 1]区间。它适用于已知特征有明确上下界、数据分布比较均匀的场景比如像素值0到255。但Min-Max归一化有一个致命弱点一旦新来的数据超出之前的最小值或最大值整个映射关系就被打破。我曾在一次上线模型时因为线上数据出现了一个比训练集更大的值导致所有归一化后的特征都跟着偏移模型预测效果明显变差。所以在线系统里我一般更倾向用Z-score或者使用分位数缩放这类稳健方法。4.3 一个必须避开的坑数据泄露这是我在实际项目中踩过最深的坑。做标准化时如果用整个数据集的均值和方差去缩放训练集和测试集实际上测试集的信息已经偷偷进入了训练阶段这就是数据泄露。正确做法是先在训练集上计算均值和方差再用这两个统计量去缩放验证集和测试集。from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test)注意看fit_transform只对训练集调用测试集只调用transform。缩放器里的均值和标准差完全来自训练集。这个细节决定你验证集评估结果的真实性也决定模型上线后的稳定表现。网上很多新手教程在写标准化时直接对整个数据集fit_transform实践中应该避免这种写法。注意任何基于全局数据统计的预处理标准化、PCA、归一化都必须严格限制在训练集上拟合测试集只做变换否则评估结果偏乐观线上表现会打折扣。5. 批归一化让统计量成为网络的一部分5.1 从数据预处理到网络内部数据标准化是建模前对输入特征做的但深层网络的中间层输出会随着训练更新不断变化导致每层的输入分布一直在变。这种现象被称为内部协变量偏移。BN的思路很直接在每一层激活函数之前把中间输出拉回到接近标准正态分布的形态然后通过两个可学习的参数做恢复性变换。BN的完整计算分四步每步都跟统计量相关计算当前batch的均值(\mu_B)。计算当前batch的方差(\sigma_B^2)。用这两个统计量做标准化(\hat{x} \frac{x - \mu_B}{\sqrt{\sigma_B^2 \epsilon}})缩放和平移(y \gamma \hat{x} \beta)这里的(\gamma)和(\beta)是网络可学习的参数。初始时一般设(\gamma1)、(\beta0)确保BN层刚接入时不会破坏原有的特征分布随着训练过程自动调节。5.2 训练和推理时的行为差异这是BN实现里最微妙的地方。训练阶段我们用当前batch的均值和方差做标准化好处在于batch统计量带一定噪声反而有轻微正则化效果类似Dropout。但推理阶段你不可能每次预测都凑一个batch再算均值。实际操作中PyTorch和TensorFlow都会维护一个滑动平均的全局均值和全局方差推理时直接用这两个全局统计量做标准化。这个“全局统计量”才是最接近训练数据整体分布的版本。我第一次自己手写BN层时推理效果崩得一塌糊涂后来才发现问题不在结构而在推理阶段用了当前batch的统计量而当前batch数据量太小估计的均值方差噪声大到完全破坏特征分布。5.3 为什么BN能加速收敛关于BN为什么有效学术界有过一些争议最初认为它是解决内部协变量偏移问题后来有研究证明内部协变量偏移的减少程度和BN的加速效果并不完全相关。更被广泛接受的一个解释是BN让损失曲面变得更加光滑梯度更新更稳定因此可以使用更大的学习率。我在实际调参中的体验是加上BN之后对学习率的敏感度确实下降了模型更容易训练即使初始学习率设置偏大也不易发散。这个特点和“统计量”有什么关系因为它本质上是把每层的输出分布调整到合理范围避免某一层的输出值过大或过小导致梯度爆炸或消失。均值决定输出的中心位置方差决定输出的尺度而(\gamma)和(\beta)给网络保留了恢复任意分布的自由度。5.4 用numpy手写一个简版BN为了弄懂BN到底做了什么我建议自己手写一遍前向过程哪怕只是玩具版。import numpy as np def batchnorm_forward(x, gamma, beta, eps1e-5): mu np.mean(x, axis0) var np.var(x, axis0) x_hat (x - mu) / np.sqrt(var eps) out gamma * x_hat beta return out x np.random.randn(32, 64) # 模拟batch32特征维度64 gamma np.ones(64) beta np.zeros(64) out batchnorm_forward(x, gamma, beta) print(out.mean(axis0)) # 接近0 print(out.std(axis0)) # 接近1这里能直观看到经过BN之后输出的均值和标准差都被归一化到0和1附近。真实框架里还会维护全局统计量和梯度反传但这个简单的过程已经能说明BN和均值方差这些基础统计量之间的关系。BN在小batch场景下容易出问题。batch size只有2或4时样本太少均值和方差的估计不可靠反而引入噪声。这时可以考虑用LayerNorm或GroupNorm这类不依赖batch的归一化方式。我实际训练过batch size为1的任务BN完全不适用换成LayerNorm之后才正常收敛。6. 实操案例统计量打包用在一次特征工程里6.1 一个完整的建模前流程为了让你看到这些统计量如何协同工作我模拟一个房价预测的典型流程。数据包含面积、房间数、楼龄、到地铁站距离四个特征目标变量是房价。第一步加载数据并查看基本统计信息。import pandas as pd import numpy as np df pd.DataFrame({ 面积: [80, 120, 60, 150, 90, 110, 70, 130], 房间数: [2, 3, 1, 4, 2, 3, 2, 4], 楼龄: [5, 20, 30, 10, 15, 25, 40, 8], 距地铁: [500, 1200, 800, 2000, 600, 1500, 300, 900], 房价: [350, 480, 280, 550, 390, 460, 300, 520] }) print(df.describe())从describe输出里能快速看到各个特征的均值、标准差和分位数。面积、距地铁的数值范围差异很大如果直接建模距离计算会被面积主导这时候标准化就非常必要。第二步检查相关系数矩阵判断特征间是否存在冗余。print(df.corr())假设输出显示“面积”和“房间数”相关系数达到0.85以上我会考虑是否只保留其中一个或者把两者合并成一个新特征比如“人均居住面积”。这种基于相关性矩阵的特征筛选比盲目堆特征要可靠得多。第三步分离训练集和测试集在训练集上fit标准化器。from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler X df.drop(房价, axis1) y df[房价] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.25, random_state42) scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test)第四步可以进入模型训练阶段。这一步用到的是上面所有统计量的累积结果均值、方差让我们理解数据相关系数让我们筛选特征标准化让模型能够公平学习各维度信息。6.2 菜鸟和高手的差距在于对统计量的敏感度同样拿到一份新数据集有经验的人第一件事就是跑describe和corr。这看起来简单实际是在利用统计量快速建立对数据的理解数据是否有缺失、是否有离群点、特征间是否冗余、数值范围差异多大。这些判断决定了后续所有处理的思路而不只是盲目套模型。我在实际使用中的体会是越到后面越发现模型选择是套路化的事但数据理解永远是拉开差距的地方。统计量不是考试内容是工具。6.3 简化思考把统计量当成模型的“体检指标”一个模型训完之后我会习惯性检查几类统计指标训练集和验证集的损失均值、残差标准差、特征相关性变化。如果验证集loss的均值不断下降但标准差特别大说明模型在部分样本上表现优异在另一部分样本上表现糟糕可能需要检查数据分片或者增加特定样本的训练权重。如果某个特征在训练前后的标准差变化异常说明模型对该特征非常敏感此时可以检查是否有异常特征工程操作。这些都是统计量在日常调参中的延伸应用。它们不直接出现在网络结构里但指导着你每一步决策。7. 常见问题与避坑指南7.1 标准化和归一化到底什么时候用哪个这个问题几乎每次带新人都会遇到。我给出的建议很简单如果算法是基于距离的KNN、SVM、KMeans优先用标准化。如果特征是已知有边界的数值像素、百分比Min-Max归一化够用。如果数据存在较多离群点可以考虑RobustScaler使用中位数和四分位距做缩放这也是统计量在工程里的另一种应用。不需要死记硬背只要理解标准化是“减均值除以标准差”归一化是“压缩到固定区间”然后根据数据和模型选择即可。7.2 为什么训练集和测试集要用不同的fit方式已经详细说过数据泄露问题。这里补充一个具体的后果案例某次实验里我先对整个数据集做了标准化再划分训练测试集结果验证集AUC比正确做法高出0.03左右。看起来“效果更好”但上线后真实表现远没有这么好。这个0.03就是数据泄露带来的虚假红利。任何比赛和实际业务里沿着错误流程做出来的评估结果都不具备参考价值。7.3 BN在推理阶段效果不对如果你发现在训练时loss正常下降但切换eval模式后预测结果明显异常优先检查BN层的全局统计量是否更新正确。某些自定义模型在加载预训练权重时如果BN层的running_mean和running_var没有正确加载也会出现类似问题。解决办法是确认框架默认的参数持久化逻辑并且在冻结BN层时小心处理统计量的更新。7.4 方差和标准差的备份作用我通常在训练前会把每个特征的均值、标准差保存成一个JSON文件线上服务做特征转换时直接读取这两个统计量保证线上推理用的标准化参数和训练时完全一致。如果每次都在线上重新算均值方差那就等于引入了新的数据分布模型很容易失灵。8. 最后再分享一点体会统计量这个主题看起来基础但每次我觉得“已经懂了”的时候总会在新的模型架构或新的数据处理需求里遇到它们的变体。比如自注意力机制里的LayerNorm整个人工智能框架都在沿用“减均值、除标准差、再缩放平移”这个范式。可以说理解了均值方差这些统计量就拿到了理解现代模型结构的一把钥匙。而且我还发现一个学习方法不要只背公式要亲手把公式用numpy实现一遍再和框架自带实现做对比。过程会很慢但就在这个过程中你对“为什么用这些统计量”“这些统计量到底起了什么作用”的理解会上一个台阶。如果你刚开始学机器学习我建议把今天提到的这些统计量作为优先掌握的基础深入理解每一个的公式、计算方法和实际用途后面再看模型代码时你会发现很多结构突然就通了。