scikit-learn 快速上手指南:Estimator、Pipeline 与自动超参数搜索的完整实践

发布时间:2026/9/18 13:44:44
scikit-learn 快速上手指南:Estimator、Pipeline 与自动超参数搜索的完整实践
scikit-learn 快速上手指南Estimator、Pipeline 与自动超参数搜索的完整实践【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn本指南基于 scikit-learn 官方入门文档doc/getting_started.rst编写面向已经具备基础机器学习概念拟合、预测、交叉验证等的读者。文章将带你走完一条从训练一个模型到构建完整机器学习工作流的经典路径掌握 Estimator 的fit/predict核心 API理解 Transformer 与 Pipeline 的链式组合方式及数据泄露风险学会用交叉验证评估泛化能力并借助RandomizedSearchCV自动搜索最优超参数。读完本文你将能够独立搭建一套预处理 建模 评估 调参的完整 scikit-learn 实战流程。前置安装与准备scikit-learn 是一个支持监督学习与无监督学习的开源机器学习库并提供模型拟合、数据预处理、模型选择、模型评估等一系列工具。开始阅读前请先参照仓库中的安装说明完成环境准备并确保具备基础的机器学习实践认知模型拟合、预测、交叉验证等。本仓库代码示例假定你使用 Python 交互环境如 IPython或脚本文件运行示例中的前缀即交互式提示符。Estimator 基础一切从 fit 开始scikit-learn 将内置的数十种机器学习算法与模型统一抽象为**Estimator估计器**概念。每个 Estimator 都可以通过它的fit方法在数据上完成训练。这一抽象是所有 scikit-learn 组件的基石——不仅分类器、回归器连后面的 Transformer、Pipeline 都遵循同一套接口约定。来看一个最基础的例子用RandomForestClassifier随机森林分类器拟合一份极小的数据 from sklearn.ensemble import RandomForestClassifier clf RandomForestClassifier(random_state0) X [[ 1, 2, 3], # 2 个样本3 个特征 ... [11, 12, 13]] y [0, 1] # 每个样本所属的类别 clf.fit(X, y) RandomForestClassifier(random_state0)fit 的两个输入样本矩阵 X 与目标值 yfit方法通常接受两个输入样本矩阵设计矩阵X尺寸通常是(n_samples, n_features)即样本按行排列、特征按列排列。目标值 y回归任务中为实数分类任务中为整数或其他离散取值。对于无监督学习任务y可以不指定。y通常是一维数组其中第i个元素对应X的第i个样本行的目标值。X与y一般期望是 NumPy 数组或等价的 array-like 数据类型不过部分 Estimator 也支持稀疏矩阵等其他格式。拟合完成后即可预测Estimator 一旦完成拟合就可以直接对新数据进行预测且无需重新训练 clf.predict(X) # 预测训练数据的类别 array([0, 1]) clf.predict([[4, 5, 6], [14, 15, 16]]) # 预测新数据的类别 array([0, 1])从实现层面看所有 Estimator 都继承自 BaseEstimator。该基类提供了默认的get_params/set_params供GridSearchCV等工具读写参数、参数校验、数据校验、特征名校验与序列化能力是统一 API约定的落地点。例如RandomForestClassifier的n_estimators森林中树的数量默认 100与max_depth树的最大深度默认None即不限制都定义在其构造函数中见 sklearn/ensemble/_forest.py。如果你不确定自己的任务该选哪种模型可以参考仓库中的机器学习地图进行选型。Transformers 与预处理器变换而非预测真实机器学习工作流通常由多个环节组成一个典型的流程包含预处理步骤变换或插补数据与最终预测器预测目标值。在 scikit-learn 中预处理器和转换器遵循与 Estimator相同的 API 约定——它们实际上同样继承自BaseEstimator基类。区别在于Transformer没有predict方法取而代之的是transform方法输出一份变换后的新样本矩阵X from sklearn.preprocessing import StandardScaler X [[0, 15], ... [1, -10]] # 根据计算出的缩放参数对数据进行标准化 StandardScaler().fit(X).transform(X) array([[-1., 1.], [ 1., -1.]])StandardScaler 的底层原理以示例中的StandardScaler为例它通过移除均值并缩放到单位方差来完成标准化标准分数计算公式为z (x - u) / s其中u是训练样本的均值s是训练样本的标准差。均值和标准差在fit阶段按特征独立计算并存储供之后transform新数据使用详见 sklearn/preprocessing/_data.py。该缩放器有三个关键参数值得注意参数默认值作用copyTrue是否避免复制并原地缩放数据with_meanTrue缩放前是否居中对稀疏矩阵必须设为False否则会构建稠密矩阵导致内存问题with_stdTrue是否缩放到单位方差拟合后生成的属性包括mean_每特征均值、var_每特征方差与scale_每特征缩放因子。标准化是很多机器学习算法的常见前置条件——例如 SVM 的 RBF 核、线性模型的 L1/L2 正则项都假设特征围绕 0 居中且量级一致否则量级过大的特征会主导目标函数导致模型无法正确学习其他特征。对不同特征应用不同变换ColumnTransformer有时你希望对不同特征应用不同的变换。此时应使用 ColumnTransformer它允许按列指定不同的变换器例如对数值列做标准化、对类别列做独热编码是处理异构表格数据的标准组件。Pipelines链式组合预处理器与估计器Transformer 与预测器可以组合进一个统一对象Pipeline管道。管道提供与普通 Estimator 相同的 API——可以整体fit、整体predict。更关键的是使用管道能防止数据泄露data leakage即避免测试集信息混入训练数据。以下示例加载鸢尾花数据集Iris划分为训练集与测试集并用管道在测试集上计算准确率 from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.pipeline import make_pipeline from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score ... # 创建管道对象 pipe make_pipeline( ... StandardScaler(), ... LogisticRegression() ... ) ... # 加载鸢尾花数据集并划分为训练集与测试集 X, y load_iris(return_X_yTrue) X_train, X_test, y_train, y_test train_test_split(X, y, random_state0) ... # 拟合整个管道 pipe.fit(X_train, y_train) Pipeline(steps[(standardscaler, StandardScaler()), (logisticregression, LogisticRegression())]) # 现在可以像使用任何其他 Estimator 一样使用它 accuracy_score(pipe.predict(X_test), y_test) 0.97...Pipeline 的接口约定与参数访问从 Pipeline 实现 可以看到它的接口约定中间步骤必须是 Transformer即必须实现fit和transform两个方法最后一步预测器只需实现fit所有步骤必须定义fit与 scikit-learn API 兼容。构造方式有两种显式的Pipeline([(name, estimator), ...])元组列表或便捷函数make_pipeline(...)按位置自动生成步骤名。管道还支持通过named_steps属性按名字访问任意步骤通过步骤名__参数名语法双下划线分隔设置某一步的参数例如pipe.set_params(logisticregression__C0.1)——这为后面的对管道做超参数搜索铺平了道路通过memory参数缓存耗时步骤的拟合结果。为什么管道能防止数据泄露设想一个反例如果你不使用管道先把标准化等预处理应用到整个数据集再执行任意形式的交叉验证就会破坏训练数据与测试数据相互独立这一基本假设。因为预处理使用了全量数据测试集的部分信息已经泄漏给了训练集最终会高估模型的泛化能力。而把预处理放进管道每次交叉验证折内都只使用训练折的数据来拟合预处理参数从机制上规避了这一常见陷阱。模型评估train_test_split 与交叉验证模型在训练数据上拟合良好并不代表它对未见数据预测得好泛化性能必须直接评估。前面我们已经用过train_test_split这个把数据集划分为训练集与测试集的辅助函数而 scikit-learn 还提供了大量其他评估工具尤其是交叉验证cross-validation相关能力。train_test_split 的关键参数train_test_split定义见 sklearn/model_selection/_split.py支持以下参数test_size浮点数0.0~1.0测试集比例或整数测试样本绝对数量默认None此时若train_size也为None测试集取 0.2525%。train_size训练集比例或样本数默认自动取测试集的补集。random_state控制切分前的打乱传入整数可获得可复现的结果。shuffle是否在切分前打乱数据默认True。stratify传入类别标签后按分层策略切分保证训练/测试集中类别比例一致对不平衡分类数据尤为重要。5 折交叉验证cross_validate下面演示用cross_validate辅助函数执行一次 5 折交叉验证。注意你也可以手动迭代折、使用不同的数据划分策略、使用自定义评分函数详见交叉验证用户指南 from sklearn.datasets import make_regression from sklearn.linear_model import LinearRegression from sklearn.model_selection import cross_validate ... X, y make_regression(n_samples1000, random_state0) lr LinearRegression() ... result cross_validate(lr, X, y) # 默认 5 折交叉验证 result[test_score] # r_squared 分数很高因为这个数据集很简单 array([1., 1., 1., 1., 1.])cross_validate实现见 sklearn/model_selection/_validation.py在评估之外还会记录拟合与评分时间。几个值得记住的默认行为cvNone时的默认策略当估计器是分类器且y为二分类或多分类时使用StratifiedKFold分层 K 折其余情况使用KFold均为 5 折且shuffleFalse保证多次调用结果一致。scoringNone时使用估计器自带的默认评估准则也可传入字符串评分名、可调用对象或字典以实现多指标评估。n_jobs控制跨折并行训练-1表示使用全部处理器。通过return_train_score默认False可以额外返回训练集得分用于分析过拟合/欠拟合权衡return_estimatorTrue可保留每折拟合的模型对象。自动参数搜索RandomizedSearchCV 与 GridSearchCV所有估计器都有可调参数文献中常称超参数而估计器的泛化能力往往严重依赖其中少数几个参数。例如RandomForestRegressor的n_estimators决定森林中的树数量max_depth决定每棵树的最大深度。这些参数的合适取值高度依赖当前数据通常难以凭经验确定。scikit-learn 提供了通过交叉验证自动寻找最佳参数组合的工具。下面的例子用RandomizedSearchCV在随机森林的参数空间中做随机搜索。搜索结束后RandomizedSearchCV对象表现得就像一个用最优参数组合拟合过的RandomForestRegressor from sklearn.datasets import make_regression from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import RandomizedSearchCV from sklearn.model_selection import train_test_split from scipy.stats import randint ... # 创建合成数据集 X, y make_regression(n_samples20640, ... n_features8, ... noise0.1, ... random_state0) X_train, X_test, y_train, y_test train_test_split(X, y, random_state0) ... # 定义将被搜索的参数空间 param_distributions {n_estimators: randint(1, 5), ... max_depth: randint(5, 10)} ... # 创建搜索对象并拟合数据 search RandomizedSearchCV(estimatorRandomForestRegressor(random_state0), ... n_iter5, ... param_distributionsparam_distributions, ... random_state0) search.fit(X_train, y_train) RandomizedSearchCV(estimatorRandomForestRegressor(random_state0), n_iter5, param_distributions{max_depth: ..., n_estimators: ...}, random_state0) search.best_params_ {max_depth: 9, n_estimators: 4} # 搜索对象现在表现像一个普通的随机森林估计器 # 且已使用 max_depth9 和 n_estimators4 search.score(X_test, y_test) 0.84...搜索对象的关键属性与孪生兄弟 GridSearchCVRandomizedSearchCV继承自BaseSearchCV见 sklearn/model_selection/_search.py 与 L1726搜索完成后会自动在全部数据上以最优参数重新拟合一个估计器暴露为best_estimator_属性记录best_params_最优参数、best_score_最优参数在交叉验证上的平均得分与cv_results_全部候选的详细得分表当refitTrue默认时搜索对象直接转发predict、predict_proba、score、transform等方法给best_estimator_这就是示例中search.score(X_test, y_test)能直接工作的原因。它的孪生兄弟是GridSearchCV当参数空间较小时可以用它做穷举式网格搜索RandomizedSearchCV则用n_iter控制采样次数适合更大的参数空间。二者都支持对多指标评分通过scoring传字典并通过refit指定用于选优的指标。重要实践建议对 Pipeline 进行搜索在实践中你几乎总是应该对管道Pipeline进行搜索而不是对单个估计器搜索。原因回到上文的数据泄露如果对整个数据集先做预处理再交叉验证同样会破坏训练/测试独立性。将预处理步骤与最终预测器一起放进管道后再做交叉验证与搜索就能从机制上规避这一常见陷阱。配合步骤名__参数名语法你可以在一次搜索中同时调节预处理参数如standardscaler__with_mean与模型参数如logisticregression__C详见组合估计器与网格搜索。后续学习路径至此本文已覆盖估计器的拟合与预测、预处理步骤、管道、交叉验证工具与自动超参数搜索。这份指南为你勾勒了库中核心特性的全景但 scikit-learn 的能力远不止于此。接下来你可以阅读用户指南系统了解所有内置工具的细节查阅 API 参考获取公开 API 的完整清单浏览仓库 examples 目录下的大量示例观察 scikit-learn 在分类、聚类、回归、文本处理、模型可解释性等不同场景下的实际用法。这些示例大多采用一个示例一个文件的脚本形式配合 doc/modules 下的专题文档是你从入门走向熟练的进阶路线。【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考