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 计算
是否需要数据近似正态 不强制,但效果更好 不需要
数值标准化方法选择流程 原始数值特征 是否有明确物理边界? 是 否 Min-Max 归一化 缩放到 [0,1] 区间 Z-score 标准化 均值为0,标准差为1 适用场景 图像像素、传感器数据 神经网络输入层 适用场景 SVM、PCA、聚类分析 存在异常值的数据

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)和编码映射表必须从训练集计算,并应用到测试集和验证集,避免数据泄露。