3. 数据标准化与编码:Z-score标准化、Min-Max归一化、独热编码与标签编码的原理与适用场景
原始数据通常具有不同的量纲、量级和数据类型。如果不经过处理直接输入模型,会导致模型偏向数值较大的特征,或无法处理类别型数据。本章系统讲解两种最常用的数值标准化方法(Z-score、Min-Max)和两种类别编码方法(独热编码、标签编码),并给出明确的适用场景选择依据。
3.1 数值标准化:为什么要消除量纲影响?
当特征的单位或数值范围差异较大时(如年龄 0-100 与收入 0-100000),基于距离或梯度的模型(如 SVM、KNN、神经网络、线性回归)会认为数值大的特征更重要,从而扭曲模型结果。标准化的目标是将不同尺度的特征映射到同一参考系,保留分布信息的同时消除量纲。
核心原则: 树模型(决策树、随机森林、XGBoost)对特征尺度不敏感,通常不需要标准化;但线性模型、距离模型、神经网络必须进行标准化。
3.2 Z-score 标准化(标准化)
原理: 将原始数据转换为均值为 0、标准差为 1 的分布。公式为:
z = (x - μ) / σ
其中 μ 为特征均值,σ 为特征标准差。输出值表示原始值距离均值多少个标准差。
适用场景:
- 数据近似服从正态分布或至少对称分布
- 存在明显异常值时仍能保持稳健(因为标准差会放大异常值的影响,但 Z-score 本身可识别异常)
- 需要保留原始数据的相对排序和距离关系
- PCA、聚类、SVM、线性回归等对数据分布敏感的算法
注意: 如果原始数据分布严重偏态,Z-score 标准化后仍会保留偏态特征,此时建议先做对数变换或 Box-Cox 变换再标准化。
3.3 Min-Max 归一化(归一化)
原理: 将原始数据线性缩放到 [0, 1] 区间(也可缩放到 [-1, 1])。公式为:
x' = (x - min) / (max - min)
其中 min 和 max 分别为特征的最小值和最大值。
适用场景:
- 数据有明确的上下界,且边界值有意义(如像素值 0-255)
- 需要将数据压缩到固定区间,如神经网络输入层要求 [0,1]
- 数据分布较均匀,不存在极端异常值
- 图像处理、信号处理等物理量归一化
注意: Min-Max 对异常值极其敏感。如果测试集中的值超出训练集的 min/max 范围,归一化后的值会超出 [0,1] 区间,导致模型失效。建议先剔除或截断异常值后再使用。
3.4 两种标准化方法的对比
| 对比维度 | Z-score 标准化 | Min-Max 归一化 |
|---|---|---|
| 输出范围 | 无固定范围(通常约 [-3, 3]) | 固定 [0, 1] 或 [-1, 1] |
| 对异常值敏感度 | 中等(异常值会拉大标准差) | 高(异常值会压缩正常值区间) |
| 保留分布形状 | 保留原始分布形状(仅平移缩放) | 保留原始分布形状(仅线性缩放) |
| 适用算法 | SVM、PCA、聚类、线性回归、神经网络 | 神经网络(输入层)、KNN、图像处理 |
| 对新数据的处理 | 使用训练集的 μ 和 σ 计算 | 使用训练集的 min 和 max 计算 |
| 是否需要数据近似正态 | 不强制,但效果更好 | 不需要 |
3.5 类别特征编码:为什么不能直接输入字符串?
绝大多数机器学习算法只能处理数值输入。类别特征(如颜色:红、绿、蓝;城市:北京、上海、广州)需要转换为数值形式。但直接映射为整数(红=1, 绿=2, 蓝=3)会引入虚假的序数关系,导致模型认为“蓝 > 绿 > 红”。因此需要专门的编码方法。
3.6 独热编码(One-Hot Encoding)
原理: 将每个类别值扩展为一个二进制向量,向量长度等于类别总数。只有当前类别对应的位置为 1,其余为 0。
示例:颜色特征有 3 个类别:红、绿、蓝
红 → [1, 0, 0]
绿 → [0, 1, 0]
蓝 → [0, 0, 1]
适用场景:
- 类别之间没有顺序关系(名义变量)
- 类别数量较少(通常 < 20,否则维度爆炸)
- 线性模型、神经网络、KNN 等需要无偏距离度量的算法
实践建议: 使用 pandas.get_dummies() 或 sklearn.preprocessing.OneHotEncoder。注意设置 drop='first' 或 handle_unknown='ignore' 避免多重共线性或测试集出现新类别。
3.7 标签编码(Label Encoding)
原理: 将每个类别映射为一个整数,从 0 开始递增。如:红→0, 绿→1, 蓝→2。
适用场景:
- 类别之间存在明确的序数关系(如:小=0, 中=1, 大=2)
- 树模型(决策树、随机森林、XGBoost、LightGBM)—— 树模型基于分裂点做决策,整数编码不会引入虚假距离
- 类别数量非常多(如城市名、用户ID),独热编码会导致维度灾难
注意: 标签编码 绝对不能 用于线性模型、SVM、神经网络等基于距离或梯度的算法,否则模型会错误地认为类别之间有数值大小关系。例如:红=0, 绿=1, 蓝=2,模型会认为“蓝是红的2倍”。
3.8 两种编码方法的对比
| 对比维度 | 独热编码 | 标签编码 |
|---|---|---|
| 输出维度 | k 维(k 为类别数) | 1 维 |
| 是否引入序数关系 | 否(各维度正交) | 是(整数大小隐含顺序) |
| 适用算法 | 线性模型、神经网络、KNN、SVM | 树模型(决策树、随机森林、GBDT) |
| 类别数量限制 | 建议 < 20,否则维度爆炸 | 无限制,可处理高基数类别 |
| 处理新类别 | 需设置 handle_unknown='ignore' | 需映射到未知类标记(如 -1) |
| 可解释性 | 高(每个维度对应一个类别) | 低(整数无实际含义) |
3.9 实战编码示例(Python)
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler, OneHotEncoder, LabelEncoder
# ===== 数值标准化 =====
data = {'age': [25, 30, 35, 40, 45],
'income': [50000, 60000, 70000, 80000, 100000]}
df = pd.DataFrame(data)
# Z-score 标准化
scaler_z = StandardScaler()
df_z = scaler_z.fit_transform(df)
print("Z-score 标准化结果:\n", df_z)
# Min-Max 归一化
scaler_mm = MinMaxScaler()
df_mm = scaler_mm.fit_transform(df)
print("\nMin-Max 归一化结果:\n", df_mm)
# ===== 类别编码 =====
categories = pd.DataFrame({'color': ['红', '绿', '蓝', '绿', '红']})
# 独热编码
encoder_ohe = OneHotEncoder(sparse_output=False)
encoded_ohe = encoder_ohe.fit_transform(categories)
print("\n独热编码结果:\n", encoded_ohe)
# 标签编码
encoder_le = LabelEncoder()
encoded_le = encoder_le.fit_transform(categories['color'])
print("\n标签编码结果:\n", encoded_le)
3.10 本章要点总结
- Z-score 标准化: 适合分布未知、存在异常值、需要保留距离关系的场景;输出无固定范围。
- Min-Max 归一化: 适合有明确边界、无异常值、需要固定输出区间的场景;对异常值敏感。
- 独热编码: 适合无序类别、类别数少、使用线性/距离模型的场景;避免引入虚假顺序。
- 标签编码: 适合有序类别、类别数多、使用树模型的场景;严禁用于线性模型和神经网络。
- 通用原则: 标准化参数(μ, σ, min, max)和编码映射表必须从训练集计算,并应用到测试集和验证集,避免数据泄露。