Scikit-learn 的 preprocessing 模块主要用于把原始特征转换成更适合模型使用的数据表示。它提供了标准化、归一化、类别编码、特征变换、特征扩展等工具是 Scikit-learn 建模流程中的重要组成部分。Scikit-learn 官方说明中也强调sklearn.preprocessing 提供的工具函数和转换器类目的就是把原始特征向量变成更适合下游估计器使用的表示。需要注意的是缺失值填补主要位于 sklearn.impute 模块而不是 sklearn.preprocessing 模块但在实际建模流程中它通常与预处理一起使用因此本文也会一并说明。一、认识 preprocessing 模块在机器学习中模型并不是直接处理现实对象而是处理经过整理后的数据。现实数据往往并不规整例如不同特征的取值范围差异很大有些列是文字类别有些位置还可能存在缺失值。这样的数据如果直接输入模型可能影响训练效果甚至导致模型无法运行。Scikit-learn 的 preprocessing 模块主要用于在模型训练之前对特征数据进行转换使数据更适合模型学习。它不负责训练模型而是负责整理输入数据。可以简单理解为preprocessing 模块解决的是“数据怎样交给模型更合适”的问题。常见预处理任务包括• 标准化让不同特征具有相近的尺度• 归一化把数据缩放到指定范围内• 类别编码把文字类别转换为数值表示• 特征变换对原始特征进行数学变换• 特征扩展构造新的组合特征需要注意的是预处理对象也遵循 Scikit-learn 的统一接口。fit() 表示从数据中学习变换所需的信息例如均值、标准差或类别集合transform() 表示按照已经学到的规则转换数据fit_transform() 表示先学习再转换。二、标准化StandardScaler1、标准化的基本含义标准化Standardization是最常见的数据预处理方法之一。它的目标是把特征转换成均值接近 0、标准差接近 1 的形式。Scikit-learn 中常用 StandardScaler 完成标准化。官方文档说明StandardScaler 通过去除均值并缩放到单位方差来标准化特征。标准化可以表示为其中• x 表示原始特征值• μ 表示该特征在训练集中的均值• σ 表示该特征在训练集中的标准差• z 表示标准化后的特征值标准化之后不同特征的数值尺度会更接近便于模型学习。2、StandardScaler 的基本用法from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train)X_test_scaled scaler.transform(X_test)这里需要注意• 对训练集使用 fit_transform()• 对测试集只使用 transform()• 不应在测试集上重新 fit()原因是测试集应该模拟模型未来面对的新数据。预处理参数应当只从训练集中学习而不应提前使用测试集信息。3、StandardScaler 适合哪些场景StandardScaler 常用于• 线性回归、岭回归、逻辑回归• 支持向量机• K 近邻• PCA• 神经网络相关模型它尤其适合数据大致呈连续数值型分布并且模型对特征尺度较敏感的场景。不过标准化并不能解决所有问题。如果数据中存在极端异常值均值和标准差会受到明显影响此时可以考虑使用更稳健的缩放方法例如 RobustScaler。三、归一化与缩放1、归一化MinMaxScaler归一化Normalization通常是指把数据缩放到某个固定范围内例如 0 到 1。Scikit-learn 中常用 MinMaxScaler 完成这种变换。官方文档说明MinMaxScaler 会对每个特征单独缩放和平移使其落在给定范围内默认通常是 0 到 1。其基本思想可以表示为其中• x 表示原始特征值• x_min 表示该特征在训练集中的最小值• x_max 表示该特征在训练集中的最大值• x_scaled 表示缩放后的值基本用法如下from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler() X_train_scaled scaler.fit_transform(X_train)X_test_scaled scaler.transform(X_test)MinMaxScaler 的特点是结果范围清晰适合需要固定输入范围的场景。但它对异常值比较敏感因为最大值和最小值可能被极端样本拉开。2、MaxAbsScalerMaxAbsScaler 会按照每个特征的最大绝对值进行缩放使特征值通常落在 −1 到 1 之间。它适合处理已经以 0 为中心或者希望保留稀疏数据结构的场景。例如from sklearn.preprocessing import MaxAbsScaler scaler MaxAbsScaler() X_train_scaled scaler.fit_transform(X_train)X_test_scaled scaler.transform(X_test)可以简单理解为• MinMaxScaler 关注最小值和最大值• MaxAbsScaler 关注最大绝对值• 二者都属于数值缩放方法3、RobustScalerRobustScaler 是一种对异常值更稳健的缩放方法。它通常使用中位数和四分位范围来缩放数据而不是使用均值和标准差。基本用法如下from sklearn.preprocessing import RobustScaler scaler RobustScaler() X_train_scaled scaler.fit_transform(X_train)X_test_scaled scaler.transform(X_test)如果数据中存在明显极端值例如收入、消费金额、房价等特征RobustScaler 有时比 StandardScaler 或 MinMaxScaler 更合适。4、标准化与归一化如何选择常见经验如下• 如果模型依赖距离或梯度优化可以优先考虑标准化• 如果特征需要限制在固定范围内可以考虑归一化• 如果数据存在明显异常值可以考虑 RobustScaler• 如果使用树模型通常不必因为尺度问题强制标准化需要强调的是标准化、归一化没有绝对优劣。它们都是为了让数据表示更适合模型而不是为了让数据“看起来更整齐”。四、类别编码1、为什么类别特征需要编码许多机器学习模型只能处理数值型输入不能直接理解字符串类别。例如某个特征是“城市”北京、上海、广州、长沙。模型不能直接把这些中文字符串当作数值计算。因此需要把类别特征转换为数值表示这个过程称为类别编码。Scikit-learn 中常见的类别编码工具包括• OrdinalEncoder• OneHotEncoder• LabelEncoder但它们的用途并不完全相同。2、OrdinalEncoder把类别映射为整数OrdinalEncoder 用于把输入特征中的类别值转换成整数编号。例如• 低、中、高可能被转换为• 0、1、2基本用法如下from sklearn.preprocessing import OrdinalEncoder encoder OrdinalEncoder() X_encoded encoder.fit_transform(X_category)OrdinalEncoder 适合处理类别本身具有顺序关系的特征例如• 学历小学、初中、高中、大学• 评价等级低、中、高• 风险等级低风险、中风险、高风险但如果类别之间没有天然顺序例如城市、颜色、职业等直接使用整数编码可能会让模型误以为类别之间存在大小关系。3、OneHotEncoder把类别转换为独热编码OneHotEncoder 会把每个类别转换为一个二进制列。官方文档说明OneHotEncoder 用于把类别特征编码为 one-hot 数值数组并会为每个类别创建一个二进制列。例如颜色特征有三个类别• 红色、蓝色、绿色独热编码后可以理解为• 红色 → [1, 0, 0]• 蓝色 → [0, 1, 0]• 绿色 → [0, 0, 1]基本用法如下from sklearn.preprocessing import OneHotEncoder encoder OneHotEncoder(handle_unknownignore) X_encoded encoder.fit_transform(X_category)其中handle_unknownignore 的作用是当测试集或新数据中出现训练集没有见过的类别时不直接报错而是按可处理方式忽略。OneHotEncoder 适合处理没有大小顺序的类别特征例如• 城市• 颜色• 职业• 商品类别• 浏览器类型4、LabelEncoder主要用于标签 yLabelEncoder 常用于把目标变量 y 中的类别标签转换成数字编号。例如• setosa、versicolor、virginica可以编码为• 0、1、2基本用法如下from sklearn.preprocessing import LabelEncoder encoder LabelEncoder() y_encoded encoder.fit_transform(y)需要注意的是LabelEncoder 主要用于目标变量 y而不是用于特征矩阵 X 中的普通类别特征。对于 X 中的类别特征通常应优先考虑 OrdinalEncoder 或 OneHotEncoder。五、缺失值处理SimpleImputer1、为什么要处理缺失值现实数据中经常存在缺失值。例如• 用户没有填写年龄• 某个传感器没有采集到数据• 表格中某些列为空• 某些记录缺少价格、类别或时间信息很多模型不能直接处理缺失值。如果数据中存在 NaN模型训练时可能报错。因此在建模之前通常需要先处理缺失值。缺失值处理主要位于 sklearn.impute 模块而不是 sklearn.preprocessing 模块。但在实际工作流中它经常和标准化、编码等预处理步骤放在一起。2、SimpleImputer 的基本作用SimpleImputer 是 Scikit-learn 中最常用的简单缺失值填补工具。官方文档说明它可以使用每列的均值、中位数、众数或者指定常量来替换缺失值。基本用法如下from sklearn.impute import SimpleImputer imputer SimpleImputer(strategymean) X_filled imputer.fit_transform(X)其中• strategymean 表示用均值填补• strategymedian 表示用中位数填补• strategymost_frequent 表示用最常见值填补• strategyconstant 表示用指定常量填补3、不同类型数据的填补方式对于数值型特征常见策略包括• 用均值填补• 用中位数填补• 用固定值填补如果数据存在极端值中位数通常比均值更稳健。对于类别型特征常见策略包括• 用最常见类别填补• 用 “Unknown” 或 “Missing” 等常量填补例如from sklearn.impute import SimpleImputer imputer SimpleImputer(strategymost_frequent) X_filled imputer.fit_transform(X)需要注意的是缺失值填补也应只在训练集上 fit()再对测试集使用 transform()避免测试集信息提前进入训练流程。4、更复杂的缺失值处理方法除了 SimpleImputerScikit-learn 还提供• KNNImputer根据相似样本填补缺失值• IterativeImputer利用其他特征迭代估计缺失值• MissingIndicator生成缺失位置的指示特征Scikit-learn 的 sklearn.impute API 中也列出了这些用于缺失值填补和缺失指示的工具。对于入门学习而言先掌握 SimpleImputer 已经足够。更复杂的方法可以在理解数据结构和模型需求之后再学习。六、特征变换与特征扩展1、二值化Binarizer二值化Binarization是指根据某个阈值把数值特征转换为 0 或 1。例如某个特征表示用户消费金额可以按照阈值判断是否属于高消费• 消费金额 1000 → 1• 消费金额 ≤ 1000 → 0在 Scikit-learn 中可以使用 Binarizerfrom sklearn.preprocessing import Binarizer binarizer Binarizer(threshold1000) X_binary binarizer.fit_transform(X)二值化适合那些本身可以用阈值表达含义的特征但不应随意使用。因为二值化会丢失原始数值中的细节信息。2、多项式特征PolynomialFeatures多项式特征扩展Polynomial Features用于从原始特征中构造更复杂的组合特征。例如原始输入只有两个特征 a 和 b二次多项式特征可能包含a, b, a², ab, b²。在 Scikit-learn 中可以使用 PolynomialFeaturesfrom sklearn.preprocessing import PolynomialFeatures poly PolynomialFeatures(degree2) X_poly poly.fit_transform(X)多项式特征可以让线性模型表达一定程度的非线性关系。例如线性回归本身只能拟合线性关系但如果先构造多项式特征再使用线性回归就可以拟合曲线关系。不过多项式特征会增加特征数量。如果阶数过高可能导致模型复杂度过高甚至出现过拟合。3、函数变换FunctionTransformerFunctionTransformer 可以把自定义函数包装成 Scikit-learn 风格的转换器。例如对某些偏态分布的特征可以进行对数变换import numpy as npfrom sklearn.preprocessing import FunctionTransformer log_transformer FunctionTransformer(np.log1p) X_log log_transformer.fit_transform(X)其中• np.log1p(x) 表示计算 log(1 x)• 它常用于处理右偏分布的非负数值特征• FunctionTransformer 可以让这种自定义变换融入 Pipeline这类工具适合把常见数学变换纳入标准化工作流中。七、ColumnTransformer不同列采用不同处理方式1、为什么需要 ColumnTransformer在真实表格数据中不同列往往需要不同处理方式。例如• 数值列需要标准化• 类别列需要独热编码• 缺失值列需要填补• 某些列可能需要删除或保留如果手动分别处理每一列流程容易混乱也容易在训练集和测试集之间产生不一致。ColumnTransformer 可以让不同列使用不同的预处理方法并把结果合并起来。2、ColumnTransformer 的基本用法假设数据中有数值列和类别列from sklearn.compose import ColumnTransformerfrom sklearn.preprocessing import StandardScaler, OneHotEncoder numeric_features [age, income]categorical_features [city, gender] preprocessor ColumnTransformer( transformers[ (num, StandardScaler(), numeric_features), (cat, OneHotEncoder(handle_unknownignore), categorical_features) ])其中• num 是数值列处理步骤的名称• StandardScaler() 用于处理数值列• cat 是类别列处理步骤的名称• OneHotEncoder() 用于处理类别列这样数值列和类别列就可以在同一个预处理对象中分别处理。3、ColumnTransformer 与 Pipeline 配合在真实建模中ColumnTransformer 通常会与 Pipeline 配合使用from sklearn.pipeline import Pipelinefrom sklearn.linear_model import LogisticRegression model Pipeline( steps[ (preprocessor, preprocessor), (classifier, LogisticRegression()) ])这样完整流程就变成原始表格数据 → 分列预处理 → 模型训练 → 模型预测这种写法特别适合真实表格数据因为真实数据通常同时包含数值特征和类别特征。八、Pipeline避免数据泄漏的关键工具1、为什么预处理容易产生数据泄漏数据泄漏是指模型训练过程中使用了本不应该提前知道的信息尤其是测试集或验证集中的信息。例如下面这种做法并不推荐X_scaled scaler.fit_transform(X)X_train, X_test, y_train, y_test train_test_split(X_scaled, y)这里的问题是标准化器已经在全量数据 X 上学习了均值和标准差其中包含测试集信息。这样会让测试结果偏乐观。2、正确做法先划分再 fit更合理的做法是X_train, X_test, y_train, y_test train_test_split(X, y) scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train)X_test_scaled scaler.transform(X_test)也就是说• 训练集用于 fit() 和 transform()• 测试集只用于 transform()• 测试集不能参与预处理参数的学习Scikit-learn 的常见问题指南也强调训练集和测试集应使用一致的预处理流程可以在训练集上使用 fit_transform()在测试集上使用 transform()。同时Pipeline 是避免数据泄漏的重要方式因为它能确保在正确的数据子集上执行正确的方法。3、使用 Pipeline 组织完整流程更推荐的方式是使用 Pipelinefrom sklearn.pipeline import Pipelinefrom sklearn.preprocessing import StandardScalerfrom sklearn.linear_model import Ridge pipe Pipeline([ (scaler, StandardScaler()), (model, Ridge())]) pipe.fit(X_train, y_train)y_pred pipe.predict(X_test)Pipeline 可以按顺序应用多个转换器并且可以在最后连接一个预测器。Scikit-learn 官方文档也说明Pipeline 用于顺序应用一组数据转换器并可在最后接一个预测器。这样写的好处是• 代码更清晰• 训练和预测流程更一致• 更不容易出现数据泄漏• 便于结合交叉验证和超参数搜索Scikit-learn 关于 Pipeline 和组合估计器的说明中也指出Pipeline 有助于避免交叉验证中测试数据统计量泄漏到模型训练中并且可以一次性对 Pipeline 中各估计器参数进行网格搜索。九、常见预处理方法的选择建议不同预处理方法适合不同数据和模型。下面给出一些入门级判断方法。1、数值型特征如果数值特征量纲差异明显可以考虑• StandardScaler常用默认选择适合许多线性模型、K 近邻、SVM、PCA• MinMaxScaler适合需要固定取值范围的场景• RobustScaler适合存在明显异常值的场景如果特征分布明显偏斜也可以考虑对数变换、幂变换等方法。2、类别型特征如果类别有顺序可以考虑• OrdinalEncoder例如低、中、高。如果类别没有顺序可以考虑• OneHotEncoder例如城市、职业、商品类型。如果是目标变量 y 的类别标签可以考虑• LabelEncoder3、缺失值如果是数值特征缺失可以考虑• 均值填补• 中位数填补• 固定值填补如果是类别特征缺失可以考虑• 最常见类别填补• “Unknown” 等常量填补缺失值处理不应只看技术方便还要结合缺失原因判断。某些缺失本身可能包含重要信息。4、表格数据真实表格数据往往同时包含数值列和类别列。因此建议使用• ColumnTransformer 处理不同列• Pipeline 连接预处理与模型这样可以让整个流程更加清晰、可靠也更适合后续交叉验证和模型选择。 小结preprocessing 模块用于把原始特征转换为更适合模型学习的数据表示常见功能包括标准化、归一化、类别编码、特征变换和特征扩展。实际建模中还应结合缺失值处理、ColumnTransformer 和 Pipeline避免数据泄漏并形成可靠的预处理流程。“点赞有美意赞赏是鼓励”