详解 scikit-learn 数据预处理工具:从理论到实践
在机器学习工作流程中,数据预处理是连接原始数据与模型训练的关键桥梁。高质量的预处理能够显著提升模型性能,而 scikit-learn 库提供了一套全面且高效的预处理工具集,帮助开发者轻松应对各种数据转换需求。本文将系统介绍 scikit-learn 中 17 种常用预处理工具的原理与实践应用,通过实例代码展示其具体用法。
数据预处理的重要性
现实世界中的原始数据往往存在各种 "缺陷":数值特征量纲不一、类别特征非数值化、存在缺失值、特征分布不符合模型假设等。这些问题会导致模型收敛困难、预测偏差甚至失效。数据预处理通过标准化、编码、转换等操作,将原始数据转化为适合模型处理的形式,主要体现在以下几个方面:
- 消除量纲影响,使不同特征具有可比性
- 将非数值信息转化为模型可理解的数值形式
- 处理缺失值,提高数据完整性
- 优化特征分布,适应模型假设
- 创造新特征,增强数据表达能力
实验数据准备
为全面展示各类预处理工具的效果,我们构造了包含多种数据类型的异构数据集:
import numpy as np
import pandas as pddata = {'num': [10, 20, 30], # 整数特征'cat': ['low', 'medium', 'high'], # 类别特征'int': [2, 5, 8], # 整数特征'float': [0.5, 0.8, 1.2], # 浮点特征'multi_label': [['red', 'blue'], ['blue'], ['green']], # 多标签特征'missing': [3, 5, None] # 含缺失值特征
}
df = pd.DataFrame(data)
数值特征预处理工具
数值特征是机器学习中最常见的数据类型,scikit-learn 提供了多种工具用于数值特征的标准化、缩放和转换。
1. preprocessing.scale()
scale()
函数用于对数据进行标准化处理,将特征转换为均值为 0、标准差为 1 的分布,计算公式为:
(x - mean(x)) / std(x)
from sklearn.preprocessing import scale
scaled_data = scale(df[['num', 'int', 'float']])
该函数直接返回标准化后的数组,适用于快速预处理,但不支持后续对新数据的转换(无transform
方法)。
2. MinMaxScaler
MinMaxScaler 将特征缩放到指定范围(默认 [0,1]),计算公式为:
(x - min(x)) / (max(x) - min(x))
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
minmax_data = scaler.fit_transform(df[['num', 'int', 'float']])
这种缩放方式对异常值敏感,适用于已知数据边界的场景,如像素值(0-255)处理。
3. StandardScaler
StandardScaler 与scale()
功能类似,都是进行标准化处理,但提供了完整的fit-transform
接口,便于管道化操作和新数据处理:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
std_scaled = scaler.fit_transform(df[['num', 'int', 'float']])
标准化后的数据均值为 0,标准差为 1,使不同量纲的特征具有可比性,是最常用的缩放方法之一。
4. MaxAbsScaler
MaxAbsScaler 通过特征的最大绝对值进行缩放,计算公式为:x / max(abs(x))
from sklearn.preprocessing import MaxAbsScaler
scaler = MaxAbsScaler()
maxabs_data = scaler.fit_transform(df[['num', 'int', 'float']])
缩放后的数据范围在 [-1, 1] 之间,适用于稀疏数据,因为它不会改变数据的稀疏结构。
5. RobustScaler
RobustScaler 对异常值具有较强的鲁棒性,使用中位数和四分位距进行缩放:
(x - median) / (Q3 - Q1)
from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
robust_data = scaler.fit_transform(df[['num', 'int', 'float']])
当数据中存在异常值时,RobustScaler 比 StandardScaler 表现更好,常见于金融、风控等领域。
6. QuantileTransformer
QuantileTransformer 通过将数据映射到均匀分布或正态分布来转换特征,能够有效处理偏态分布数据:
from sklearn.preprocessing import QuantileTransformer
scaler = QuantileTransformer()
quantile_data = scaler.fit_transform(df[['num', 'int', 'float']])
这种方法对异常值不敏感,适用于需要将数据转换为特定分布的场景,如 Gaussian 过程模型。
7. PowerTransformer
PowerTransformer 应用幂变换使数据更接近正态分布,支持 Box-Cox 和 Yeo-Johnson 两种变换:
from sklearn.preprocessing import PowerTransformer
scaler = PowerTransformer()
power_data = scaler.fit_transform(df[['num', 'int', 'float']])
幂变换特别适用于处理偏态分布的数据,如收入、房价等具有长尾分布特征的数据。
8. Normalizer
Normalizer 对样本进行归一化,使每个样本的 L1 或 L2 范数为 1,计算公式为:
- L1 范数:
x / sum(abs(x))
- L2 范数:
x / sqrt(sum(x^2))
from sklearn.preprocessing import Normalizer scaler = Normalizer(norm='l2') normalized_data = scaler.fit_transform(df[['num', 'int', 'float']])
归一化适用于需要关注样本向量方向而非大小的场景,如文本分类(词袋模型)、推荐系统等。
类别特征编码工具
机器学习模型通常要求输入为数值形式,因此需要将类别特征转换为数值表示,scikit-learn 提供了多种类别编码工具。
9. OrdinalEncoder
OrdinalEncoder 将类别特征转换为有序整数,适用于具有内在顺序的类别特征(序数特征):
from sklearn.preprocessing import OrdinalEncoder encoder = OrdinalEncoder(categories=[['low', 'medium', 'high']]) df['cat_encoded'] = encoder.fit_transform(df[['cat']])
使用时需注意指定
categories
参数以确保正确的顺序映射,如本例中将 'low'→0,'medium'→1,'high'→2。10. LabelEncoder
LabelEncoder 与 OrdinalEncoder 功能类似,但适用于目标变量(y)的编码:
from sklearn.preprocessing import LabelEncoder encoder = LabelEncoder() df['cat_label_encoded'] = encoder.fit_transform(df['cat'])
注意:不推荐使用 LabelEncoder 对特征进行编码,尤其是无序类别特征,可能会引入错误的顺序关系。
11. MultiLabelBinarizer
MultiLabelBinarizer 用于处理多标签特征,将每个样本的多个标签转换为二进制指示向量:
from sklearn.preprocessing import MultiLabelBinarizer mlb = MultiLabelBinarizer(classes=['red', 'blue', 'green']) multi_label_df = pd.DataFrame(mlb.fit_transform(df['multi_label']),columns=mlb.classes_,index=df.index ) df = pd.concat([df, multi_label_df], axis=1)
这种编码方式适用于一个样本可能属于多个类别的场景,如文本的多主题分类。
12. OneHotEncoder
OneHotEncoder 将无序类别特征转换为独热编码(one-hot encoding),每个类别生成一个二进制特征:
from sklearn.preprocessing import OneHotEncoder encoder = OneHotEncoder(sparse=False) onehot_data = encoder.fit_transform(df[['cat']]) onehot_df = pd.DataFrame(onehot_data, columns=encoder.get_feature_names_out(['cat']))
独热编码避免了为无序类别引入虚假顺序关系的问题,但会增加特征维度(维度灾难),适用于类别数量较少的场景。
其他预处理工具
除了上述主要用于数值和类别特征的工具外,scikit-learn 还提供了一些处理特殊需求的预处理工具。
13. KBinsDiscretizer
KBinsDiscretizer 将连续特征离散化为有限数量的区间( bins ):
from sklearn.preprocessing import KBinsDiscretizer discretizer = KBinsDiscretizer(n_bins=3, encode='ordinal') binned_data = discretizer.fit_transform(df[['num']]) df['binned'] = binned_data
离散化可以捕捉特征的非线性关系,降低模型对异常值的敏感度,常见于决策树类模型的预处理。
14. FunctionTransformer
FunctionTransformer 允许用户自定义转换函数,灵活处理各种特殊转换需求:
from sklearn.preprocessing import FunctionTransformer def custom_func(x):return x + 1 transformer = FunctionTransformer(custom_func) custom_data = transformer.transform(df[['num', 'int']])
这种方式扩展性强,可用于实现对数转换、指数转换、倒数转换等任意自定义操作。
15. Binarizer
Binarizer 根据阈值将连续特征转换为二进制特征(0 或 1):
from sklearn.preprocessing import Binarizer binarizer = Binarizer(threshold=20) df['num_binarized'] = binarizer.fit_transform(df[['num']])
二值化适用于需要将特征简化为 "是 / 否" 或 "有 / 无" 的场景,如将收入划分为高 / 低两个等级。
16. PolynomialFeatures
PolynomialFeatures 用于生成多项式特征和交互特征,增强模型对非线性关系的捕捉能力:
from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(degree=2, include_bias=False) poly_features = poly.fit_transform(df[['num', 'int']]) poly_df = pd.DataFrame(poly_features, columns=poly.get_feature_names_out(['num', 'int']))
对于 degree=2,会生成原始特征(num, int)、平方特征(num², int²)和交互特征(num×int),适用于线性模型处理非线性问题。
17. SimpleImputer(缺失值处理)
SimpleImputer 用于处理缺失值,支持多种填充策略(均值、中位数、众数等):
from sklearn.impute import SimpleImputer imputer_new = SimpleImputer(strategy='mean') df['missing_imputed'] = imputer_new.fit_transform(df[['missing']])
缺失值处理是数据预处理的重要步骤,合理的填充策略能够减少信息损失,常见的填充策略包括统计量填充、模型预测填充等。
预处理工具选择指南
面对众多预处理工具,如何选择合适的工具是实际应用中的关键问题,以下是一些选择建议:
- 数值缩放:优先考虑 StandardScaler;数据含异常值时用 RobustScaler;需要固定范围时用 MinMaxScaler
- 类别编码:有序类别用 OrdinalEncoder;无序类别用 OneHotEncoder;多标签用 MultiLabelBinarizer
- 分布转换:偏态分布用 PowerTransformer;需要特定分布用 QuantileTransformer
-
实际应用中,预处理通常不是单一操作,而是多种工具的组合,scikit-learn 的 Pipeline 工具可以将多个预处理步骤和模型训练整合为一个流程,提高代码的可维护性和可复现性。
- 特征创建:需要非线性特征用 PolynomialFeatures;自定义转换用 FunctionTransformer
- 缺失值:根据数据类型选择合适的填充策略,数值型常用均值 / 中位数,类别型常用众数