【机器学习】5 个 Scikit-learn Pipeline 技巧,让你的工作流程更高效
【精选优质专栏推荐】
- 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用
- 《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看
- 《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解
- 《网安渗透工具使用教程(全)》 —— 一站式工具手册
- 《CTF 新手入门实战教程》 —— 从题目讲解到实战技巧
- 《前后端项目开发(新手必知必会)》 —— 实战驱动快速上手
每个专栏均配有案例与图文讲解,循序渐进,适合新手与进阶学习者,欢迎订阅。
文章目录

介绍
Pipeline 可能是 scikit-learn 中最被低估但同时最强大的功能之一,它能帮助构建高效、模块化的机器学习工作流。从数据准备、特征工程到建模、调优和验证,它简化了整个过程,同时降低数据泄漏风险,使代码更具可复现性,也更简洁易维护。
在本文中,我们将通过简洁但偏中高级的用例,介绍并演示五个 pipeline 技巧,帮助你提升正在进行的机器学习项目。
初始设置
下面的代码及其组成部分会在后续多个示例中使用,因此建议先完成这些准备步骤。
需要注意的是,接下来我们主要使用常见的 Titanic 生存预测数据集:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.impute import SimpleImputer
from sklearn.datasets import fetch_openml
# 加载数据集 (Titanic 生存预测)
titanic = fetch_openml("titanic", version=1, as_frame=True)
X = titanic.data[["pclass", "sex", "age", "fare"]]
y = titanic.target == "1"
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)
# 按特征类型选择特征
num_features = ["age", "fare"]
cat_features = ["pclass", "sex"]
现在正式进入本文的核心实践部分。
1. 使用 ColumnTransformer 处理混合数据类型
在第一个示例中,我们将实例化一个 ColumnTransformer 对象来定义一个健壮的数据预处理 pipeline。这个类允许针对不同的特征子集灵活应用不同的转换操作,以统一的方式处理混合数据类型和缺失值,避免繁琐的操作和重复代码。
# 实例化 ColumnTransformer 以进行健壮的数据预处理
preprocessor = ColumnTransformer([
("num", Pipeline([
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler())
]), num_features),
("cat", Pipeline([
("imputer", SimpleImputer(strategy="most_frequent")),
("onehot", OneHotEncoder(handle_unknown="ignore"))
]), cat_features)
])
pipe = Pipeline([
("preprocessor", preprocessor),
("model", LogisticRegression(max_iter=1000))
])
pipe.fit(X_train, y_train)
print("Accuracy:", pipe.score(X_test, y_test))
这种方法能同时处理数值特征、类别特征和缺失值,并在训练逻辑回归分类器前,把它们整合进一个整体 pipeline。
2. 使用自定义 Transformer 进行特征工程
在 scikit-learn 中,自定义 transformer 允许我们定义自己的特征级转换步骤(无论是特征工程还是预处理),并直接嵌入 pipeline。常见做法是继承 TransformerMixin,实现 fit 和 transform 方法,这样就可以无缝使用 fit_transform()。
下面的代码通过继承定义了一个自定义 transformer 类。它会将数值特征 age 转换为二进制特征(0 或 1),表示乘客是否为成年人。然后,我们将该逻辑集成到类似前例的 ColumnTransformer 中。
from sklearn.base import BaseEstimator, TransformerMixin
# 自定义 transformer:基于 age 创建二进制特征 "is_adult"
class IsAdult(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X):
return (X["age"].fillna(0) >= 18).astype(int).to_frame("is_adult")
# 扩展 ColumnTransformer,加入自定义 transformer
extended = ColumnTransformer([
("num", Pipeline([
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler())
]), num_features),
("cat", Pipeline([
("imputer", SimpleImputer(strategy="most_frequent")),
("onehot", OneHotEncoder(handle_unknown="ignore"))
]), cat_features),
("is_adult", IsAdult(), ["age"])
])
pipe = Pipeline([
("preprocessor", extended),
("model", LogisticRegression(max_iter=1000))
])
pipe.fit(X_train, y_train)
print("Accuracy with custom feature:", pipe.score(X_test, y_test))
3. 在整个 Pipeline 上进行超参数调优
超参数调优(在多个选项中找到最佳配置)并不仅限于模型本身的参数,它也可以应用到前面的预处理步骤。下面的示例展示了如何做到这一点:
from sklearn.svm import SVC
pipe = Pipeline([
("preprocessor", preprocessor),
("model", SVC())
])
param_grid = {
"preprocessor__num__imputer__strategy": ["mean", "median"],
"model__C": [0.1, 1, 10],
"model__kernel": ["linear", "rbf"]
}
search = GridSearchCV(pipe, param_grid, cv=3)
search.fit(X_train, y_train)
print("Best params:", search.best_params_)
print("Best score:", search.best_score_)
请注意,preprocessor 就是示例 1 中定义的 ColumnTransformer。关键在于搜索网格中加入了一个与预处理步骤相关的超参数,即缺失值填充策略。换句话说,训练出的多个模型版本不仅基于模型自身的超参数,还涉及预处理中的具体设置。
4. 在 Pipeline 中集成特征选择
对于特征数量较多的数据集,一个有力的技巧是将特征选择步骤动态地放进 pipeline,使最终模型更简洁。
下面的示例在训练模型之前,自动选择最有信息量的预处理特征。这里通过 SelectKBest 类调用评分函数,挑选出得分最高的特征:
from sklearn.feature_selection import SelectKBest, f_classif
pipe = Pipeline([
("preprocessor", preprocessor),
("feature_selection", SelectKBest(score_func=f_classif, k=5)),
("model", LogisticRegression(max_iter=1000))
])
pipe.fit(X_train, y_train)
print("Test accuracy:", pipe.score(X_test, y_test))
SelectKBest 需要一个评分函数或判定标准来选择前 k 个特征。例如,也可以使用 score_func=chi2,它基于卡方检验选择特征,适合类别特征占主导的数据集。
5. 堆叠 Pipeline
最后一个示例展示如何堆叠多个 pipeline 来构建集成学习方案。在不同模型(甚至包含不同预处理步骤)的场景下,pipeline 能帮助我们避免数据管理不一致,同时实现高度可定制的集成。
在下面的示例中,我们定义了两个“顶层” pipeline:一个对数据进行预处理并训练逻辑回归分类器,另一个应用相同的预处理,但训练决策树分类器:
from sklearn.ensemble import StackingClassifier
from sklearn.tree import DecisionTreeClassifier
log_reg_pipe = Pipeline([
("preprocessor", preprocessor),
("logreg", LogisticRegression(max_iter=1000))
])
tree_pipe = Pipeline([
("preprocessor", preprocessor),
("tree", DecisionTreeClassifier(max_depth=5))
])
stack = StackingClassifier(
estimators=[("lr", log_reg_pipe), ("dt", tree_pipe)],
final_estimator=LogisticRegression()
)
stack.fit(X_train, y_train)
print("Stacked accuracy:", stack.score(X_test, y_test))
这两个 pipeline 随后通过 StackingClassifier 堆叠。该类会使用一个最终估计器来学习如何最佳组合基础模型的预测,从而得到更强大、更具泛化能力的模型。
总结
本文展示了五个关于 scikit-learn pipeline 的实用示例,用来加速并增强机器学习工作流的效果、可定制性和性能。从针对混合数据类型的自定义预处理 pipeline,到将超参数调优扩展至预处理步骤,我们介绍了多个技巧和方法,帮助你把机器学习建模项目提升到新的水平。
更多推荐


所有评论(0)