news 2026/9/9 17:16:44

ColumnTransformer实战:打造高效可复用的机器学习特征预处理流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ColumnTransformer实战:打造高效可复用的机器学习特征预处理流程

如果你做过真实的机器学习项目,而不是只在 Kaggle 上跑通几个 demo,大概率遇到过这样一类问题:数据里既有年龄、收入这种数值特征,也有性别、城市这种类别特征,偶尔还有文本描述和缺失值。建模之前必须做特征变换,但数值列要标准化,类别列要 One-Hot 编码,缺失列要填充,文本列可能要单独向量化。如果手动按列名分别处理,先拆列、再变换、再拼接,代码很快会变成一团乱麻。

很多人第一次用到ColumnTransformer时,觉得它不过是个“把多个预处理步骤拼在一起”的封装工具,省了几行代码而已。但真正在工程里用过一段时间之后,我的判断是:ColumnTransformer 是 sklearn 里被低估最严重的组件之一,它真正解决的,是特征预处理代码的可维护性、可复现性和防呆问题。

这篇文章会用场景化的方式讲清楚:ColumnTransformer 解决的是什么问题,和 Pipeline、FeatureUnion 有什么区别,如何在真实项目里组合使用,以及新手最容易踩的坑。文章包含完整的可运行代码,读完你可以直接把它用到自己的特征工程流程里。

1. 这篇文章真正要解决的问题

先看一段很多初学者都写过的代码:

import pandas as pd from sklearn.preprocessing import StandardScaler, OneHotEncoder df = pd.DataFrame({ 'age': [25, 30, 35, 40, 45], 'salary': [50000, 60000, 80000, 120000, 150000], 'city': ['北京', '上海', '广州', '北京', '上海'], 'gender': ['男', '女', '男', '女', '男'] }) # 手动拆列处理:选出数值列和类别列 num_cols = ['age', 'salary'] cat_cols = ['city', 'gender'] # 分别变换 num_transformed = StandardScaler().fit_transform(df[num_cols]) cat_transformed = OneHotEncoder().fit_transform(df[cat_cols]) # 手动拼接(这里还要处理数组类型、稀疏矩阵等问题) # ...

这段代码的问题不在于“能不能跑”,而在于:

  • 一旦列数变多,每个预处理步骤都手动处理,代码会迅速膨胀。
  • 不同变换之间的顺序、拼接逻辑全靠人脑记忆,改一处容易漏另一处。
  • 在交叉验证或线上推理时,很容易对测试集误用fit_transform而不是transform
  • 一旦要加入新的数据处理步骤,比如缺失值填充、自定义函数变换,代码结构会变得很难维护。

ColumnTransformer 要解决的正是这个问题:让不同类型的列,应用不同的变换规则,并且保持在一个清晰的组件里,作为一个整体进行 fit、transform 和保存。

如果你正在做以下事情,这篇文章对你会有直接帮助:

  • 正在学习机器学习,想弄清楚 sklearn 的预处理组件如何组合。
  • 在做实际项目,需要同时处理数值列、类别列、缺失值,但不想写一大段拼接代码。
  • 想把特征预处理和模型训练放在同一个 Pipeline 里,避免数据泄露。
  • 在团队协作中,希望特征处理代码更清晰、更容易被别人接手。

2. ColumnTransformer 核心概念与适用场景

2.1 什么是 ColumnTransformer

ColumnTransformer 是scikit-learn在 0.20 版本引入的一个预处理器。它的作用非常明确:把数据集按列拆分成若干组,每一组应用各自的变换器,最后把变换结果按顺序拼接成一个完整特征矩阵。

在没有它之前,你需要在代码里手动完成“选列 — 变换 — 拼接”这三步;有了它之后,你只需要声明每个变换器作用于哪些列,剩下的拆分和拼接由 ColumnTransformer 自动完成。

它的核心参数是transformers,这是一个列表,每一项是一个三元组:

(名称, 变换器, 列名列表)

例如:

from sklearn.compose import ColumnTransformer preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['age', 'salary']), ('cat', OneHotEncoder(), ['city', 'gender']) ] )

列名列表可以是:

  • 列名的字符串列表,如['age', 'salary']
  • 列位置的整数列表,如[0, 1]
  • 布尔掩码数组。
  • 也可以传make_column_selector按数据类型自动选择列。

2.2 ColumnTransformer 与 Pipeline 的关系

理解 ColumnTransformer,必须把它放在 Pipeline 的上下文中看。

Pipeline 解决的是“步骤之间按顺序执行”的问题,比如:先填充缺失值,再标准化,再训练模型。它的典型写法是:

from sklearn.pipeline import Pipeline model = Pipeline(steps=[ ('preprocess', SomePreprocessor()), ('clf', LogisticRegression()) ])

但传统 Pipeline 有一个限制:preprocess这一步只能对整个特征矩阵应用同一个变换器。如果你有数值列和类别列,就需要先手动让它们经过不同处理,再合并回去。

ColumnTransformer 的价值在于:它让 Pipeline 中的“数据预处理”这个步骤,从“只能对全列施加统一操作”升级为“不同列各走各路”。

所以最常见的组合方式是这样的:

from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.linear_model import LogisticRegression preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['age', 'salary']), ('cat', OneHotEncoder(), ['city', 'gender']) ] ) model = Pipeline(steps=[ ('preprocessor', preprocessor), ('classifier', LogisticRegression()) ])

这个 Pipeline 对象可以像普通模型一样fitpredict、用于交叉验证,也可以被打包保存。特征工程、数据清洗和模型训练被绑定为一个整体,这是工程上非常重要的进步。

2.3 ColumnTransformer 与 FeatureUnion 的区别

还有一个容易混淆的组件叫FeatureUnion。它和 ColumnTransformer 都做“合并特征”,但思路不同。

  • FeatureUnion:对同一组列应用多个不同的变换器,然后横向拼接结果。比如对文本列同时做 TF-IDF 和关键词计数,把两组特征拼接起来。
  • ColumnTransformer:对不同组别的列应用不同的变换器,然后横向拼接结果。比如数值列标准化、类别列独热编码。

可以这样区分:如果你关心的是“同一份数据从多个角度提取特征”,用 FeatureUnion;如果关心的是“不同类型的数据分别走各自的预处理流程”,用 ColumnTransformer。

2.4 什么时候需要 ColumnTransformer

从实际经验看,以下场景是 ColumnTransformer 的主场:

  • 表格数据建模,特征包含数值列和类别列。
  • 数据里同时存在缺失值、异常值、偏态分布,需要针对不同列做不同处理。
  • 想要把预处理和模型训练放进同一个 Pipeline,避免数据泄露。
  • 需要反复交叉验证,希望每个验证折上都用相同方式处理数据。
  • 模型上线时,想用一个“模型对象”搞定所有事情,而不是为预处理单独写一套逻辑。

3. 环境准备与前置条件

在开始写代码之前,先确认环境。

本文代码基于 Python 3 和 scikit-learn。ColumnTransformer 从 sklearn 0.20 版本引入,建议使用 0.24 以上版本,如果使用 1.0 以上版本,get_feature_names_out()等 API 会更完善。如果版本过低,部分示例中的 API 可能不存在。

推荐使用虚拟环境安装依赖:

python -m venv ml_env source ml_env/bin/activate # Windows 下使用 ml_env\Scripts\activate

安装依赖:

pip install scikit-learn pandas numpy

版本方面以实际安装为准,例如:

python -c "import sklearn; print(sklearn.__version__)"

本文示例没有特别依赖具体版本,核心逻辑在主流版本中均可运行。只是当你的 sklearn 版本等于或高于 1.0 时,OneHotEncoder 的get_feature_names_out()方法会更方便。

建议使用 Jupyter Notebook 或 VS Code 的交互式环境运行示例,方便逐步查看中间输出。

4. 构建列变换器的核心流程

使用 ColumnTransformer 构建特征预处理,大致分为四个步骤:

  1. 确定列分组:先观察数据,判断哪些列是数值列、哪些是类别列、哪些需要缺失值填充或自定义处理。
  2. 选择变换器:为每组列挑选合适的 sklearn 变换器。
  3. 组装 ColumnTransformer:把“名称、变换器、列名”的元组按顺序传进去。
  4. 接入 Pipeline 或直接使用:在 Pipeline 中使用,或单独对它fit_transform

这个流程看起来简单,但很容易在第一步和第三步出问题。尤其是第一步,很多人不分析数据就直接套模板,结果数值列里混入对象类型,或者类别列里出现高基数情况,后续编码结果和预期完全不同。

4.1 分析数据结构

用一个贴近实际场景的示例数据来说明。假设我们有一份简化版员工信息表,目标是预测员工是否离职:

import pandas as pd import numpy as np df = pd.DataFrame({ 'age': [25, 30, 35, np.nan, 45], 'salary': [50000, 60000, 80000, 120000, 150000], 'department': ['技术', '产品', '技术', '市场', '产品'], 'city': ['北京', '上海', '广州', '北京', '上海'], 'overtime': ['高', '中', '高', '低', '中'], 'left': [0, 0, 1, 0, 1] }) print(df.dtypes)

输出:

age float64 salary int64 department object city object overtime object left int64

从数据看,age存在缺失值,salary是数值列,departmentcity是普通类别列,overtime是包含顺序的类别列。

如果直接用同一个变换器处理所有列,结果一定不理想:

  • 缺失值必须填充,不能直接交给标准化。
  • departmentcity用 One-Hot 编码没问题。
  • overtime用 One-Hot 编码会丢失顺序信息,可以考虑映射为数值或使用OrdinalEncoder

4.2 选择变换器

针对刚才的数据,合理的处理方案是:

  • age:先用SimpleImputer填充缺失值(均值策略),再交给StandardScaler标准化。但 ColumnTransformer 中一个元组只能放一个变换器,所以需要用 Pipeline 把这两个变换串起来。
  • salary:直接标准化。
  • departmentcity:One-Hot 编码。
  • overtime:用OrdinalEncoder编码,或者自定义映射。

这样,preprocessor的结构就比较清晰了:

from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder, OrdinalEncoder from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer age_pipeline = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='mean')), ('scaler', StandardScaler()) ]) numeric_pipeline = Pipeline(steps=[ ('scaler', StandardScaler()) ]) preprocessor = ColumnTransformer( transformers=[ ('age', age_pipeline, ['age']), ('salary', numeric_pipeline, ['salary']), ('dept_city', OneHotEncoder(), ['department', 'city']), ('overtime', OrdinalEncoder(), ['overtime']) ] )

这里体现了一个关键思想:当某一列需要多个变换步骤时,不需要把 ColumnTransformer 拆散,只需要在元组的第二个位置放一个 Pipeline,让列的变换流程在内部串起来。

4.3 关于 column 参数和自动选择

除了手写列名,sklearn 还提供了make_column_selector,可以根据dtype_includedtype_exclude自动选择列:

from sklearn.compose import make_column_selector preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), make_column_selector(dtype_include=np.number)), ('cat', OneHotEncoder(), make_column_selector(dtype_include=object)) ] )

这个写法的好处是,当新增一列数值特征时,只要数据类型正确,它会自动纳入预处理流程。缺点是“自动”也可能带来意外:如果某列数据类型没设对,或者新列本来不该参与建模却被自动选中,就需要额外注意。

我的建议是:在探索性分析阶段可以用make_column_selector快速验证,但在正式建模时,还是显式写出列名更稳妥。显式写列名虽然多几行代码,但可读性和可维护性都更好。

4.4 remainder 参数的作用

ColumnTransformer 有一个容易被忽略的参数remainder。它决定那些没有出现在transformers里的列怎么处理:

  • 'drop':默认值,丢弃未指定的列。
  • 'passthrough':保留未指定的列,原样拼接到输出特征矩阵的末尾。

如果漏掉remainder='passthrough'',明明存在的列却静默消失,这是新手最容易踩的坑之一。

比如把上面示例中除数num之外的列也当作特征时,如果只写:

preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['age', 'salary']) ] ) X = preprocessor.fit_transform(df) print(X.shape) # 结果只有 2 列,其他列全部被丢弃

结果会只剩数值列。因此,必须显式决定:哪些列保留,哪些列丢弃,哪些列要做变换。

5. 完整示例代码实现

示例 1:ColumnTransformer 基础用法

先从一个最小示例开始,跑通流程。

import pandas as pd import numpy as np from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder df = pd.DataFrame({ 'age': [25, 30, 35, 40, 45], 'salary': [50000, 60000, 80000, 120000, 150000], 'city': ['北京', '上海', '广州', '北京', '上海'], 'gender': ['男', '女', '男', '女', '男'] }) preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['age', 'salary']), ('cat', OneHotEncoder(), ['city', 'gender']) ] ) X_transformed = preprocessor.fit_transform(df) print(X_transformed) print(X_transformed.shape)

运行结果是一个 NumPy 数组(也可能是稀疏矩阵)。如果 OneHotEncoder 默认返回稀疏矩阵,用dense方式打印会比较直观,也可以设置OneHotEncoder(sparse_output=False)直接输出稠密矩阵。

这一步的逻辑:

  • agesalary被标准化,转换成均值为 0、方差为 1 的分布。
  • citygender被 One-Hot 编码,变成一个稀疏的 0/1 矩阵。
  • 两部分的列按顺序拼接。

示例 2:在 Pipeline 中集成 ColumnTransformer 训练模型

这是实际项目中最常用的形式。把预处理和模型放在一起,保证每次fit时训练集和验证集都走同一套逻辑。

import pandas as pd import numpy as np from sklearn.compose import ColumnTransformer from sklearn.impute import SimpleImputer from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score # 构造一份带有缺失值的数据 df = pd.DataFrame({ 'age': [25, 30, 35, np.nan, 45, 50], 'salary': [50000, 60000, 80000, 120000, 150000, np.nan], 'city': ['北京', '上海', '广州', '北京', '上海', '广州'], 'gender': ['男', '女', '男', '女', '男', '女'], 'left': [0, 0, 1, 0, 1, 0] }) X = df.drop(columns=['left']) y = df['left'] # 数值列:先填充缺失值,再标准化 numeric_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='mean')), ('scaler', StandardScaler()) ]) # 类别列:One-Hot 编码 categorical_transformer = OneHotEncoder(sparse_output=False) preprocessor = ColumnTransformer( transformers=[ ('num', numeric_transformer, ['age', 'salary']), ('cat', categorical_transformer, ['city', 'gender']) ] ) model = Pipeline(steps=[ ('preprocessor', preprocessor), ('classifier', LogisticRegression(max_iter=1000)) ]) scores = cross_val_score(model, X, y, cv=3, scoring='accuracy') print(f"交叉验证准确率: {scores.mean():.4f}")

代码里sparse_output=False是为了让 OneHotEncoder 直接输出稠密数组。不同版本的 sklearn 参数名可能有变化,早期版本叫sparse=False,新版叫sparse_output=False,建议按实际环境查看文档。

这里的关键点:整个 Pipeline 只暴露了fitpredict两个接口,外部使用者不需要关心预处理细节。这一点在模型上线时尤其重要。

示例 3:使用 make_column_transformer 简化写法

当你不想为每个变换器手动命名时,可以用make_column_transformer。它会根据变换器类型自动生成名称。

from sklearn.compose import make_column_transformer from sklearn.preprocessing import StandardScaler, OneHotEncoder preprocessor = make_column_transformer( (StandardScaler(), ['age', 'salary']), (OneHotEncoder(), ['city', 'gender']) ) X_transformed = preprocessor.fit_transform(df) print(X_transformed.shape)

这种写法适合快速验证,少打字。但缺点也很明显:不容易自定义名称,后续调试时不太方便查看每个部分对应哪些列。在正式项目中,我仍然推荐显式写ColumnTransformer

示例 4:结合自定义变换器

ColumnTransformer 的第二个位置可以放任何实现了fittransform方法的对象,也包括自定义变换器。

比如,我们要对salary做对数变换,可以用FunctionTransformer

from sklearn.preprocessing import FunctionTransformer def log_transform(X): return np.log1p(X) log_transformer = FunctionTransformer(log_transform, feature_names_out='one-to-one') preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['age']), ('salary_log', log_transformer, ['salary']), ('cat', OneHotEncoder(), ['city', 'gender']) ] ) X_transformed = preprocessor.fit_transform(df) print(preprocessor.get_feature_names_out())

FunctionTransformer的存在,让 ColumnTransformer 可以应对各种“非标准化”的变换需求。只要你能写成一个函数,就能放进列变换器里。

6. 运行结果与效果验证

6.1 如何验证预处理结果

很多初学者跑完fit_transform后,只看一眼“能运行”就结束了。但在真实项目中,你必须确认:输出的特征矩阵是否符合预期?每一列到底代表什么意思?

可以通过get_feature_names_out()查看变换后的特征名:

preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['age', 'salary']), ('cat', OneHotEncoder(), ['city', 'gender']) ] ) preprocessor.fit(df) print(preprocessor.get_feature_names_out())

输出类似:

['num__age', 'num__salary', 'cat__city_上海', 'cat__city_北京', 'cat__city_广州', 'cat__gender_女', 'cat__gender_男']

这个结果非常重要。通过特征名,你可以反推每个输出列来自哪个原始列,也能在模型训练后把特征重要性映射回原始特征。

6.2 验证 Pipeline 是否发生数据泄露

在 Pipeline 中集成 ColumnTransformer 后,交叉验证会安全地处理数据:每一折训练时只在训练子集上调用fit_transform,在验证子集上调用transform,避免均值、标准化参数等从验证集“泄露”到训练过程。

你可以用下面的方式验证特征数量是否符合预期:

model.fit(X, y) print(f"特征数量: {model.named_steps['preprocessor'].transform(X).shape[1]}")

如果特征数量远多于你的预期,很可能 One-Hot 编码产生了过多列,或者某个类别列的基数过高;如果少于预期,检查是否写了remainder='drop'

6.3 模型的整体保存与加载

因为预处理和模型在同一个 Pipeline 中,保存和加载也变简单了。推荐使用joblib

import joblib joblib.dump(model, 'employee_left_model.pkl')

加载时:

loaded_model = joblib.load('employee_left_model.pkl')

之后的预测不需要再手动执行标准化、编码等步骤,直接传入原始特征即可:

new_data = pd.DataFrame({ 'age': [38], 'salary': [90000], 'city': ['上海'], 'gender': ['女'] }) prediction = loaded_model.predict(new_data) print(prediction)

此时你才能体会到 ColumnTransformer 和 Pipeline 结合真正的价值:从原始数据到预测结果,链路是完整且一致的。

7. 常见问题与排查思路

问题现象可能原因排查方式解决方案
报错KeyError: 'salary'或列名错误transformers中写的列名在数据里不存在打印df.columns核对列名修正列名,或通过列索引方式传入
处理完数据后列数异常少未设置remainder='passthrough',未指定列被丢弃检查输出特征数量,查看get_feature_names_out()按需设置remainder='passthrough'或补全变换器
OneHotEncoder 输出矩阵太大,内存爆炸类别列基数过高,One-Hot 编码产生大量列查看类别列唯一值数量改用OrdinalEncoder、目标编码,或对低频类别合并
在 Transformer 中传入 Pandas 切片报错某些变换器只接受二维数组,而传入了 Series检查传给变换器的数据类型和形状确保列名用列表形式,如['age']而不是'age'
get_feature_names_out()不可用sklearn 版本过低查看 sklearn 版本升级到 1.0 以上版本
交叉验证得分不稳定数据量太小,或类别列中有冷门类别查看每个类别的样本数量增加数据量,或对冷门类别做合并
Pipeline 预测时提示特征数量不匹配训练和预测时传入的列不一致对比训练集和预测集的列名保证预测时使用与训练时相同的列结构

7.1 最容易忽略的“稀疏矩阵”问题

OneHotEncoder默认输出稀疏矩阵,这在内存和速度上通常更好。但当你把ColumnTransformer输出交给某些模型或工具时,可能遇到类型不兼容的问题。

临时解决办法是在编码器里设置sparse_output=False,但要注意这会显著增加内存占用。更好的做法是保留稀疏输出,让支持稀疏输入的模型(如线性模型、朴素贝叶斯)直接使用。

如果你在中间步骤希望查看稠密矩阵,可以调用.toarray()

X_dense = preprocessor.fit_transform(X).toarray()

7.2 列名传错导致“看不见”的错误

还有一个非常隐蔽的问题:列名写错了不会立即报错,但结果会异常。比如['city']写成了['Cities'],如果数据里恰好没有这个列,某些 sklearn 版本会以不可预期的方式处理,有的直接抛异常,有的静默生成全零列。

避免这个问题的最好办法是:

  1. 先打印df.columns确认列名。
  2. fit_transform后打印get_feature_names_out()
  3. 对比两个输出,确认特征结构符合预期。

8. 最佳实践与工程建议

8.1 用有意义的名称

transformers里的第一个位置是“名称”。不要随便写t1t2,最好用可读性强的名字,比如numcatage_process。因为get_feature_names_out()会以名称__子特征名的形式输出,命名规范直接影响调试效率。

8.2 用 Pipeline 封装多个连续变换

如果同一组列需要多个变换步骤,比如先填充缺失值、再标准化、再降维,不要在ColumnTransformer外手动串联,而是把这几步放进一个子 Pipeline:

preprocessor = ColumnTransformer( transformers=[ ('num', Pipeline(steps=[ ('imputer', SimpleImputer()), ('scaler', StandardScaler()) ]), ['age', 'salary']) ] )

这样每一组列的变换流程都自成一体,逻辑清晰。

8.3 把整个流程保存下来

强烈建议在训练完成后,连同预处理和模型一起保存。不要只保存模型权重,否则上线预测时还要复制一份预处理代码,一旦两边逻辑不一致,结果必然出问题。

用 joblib 保存整个 Pipeline 对象,是最稳妥的做法。

8.4 对新数据做列对齐

ColumnTransformer 在训练时记住的列,和预测时传入的列必须一致。为了让这一点更可控,可以在预测脚本里统一处理数据列顺序:

feature_columns = ['age', 'salary', 'city', 'gender'] new_data = pd.DataFrame(raw_data, columns=feature_columns)

不要依赖字典的随机顺序,也不要依赖原始文件的列顺序。

8.5 在交叉验证之前不要提前 fit

这是数据泄露的重灾区。如果在切分训练集和验证集之前,先对整个数据集做fit_transform,那么验证集的信息已经参与了标准化和编码参数的计算,最终评估结果会偏乐观。

正确的做法是:把 ColumnTransformer 放进 Pipeline,让交叉验证自动在每个 fold 内完成 fit 和 transform。这也是本文多次强调“预处理要和模型绑定”的原因。

8.6 高频类别特征的取舍

对于类别特征,One-Hot 编码不是唯一的方案,也不总是最好的方案。当类别基数很高时,One-Hot 会产生大量稀疏列,训练时间和内存开销都会上升。此时可以考虑:

  • 对低频类别做统一替换,比如把出现次数少于阈值的类别合并为'other'
  • 使用OrdinalEncoder
  • 使用目标编码(Target Encoding)。
  • 使用嵌入类方法。

ColumnTransformer 的架构不会限制你的选择,只需要把对应的变换器替换到元组里即可。

9. 总结与后续学习方向

ColumnTransformer 解决的是一个非常具体但高频的问题:机器学习建模时,不同类型特征需要走不同的预处理流程。它真正的价值,不是省掉几行代码,而是让数据预处理变成一个可组合、可复用、可部署的标准组件。

这篇文章的核心要点,总结下来是:

  • 不同的列要应用不同的变换器,用ColumnTransformer组织。
  • 多个连续变换用子 Pipeline 封装。
  • ColumnTransformer要放进外层 Pipeline 与模型一起训练,避免数据泄露。
  • remainder控制未指定列的去留。
  • get_feature_names_out()验证输出特征。
  • 训练结束后,整个 Pipeline 一起保存,部署时直接加载推理。

如果你刚接触 sklearn,建议先从本文的示例 1 和示例 2 入手,跑通后再尝试把自定义函数、缺失值填充、类别编码组合在一起。动手跑一个完整的小项目,比看十篇教程都有效。

下一步可以继续研究的方向包括:自定义 Transformer 的完整写法、FeatureUnion与 ColumnTransformer 的组合使用、以及如何处理高基数类别特征。等你把预处理链路做扎实了,再用模型调参、特征选择,整个机器学习流程就会顺很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 17:12:49

LPC17XX例程深度解析:从GPIO到DMA的嵌入式实战指南

简介:面向LPC17XX系列Cortex-M3微控制器的入门级例程合集,覆盖ADC、CAN、DAC、外部中断(EINT)与GPDMA等常用外设模块,同时提供Keil工程模板,适合正在学习NXP LPC17XX开发的初学者,以及需要在工业…

作者头像 李华
网站建设 2026/9/9 17:11:04

论文排版工具全对比:Word、LaTeX与AI辅助方案深度解析

1. 先把排版的账算清楚:我们到底在为什么头疼 1.1 论文格式要求的"反人类"细节 每年到了三四月份,各大高校的打印店都会进入一年中最忙的时段。我当时的硕士论文,内容写作花了四个月,格式调整却耗了将近两周。目录永远…

作者头像 李华
网站建设 2026/9/9 17:08:09

GLAD入门与集成实战:从生成配置到初始化避坑指南

写GLAD使用之前,先说个真实场景:你照着教程在Windows上写第一个OpenGL程序,结果link阶段报了一堆 glGenVertexArrays 、 glShaderSource 的未解析外部符号,然后你上网一搜,答案全都在说“用GLAD,别用gl…

作者头像 李华
网站建设 2026/9/9 17:07:12

electron-builder下载fpm卡住?配置镜像源一步搞定

先说个真实场景,我一个项目在 Linux 下用 electron-builder 打 deb 包,结果每次都卡在 Downloading fpm 这一步,有时候十几分钟一动不动,有时候直接超时失败。查了半天发现 electron-builder 默认要跑到 GitHub 上去拉 fpm 这个工…

作者头像 李华
网站建设 2026/9/9 17:06:10

铠侠CD8P-V企业级SSD实战:混合用途NVMe盘的选型与部署指南

如果你最近在给数据中心挑 NVMe 固态硬盘,KIOXIA CD8P-V 这个型号大概率会出现在候选清单里。它是铠侠 CD8P 家族中定位很特殊的一款:混合用途(Mixed-Use),性能和寿命卡在纯读密集与写密集之间,价格也刚好落…

作者头像 李华