4. 数值型特征标准化与归一化归纳总结
说到特征工程里的标准化和归一化,我估计不少同学第一反应就是“把数据缩到0~1之间”。嗯,其实没那么简单。我刚开始做信用评分模型时,也犯过这种“一刀切”的错。后来被坏特征狠狠教训过一次,才彻底搞明白这两兄弟到底怎么用。
4.1 标准化 vs 归一化:本质区别
先说结论:标准化(Standardization)和归一化(Normalization)都做“缩放”,但目标不同。
- 标准化:把数据转换成均值为0、标准差为1的分布。说白了就是让数据“中心化”并“压扁”,保留原始分布的形态(偏态、峰度等)。
- 归一化:把数据线性压缩到某个固定区间(比如[0,1]或[-1,1])。它会改变原始分布的形状——因为缩放范围是固定的。
我在一次信贷审批模型项目中,用了Min-Max归一化对收入做处理。结果模型在测试集上泛化很差——因为新来的客户收入分布跟训练集不同,但归一化硬生生把极值压到一起,导致模型误判。后来换成标准化,稳定性好多了。
| 方法 | 公式 | 输出范围 | 受异常值影响 | 适合场景 |
|---|---|---|---|---|
| Z-score 标准化 | z = (x - μ) / σ | ≈[-3,3](理论无界) | 中等(均值/标准差被极端值拉动) | 数据近似正态、需要保留分布形态 |
| Min-Max 归一化 | z = (x - min) / (max - min) | [0,1] | 极大(极值决定范围) | 分布固定、无异常值的场景 |
| MaxAbs 归一化 | z = x / |max| | [-1,1] | 大(受最大绝对值控制) | 稀疏数据、符号有意义的特征 |
| Robust 标准化 | z = (x - median) / IQR | ≈[-3,3] | 小(用中位数和四分位距) | 数据存在较多异常值 |
4.2 信用评分中的实战选择
信用评分特征里,最常见的数值型特征有:年龄、收入、贷款金额、历史逾期次数、信用额度使用率等。这些特征的量纲差异巨大——收入可能是几千到几十万,逾期次数最多几十次。如果不做缩放,模型会被大数值特征主导。
我个人习惯按以下三步判断:
- 先看分布:画个直方图或箱线图。如果有明显异常值(比如收入出现极端高的富豪),优先用Robust标准化。
- 再看模型:树模型(GBDT、XGBoost)对缩放不敏感,可以不做。但线性模型、SVM、KNN、PCA 必须做。
- 最后看业务含义:比如“信用额度使用率”本身就在[0,1]区间,归一化后依然是[0,1],标准化反而会变成有正有负——解释性变差。这种情况下归一化更自然。
4.3 代码实现范例
下面给出sklearn中的四种方法,以及一个简单的对比输出。注意,代码里我故意混入一些异常值——模拟真实信用数据。
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, MaxAbsScaler, RobustScaler
# 模拟信用评分特征:年龄、收入、逾期次数、使用率
np.random.seed(42)
ages = np.random.randint(22, 65, 200)
incomes = np.random.normal(8000, 3000, 200)
overdues = np.random.poisson(2, 200)
util_rate = np.random.beta(2, 5, 200)
# 故意加入异常值
incomes[0] = 50000
overdues[5] = 50
data = pd.DataFrame({
'age': ages,
'income': incomes,
'overdue': overdues,
'util_rate': util_rate
})
# 同时应用四种缩放
scalers = {
'StandardScaler': StandardScaler(),
'MinMaxScaler': MinMaxScaler(),
'MaxAbsScaler': MaxAbsScaler(),
'RobustScaler': RobustScaler()
}
results = []
for name, scaler in scalers.items():
scaled = scaler.fit_transform(data)
results.append({
'方法': name,
'income_min': scaled[:, 1].min(),
'income_max': scaled[:, 1].max(),
'income_mean': round(scaled[:, 1].mean(), 4)
})
pd.DataFrame(results).round(4)
你看,同样一个收入特征(异常值50000),MinMaxScaler会把大部分数据压缩到0~0.1之间,而StandardScaler的均值依然接近0,RobustScaler受异常干扰最小。
4.4 避坑指南:标准化后还能解释特征吗?
我曾经犯过一个错:标准化之后,把特征直接丢进线性回归,然后拿着系数说“年龄每增加1个单位,违约概率增加0.02”——实际上标准化后的“1个单位”是1个标准差,不是1岁。所以标准化后的模型系数不能直接用在业务解释上。如果你需要解释性,要么用原始单位做标准化前的模型,要么用归一化(保留原尺度)后再除以原始标准差。
4.5 一张图理清所有关系
下面这张SVG图总结了四种缩放方法对同一组数据(含异常值)的影响。我画成了分布变化示意图,方便你在脑子里建立直观印象。
4.6 标准化与归一化的统一框架
其实所有方法都可以看作一个线性变换:new_x = (x - loc) / scale。区别只在于loc和scale用什么统计量。
| 方法 | loc | scale | 抗异常 |
|---|---|---|---|
| StandardScaler | mean | std | 弱 |
| MinMaxScaler | min | max - min | 极弱 |
| MaxAbsScaler | 0 | |max| | 弱 |
| RobustScaler | median | IQR | 强 |
理解了这一点,你甚至可以自己造一个缩放器——比如用分位数间隔或极值截断后再缩放。信用评分中我就曾用过“截断99%分位数后做Min-Max归一化”,效果比纯Robust还好。不过这属于高级技巧,后面讲异常值处理时会再展开。
fit_transform用在训练集,transform用在测试/新数据。很多新手写成fit_transform(test),模型会学到未来信息。我当年就是这么被导师骂的……
好了,这一章的核心就是:不要盲目用任一方法。先看分布,再看模型,最后考虑业务解释。如果你能把这个流程内化成肌肉记忆,信用评分特征筛选的第一步就稳了。