3. 数据变换技术:标准化、归一化与非线性变换
数据变换是特征工程中最基础也最关键的环节之一。原始特征往往具有不同的量纲、分布形态和异常值敏感性,直接输入模型会导致权重失衡、收敛缓慢或预测偏差。本节系统梳理五种核心变换技术:Z-score 标准化、Min-Max 归一化、RobustScaler、Log 变换以及Box-Cox / Yeo-Johnson 幂变换,并给出选型决策框架。
3.1 标准化(Z-score)
Z-score 标准化将特征转换为均值为 0、标准差为 1 的分布,适用于特征近似正态分布且存在少量异常值的场景。公式如下:
z = (x - μ) / σ
其中 μ 为特征均值,σ 为标准差。变换后的数据无量纲,保留原始分布形状。
| 属性 | 说明 |
|---|---|
| 输出范围 | 无固定边界,理论上 (−∞, +∞) |
| 对异常值敏感度 | 中等偏高(均值和标准差受异常值影响) |
| 适用模型 | SVM、线性回归、PCA、K-Means、神经网络 |
| 要求数据分布 | 近似正态分布效果最佳 |
3.2 归一化(Min-Max)
Min-Max 归一化将特征线性缩放到 [0, 1] 区间(也可指定其他范围如 [-1, 1])。公式为:
x_scaled = (x - x_min) / (x_max - x_min)
该变换完全由数据的最大值和最小值决定,对异常值极为敏感。
| 属性 | 说明 |
|---|---|
| 输出范围 | 固定 [0, 1](或自定义区间) |
| 对异常值敏感度 | 高(单个极端值会压缩正常值的缩放比例) |
| 适用模型 | 神经网络、图像处理、距离度量模型(KNN) |
| 要求数据分布 | 无特定要求,但需确保无极端异常值 |
3.3 RobustScaler
RobustScaler 使用中位数和四分位距(IQR)代替均值和标准差,对异常值具有天然的鲁棒性。公式为:
x_scaled = (x - median) / IQR
其中 IQR = Q3 − Q1(第 75 百分位数 − 第 25 百分位数)。
| 属性 | 说明 |
|---|---|
| 输出范围 | 无固定边界,但受 IQR 约束 |
| 对异常值敏感度 | 低(中位数和 IQR 不受极端值影响) |
| 适用模型 | 含异常值的回归、异常检测、树模型前的预处理 |
| 要求数据分布 | 无特定要求,尤其适合含离群点的数据 |
3.4 非线性变换:Log、Box-Cox、Yeo-Johnson
当特征呈现右偏(长尾)、指数增长或方差随均值增大时,线性缩放无法改善分布形态,必须引入非线性变换。
3.4.1 Log 变换
最常用的非线性变换,适用于正数特征(x > 0)。公式:
x_transformed = log(x + c)
其中 c 为偏移常数(通常取 1,避免 log(0) 问题)。Log 变换能有效压缩右偏分布,使数据更接近正态。
3.4.2 Box-Cox 变换
Box-Cox 是带参数 λ 的幂变换族,自动搜索最优变换参数。要求数据严格为正(x > 0)。公式:
y(λ) = (x^λ - 1) / λ, λ ≠ 0
y(λ) = log(x), λ = 0
通过极大似然估计自动选择 λ,使变换后的数据最接近正态分布。
3.4.3 Yeo-Johnson 变换
Yeo-Johnson 是 Box-Cox 的扩展,支持零和负值数据,无需偏移常数。公式分段定义,核心思想与 Box-Cox 一致,但适用范围更广。
| 变换方法 | 数据要求 | 自动寻参 | 典型应用场景 |
|---|---|---|---|
| Log 变换 | x > 0(可加偏移) | 否 | 收入、价格、点击量、生物计数 |
| Box-Cox | x > 0 | 是(λ 自动优化) | 金融指标、物理测量、正数连续特征 |
| Yeo-Johnson | 任意实数 | 是(λ 自动优化) | 含负值的特征、评分数据、差值特征 |
3.5 变换技术选型流程
下图总结了从原始特征到变换后特征的完整决策路径:
3.6 代码实现示例
以下代码展示五种变换在 Python scikit-learn 中的标准用法:
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.preprocessing import PowerTransformer
# 示例数据:右偏特征 + 异常值
data = pd.DataFrame({
'income': [3000, 4500, 5200, 7800, 12000, 25000, 35000, 500, 6000, 150000],
'score': [-5, -2, 0, 3, 7, 10, 15, -8, 1, 20]
})
# 1. Z-score 标准化
scaler_z = StandardScaler()
data['income_z'] = scaler_z.fit_transform(data[['income']])
# 2. Min-Max 归一化
scaler_mm = MinMaxScaler()
data['income_mm'] = scaler_mm.fit_transform(data[['income']])
# 3. RobustScaler
scaler_rb = RobustScaler()
data['income_rb'] = scaler_rb.fit_transform(data[['income']])
# 4. Box-Cox 变换(自动寻参)
pt_boxcox = PowerTransformer(method='box-cox')
data['income_bc'] = pt_boxcox.fit_transform(data[['income']])
print(f"Box-Cox 最优 λ: {pt_boxcox.lambdas_[0]:.4f}")
# 5. Yeo-Johnson 变换(支持负值)
pt_yeo = PowerTransformer(method='yeo-johnson')
data['score_yj'] = pt_yeo.fit_transform(data[['score']])
print(f"Yeo-Johnson 最优 λ: {pt_yeo.lambdas_[0]:.4f}")
print(data.round(4))
3.7 变换效果对比总表
| 变换方法 | 输出范围 | 异常值鲁棒性 | 分布形态改变 | 自动寻参 | 推荐场景 |
|---|---|---|---|---|---|
| Z-score | 无界 | 中 | 否 | 否 | 正态分布、无异常值 |
| Min-Max | [0, 1] | 低 | 否 | 否 | 神经网络、有界特征 |
| RobustScaler | 无界 | 高 | 否 | 否 | 含异常值的连续特征 |
| Log 变换 | 无界 | 高 | 是(压缩右偏) | 否 | 正数长尾特征 |
| Box-Cox | 无界 | 中 | 是(自动优化) | 是 | 正数特征、正态化需求 |
| Yeo-Johnson | 无界 | 中 | 是(自动优化) | 是 | 含负值的任意特征 |