京公网安备 11010802034615号
经营许可证编号:京B2-20210330
拿到一份数据,各列的量纲往往完全不同:年龄单位是"岁"(约 20~60),收入单位是"元"(几千到几万),满意度是 1~5 分,比率是 0~1。如果直接把这几列扔进距离类算法、聚类、PCA、神经网络,数值大的列会天然主导结果——收入波动一个零头,就盖过了满意度全部的差异。
标准化解决的就是这个问题:把不同量纲的变量放到同一把尺子上,让每个变量在分析中拥有对等的话语权。
主流的标准化方法有三类:
| 方法 | 公式 | 输出范围 | 适用 |
|---|---|---|---|
| Z-score 标准化 | 无固定边界,约 -3~3 | 近似正态分布的数据 | |
| Min-Max 归一化 | 严格 [0, 1] | 有明确边界、需要固定区间 | |
| 小数定标 | 随数据浮动 | 快速粗略处理 |
其中 Z-score 应用最广,原因后面会讲到:它不仅仅是一个缩放工具,还天然附带了一套异常检测机制。
其中 是均值, 是标准差。这个式子做的是两件事:
变换后,整个数据集均值 = 0,标准差 = 1。
一个样本的 Z-score,含义是:这个值距离均值有多少个标准差。
这才是 Z-score 最有价值的解读方式——它把"绝对值"翻译成了"相对位置"。120 分的考试成绩好不好?看它在全班里是均值以上几个标准差,比看绝对分数有意义得多。
如果数据服从正态分布,经验法则(68-95-99.7 法则)告诉我们:
| 区间 | 覆盖比例 | 落在区间外的概率 |
|---|---|---|
| 68.27% | 31.73% | |
| 95.45% | 4.55% | |
| 99.73% | 0.27% |
也就是说,正态分布下只有 0.27% 的数据会落在 ±3σ 之外。反过来讲,如果一个值 z = 4.5,意味着在正态假设下出现这种情况的概率大约是百万分之三——这基本不可能是正常波动,更可能是异常值。
这就是3σ 法则(拉依达准则)的来源。
import numpy as np
import pandas as pd
# 1. 计算均值与标准差
mu = df['amount'].mean()
sigma = df['amount'].std(ddof=1)
# 2. 计算 Z-score
df['z_amount'] = (df['amount'] - mu) / sigma
# 3. 标记异常
df['is_outlier'] = df['z_amount'].abs() > 3
# 4. 查看异常样本
print(df[df['is_outlier']])
单变量逐个检测只能发现"某一列极端"的样本。如果异常体现在多个变量的组合偏离(单看每一列都正常,但整体组合很怪),就要用马氏距离(Mahalanobis Distance):
其中 是协方差矩阵。 服从自由度为 p 的卡方分布,可以用 分位数确定阈值。这是 Z-score 在多维空间的推广。
from scipy.spatial.distance import mahalanobis
from scipy.stats import chi2
cov = np.cov(X.T)
inv_cov = np.linalg.inv(cov)
d2 = [mahalanobis(x, mean_vec, inv_cov)**2 for x in X]
threshold = chi2.ppf(0.997, df=X.shape[1])
这是 Z-score 异常检测最容易被忽视的问题。
Z-score 的均值和标准差,都是用全部数据(包含异常值)算出来的。当数据里存在极端异常值时:
举个具体例子。假设正常数据是 [9, 10, 11, 10, 9, 10, 11],混入一个 100:
data = np.array([9, 10, 11, 10, 9, 10, 11, 100])
z = (data - data.mean()) / data.std(ddof=1)
print(z) # [ -0.37, -0.30, -0.22, -0.30, -0.37, -0.30, -0.22, 2.36 ]
异常值 100 的 z 只有 2.36,没超过 3,被判为正常。而不含异常值时:
data2 = np.array([9, 10, 11, 10, 9, 10, 11])
z2 = (data2 - data2.mean()) / data2.std(ddof=1)
同样的 100 在这种分布里应该是 z = 30 以上的极端值。异常值把尺子撑变形了,反而藏住了自己。
这就是统计上说的"掩蔽效应"(Masking Effect)。
多个异常值还可能互相掩护。两个方向相反的大异常值,一个让均值偏高、一个让均值偏低,同时把标准差撑得很大,结果两个都检测不出来。
核心思路:把均值和标准差换成不受异常值影响的稳健统计量——中位数和 MAD(Median Absolute Deviation)。
0.6745 这个系数是为了让 MAD 在正态分布下与标准差保持一致的尺度。
from scipy.stats import median_abs_deviation
med = np.median(data)
mad = median_abs_deviation(data, scale='normal')
mz = (data - med) / mad
outliers = data[np.abs(mz) > 3.5] # 常用阈值 3.5
阈值为什么是 3.5 而不是 3:Iglewicz 和 Hoaglin 的建议值,因为 MAD 的分布比标准差更"瘦",需要略微放宽。
MAD 的崩溃点是 50%,也就是接近一半的数据是异常值时,它依然稳定;而标准差的崩溃点是 0%——一个异常值就能毁掉它。
完全不依赖均值和标准差,只用四分位数:
其中 。这是箱线图"须线"的判定逻辑,比 3σ 更不受极端值干扰。
q1, q3 = np.percentile(data, [25, 75])
iqr = q3 - q1
lower, upper = q1 - 1.5*iqr, q3 + 1.5*iqr
补充:箱线图须线的系数在不同软件里不一样。Tukey 原始定义用 1.5×IQR,而 Excel 的箱线图实际画到的是 1.5×IQR 之外的最小/最大观测值,SPSS 也有自己的实现差异,比对时要注意。
”
不删除异常值,而是把它们"压"到边界值:
from scipy.stats.mstats import winsorize
data_w = winsorize(data, limits=[0.05, 0.05]) # 两端各截 5%
适用:样本量小、删不起数据;或者异常值是真实存在只是极端的情况(如头部用户的巨额消费)。
对于右偏严重的金额、流量类数据(少数大值拉长尾巴),取对数能先让分布接近正态,再用 Z-score 就合理得多:
data_log = np.log1p(data) # log(1+x),避免 0 值
把连续值切成分箱,从根上消除异常值的影响。适合用于建模特征而非原始分析。
检测只是第一步,处理方式取决于异常值的性质:
| 处理方式 | 做法 | 适用场景 | 风险 |
|---|---|---|---|
| 直接删除 | 剔除异常样本 | 明显是录入错误、测量失误 | 样本量减少;可能删掉真实业务信号 |
| 缩尾处理 | 压到边界值 | 异常值真实存在但极端 | 改变分布形态 |
| 视为缺失 | 置为 NaN 后填充 | 不确定异常来源 | 填充可能引入新偏差 |
| 保留并标记 | 加标志位单独建模 | 异常本身有业务价值(欺诈、故障) | 模型需支持标志特征 |
| 分组建模 | 正常/异常分开建 | 两类样本机制不同 | 增加建模复杂度 |
关键判断问题:这个"异常"是错误,还是真实?
现实中大量分析师犯的错是:一律按"异常即脏数据"处理,把最有业务价值的样本清掉了。
做机器学习时,一个必须遵守的规则:用训练集的均值和标准差,去标准化测试集和新数据,不能用全量数据算参数。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 在训练集上 fit
X_test_scaled = scaler.transform(X_test) # 用训练集参数 transform
如果对全体数据先算均值方差再切分,测试集的信息就泄露到训练过程里了,这叫数据泄露(Data Leakage),会让模型评估虚高。
一个完整的流程应该是这样的:
import numpy as np
import pandas as pd
from scipy.stats import median_abs_deviation
def detect_outliers(series, method='robust', threshold=3.5):
"""多方法异常检测"""
s = series.dropna()
if method == 'zscore':
mu, sigma = s.mean(), s.std(ddof=1)
z = (s - mu) / sigma
return s[np.abs(z) > 3]
elif method == 'robust':
med = s.median()
mad = median_abs_deviation(s, scale='normal')
mz = (s - med) / mad
return s[np.abs(mz) > threshold]
elif method == 'iqr':
q1, q3 = s.quantile([0.25, 0.75])
iqr = q3 - q1
lo, hi = q1 - 1.5*iqr, q3 + 1.5*iqr
return s[(s < lo) | (s > hi)]
# 使用
out_z = detect_outliers(df['amount'], 'zscore')
out_r = detect_outliers(df['amount'], 'robust')
out_i = detect_outliers(df['amount'], 'iqr')
print(f"Z-score 检出:{len(out_z)} 个")
print(f"稳健Z 检出:{len(out_r)} 个")
print(f"IQR 检出:{len(out_i)} 个")
实践中建议三种方法交叉验证:三种都判为异常的点,基本可以确认是真异常;只有一种判异常的,需要人工复核业务含义。
Z-score 标准化和异常检测,本质是同一个公式的两种用途:
但必须清楚它的局限:Z-score 依赖均值和标准差,这两个统计量本身对异常值极度敏感。当数据被污染时,异常值会把尺子撑变形,把自己藏起来——这就是掩蔽效应。
工程上更稳妥的做法是:
方法本身不难,难的是知道什么时候不该用它。

一、为什么数据要先标准化 拿到一份数据,各列的量纲往往完全不同:年龄单位是"岁"(约 20~60),收入单位是"元"(几千到几万) ...
2026-11-06一、为什么 Python 成了统计分析的主流工具 十年前做统计分析,主流选择是 SPSS、SAS、Stata。现在越来越多的研究者、分析师转向 ...
2026-11-06核心资源推荐 CDA教材(2025):https://edu.cda.cn/goods/show/3151CDA模拟题(2025):https://edu.cda.cn/goods/show/2845CD ...
2026-11-06核心资源推荐 CDA教材(2025):https://edu.cda.cn/goods/show/3151CDA模拟题(2025):https://edu.cda.cn/goods/show/2845CD ...
2026-11-06“大学生必备证书有哪些”最容易被答成一张越长越好的清单。但校招筛选的真实逻辑是:证书要对应你投的岗位任务,并且在校期间确 ...
2026-11-05大学期间能报的证书,先别急着看“含金量榜单”。更实用的第一步是问:我现在这个身份、这个学历,符合报考条件吗? 很多证书宣 ...
2026-11-05大学期间能考的证书很多,但真正需要先回答的是两个问题:当前有没有报考资格,以及这张证书对应什么岗位任务。 前者决定你能不 ...
2026-11-05先把结论说清楚:真正“只有在校大学生能考、毕业就彻底没资格”的证书数量不多,主要集中在语言类考试的部分专项、面向高校学生 ...
2026-11-05上班族问“考什么证书有用”,真正要解决的不是找一张“最值钱”的证,而是判断哪张证能嵌进你现有的岗位任务。同样一张证书,做 ...
2026-11-05职称证书不是统一的考试项目。同样“考职称”,经济、会计、统计、审计、软考走全国统一考试,工程、教师、卫生等系列多数走评审 ...
2026-11-0533岁选证书,最怕两件事:一是被“适合女生”的清单带着走,考完发现岗位用不上;二是投入大半年,报名时才发现学历、专业或工作 ...
2026-11-05“女生容易考的证书”这个问题,真正难的不是找一份名单,而是判断“容易”到底指什么。报名条件宽松、考试通过率高、拿证后能找 ...
2026-11-05“女生适合考什么证书”这类搜索,背后往往是同一个困惑:网上榜单太多,口径却说不清楚。有人把培训证书和职业资格混在一起排, ...
2026-11-05先把结论说清楚:没有一张证书对所有人都“又好考又实用”。同一个证,对在校生可能报名门槛都过不了,对有三年工作经验的人却只 ...
2026-11-05“考证书有哪些”这个问题,如果只想要一份名单,网上能搜到成百上千个。但真正有用的答案不是“有哪些”,而是“它们分别是什么 ...
2026-11-05“考什么证好一点”这句话,十个人问可能有十个意思。有人想问哪个证容易过,有人想知道哪个证找工作管用,还有人关心哪个证长期 ...
2026-11-05“考哪些证书最吃香”很难用一张榜单回答。同一张证书,在有的岗位是硬门槛,在另一些岗位只是加分项;对在校生和在职者的价值也 ...
2026-11-05家庭主妇能考的证书不少,但真正值得花时间的,不是“哪个证热门”,而是先确认你当前能不能报,再按每周可投入时间和未来出口缩 ...
2026-11-05“国家认证的职业技能证书”并不是某一本证书的正式名称,而是一句被大量使用的宣传口径。它可能指向人社部门的国家职业资格、备 ...
2026-11-05工程领域的证书名目确实多,但乱的不是证书本身,而是很多人把不同制度属性的证书放在一个篮子里比较。有人拿培训结业证去对标注 ...
2026-11-05