趋近智
使用 Scikit-learn 管道的主要原因之一是为确保数据转换的正确和一致应用,尤其是在使用交叉验证进行模型评估时。没有管道,在每个交叉验证折叠内部正确应用预处理步骤可能变得复杂且容易出错。
设想一个典型的交叉验证场景。你将数据分成例如5个折叠。在每次迭代中,4个折叠用于训练,1个折叠保留用于验证。如果你在此拆分发生之前执行缩放等预处理步骤,你就会无意中引入数据泄露。
为什么?因为当你对整个数据集拟合缩放器(例如 StandardScaler)时,它会使用所有数据点的信息来计算统计量(均值和标准差),包括最终将位于验证折叠中的数据点。这意味着应用于特定折叠训练数据的转换受到了该折叠验证数据的影响。你的模型评估结果将过于乐观,因为模型在预处理阶段实际上已经对验证数据有了“偷看”。
此图显示了导致数据泄露的错误工作流程:
在交叉验证拆分之前错误地应用预处理。缩放器使用整个数据集的信息进行拟合,包括未来的验证折叠。
Scikit-learn 的 Pipeline 对象,当与 cross_val_score 或 cross_validate 等交叉验证函数一起使用时,能正确且自动地处理这个问题。当你将管道传递给这些函数时:
fit_transform)仅在该特定折叠的训练数据上执行。转换器的内部状态(例如 StandardScaler 计算的均值/标准差)完全从该折叠的训练数据中学习。transform)应用于该折叠的验证数据。这个过程对每个折叠重复执行,结果会被汇总。重要的是,验证集的信息绝不会泄露到该折叠的训练过程中。
此图显示了在交叉验证中使用管道的正确工作流程:
正确应用,其中预处理(
fit_transform)严格发生在交叉验证循环内每个折叠的训练数据中。
将管道与 cross_val_score 或 cross_validate 结合使用非常简单。你只需将管道对象作为估计器传递。
让我们再次回顾使用 Iris 数据集进行缩放和逻辑回归的例子。
import numpy as np
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score, KFold
# 加载数据
iris = load_iris()
X, y = iris.data, iris.target
# 创建管道
pipe = Pipeline([
('scaler', StandardScaler()),
('classifier', LogisticRegression(solver='liblinear', multi_class='auto', random_state=42))
])
# 定义交叉验证策略
cv = KFold(n_splits=5, shuffle=True, random_state=42)
# 执行交叉验证
# 注意:我们将整个管道 'pipe' 作为估计器传递
scores = cross_val_score(pipe, X, y, cv=cv, scoring='accuracy')
print(f"交叉验证准确率得分: {scores}")
print(f"平均交叉验证准确率: {np.mean(scores):.4f}")
print(f"交叉验证准确率标准差: {np.std(scores):.4f}")
# 预期输出(分数可能因 KFold 随机打乱而略有不同):
# 交叉验证准确率得分: [1. 0.96666667 0.93333333 0.9 1. ]
# 平均交叉验证准确率: 0.9600
# 交叉验证准确率标准差: 0.0389
在此代码中,cross_val_score 负责整个过程:对于5个折叠中的每一个,它都会拆分数据,在训练部分拟合 StandardScaler,使用相同的已拟合缩放器转换训练和验证部分,在已转换的训练数据上训练 LogisticRegression,最后使用准确率得分在已转换的验证数据上进行评估。
同样,如果你需要更详细的结果,例如多个指标或计时信息,可以使用 cross_validate:
from sklearn.model_selection import cross_validate
# 使用相同的管道和交叉验证策略
cv_results = cross_validate(pipe, X, y, cv=cv,
scoring=['accuracy', 'precision_macro', 'recall_macro'],
return_train_score=True) # 可选:也获取训练分数
import pandas as pd
results_df = pd.DataFrame(cv_results)
print("\n交叉验证结果(DataFrame):")
print(results_df)
print(f"\n平均测试准确率: {results_df['test_accuracy'].mean():.4f}")
输出将显示一个字典(此处转换为 DataFrame 以提高可读性),其中包含每个折叠的拟合时间、评分时间以及请求的测试(可选训练)分数的数组。
通过将管道集成到你的交叉验证工作流程中,你可以实现:
这种组合代表了在 Scikit-learn 中评估机器学习 (machine learning)模型的标准做法。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•