机器学习
- Scikit-learn
- 
- 管道化与自动化建模
- 
- [Pipeline 基础](#Pipeline 基础)
- ColumnTransformer
- FeatureUnion
- [Pipeline + GridSearchCV](#Pipeline + GridSearchCV)
 
 
Scikit-learn
管道化与自动化建模
Pipeline 基础
为什么要用管道化?
先思考一个 "非管道化" 的痛点,假设我们要训练一个模型,流程通常是:
- 数据预处理(如标准化);
- 特征工程(如降维);
- 模型训练;
- 用测试集评估。
如果不用管道,代码可能是这样的:
            
            
              python
              
              
            
          
          from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
# 1. 加载数据并划分
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
# 2. 预处理:标准化(只对训练集拟合)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # 训练集:fit+transform
X_test_scaled = scaler.transform(X_test)        # 测试集:只transform(避免信息泄露)
# 3. 特征工程:PCA降维
pca = PCA(n_components=2)
X_train_pca = pca.fit_transform(X_train_scaled)  # 训练集:fit+transform
X_test_pca = pca.transform(X_test_scaled)        # 测试集:只transform
# 4. 模型训练
model = LogisticRegression()
model.fit(X_train_pca, y_train)
# 5. 评估
print("测试集准确率:", model.score(X_test_pca, y_test))这段代码看起来没问题,但实际使用中会暴露 3 个严重问题:
- 步骤割裂,容易出错:预测新数据时,必须严格重复 "标准化→PCA→预测" 的步骤,少一步或顺序错了都会导致结果错误(比如忘记 PCA 就直接预测);
- 无法与交叉验证兼容 :如果用GridSearchCV调参,需要手动在每折训练集上做 "标准化→PCA",否则会导致 "验证集信息泄露"(用了全量数据的统计信息);
- 代码冗余,难以维护:当步骤增多(如加缺失值处理、特征选择),代码会变得冗长,复用性差。
Pipeline 的核心解决方案:"封装流程,自动衔接"
Pipeline(管道)的本质是将多个建模步骤(如预处理、特征工程、模型)"串联" 成一个整体对象 ,这个对象能像单个模型一样调用fit/predict,且内部会自动处理步骤间的衔接,避免上述问题。
- 
Pipeline 的基本结构 用 Pipeline重构上面的流程,代码如下:pythonfrom sklearn.pipeline import Pipeline # 定义管道:按顺序串联3个步骤 pipe = Pipeline([ ('scaler', StandardScaler()), # 步骤1:标准化(命名为scaler) ('pca', PCA(n_components=2)), # 步骤2:PCA降维(命名为pca) ('model', LogisticRegression())# 步骤3:逻辑回归模型(命名为model) ])- 管道由有序的步骤列表 组成,每个步骤是一个元组(步骤名, 转换器/估计器);
- 转换器(Transformer) :有fit和transform方法的对象(如StandardScaler、PCA),用于数据处理;
- 估计器(Estimator) :有fit方法的对象(如LogisticRegression),通常是管道的最后一步(模型)。
 
- 管道由有序的步骤列表 组成,每个步骤是一个元组
- 
管道的 "一键训练与预测" 管道定义后,训练和预测变得极其简单: python# 1. 训练管道(自动完成:训练集标准化→PCA→模型训练) pipe.fit(X_train, y_train) # 只需传入原始训练数据,内部自动处理所有步骤 # 2. 预测(自动完成:测试集标准化→PCA→模型预测) y_pred = pipe.predict(X_test) # 传入原始测试数据,内部按训练时的步骤处理 # 3. 评估 print("测试集准确率:", pipe.score(X_test, y_test)) # 直接用管道评估
管道内部的神奇之处:
- 调用fit(X_train, y_train)时,管道会按顺序对每个步骤执行fit_transform(最后一步模型执行fit):- scaler.fit_transform(X_train)→ 得到标准化后的训练数据;
- pca.fit_transform(标准化数据)→ 得到降维后的训练数据;
- model.fit(降维数据, y_train)→ 训练模型。
 
- 调用predict(X_test)时,管道会对每个步骤执行transform(用训练时拟合的参数):- scaler.transform(X_test)→ 用训练集的均值 / 标准差标准化测试数据;
- pca.transform(标准化测试数据)→ 用训练集的 PCA 参数降维;
- model.predict(降维测试数据)→ 预测。
 
Pipeline 解决的 3 大核心问题
- 避免步骤遗漏或顺序错误:预测时无需手动重复预处理步骤,管道会自动按训练时的顺序执行,杜绝 "忘记标准化""PCA 顺序错了" 等低级错误。
- 防止信息泄露(Data Leakage) :管道与交叉验证(如GridSearchCV)结合时,会在每折训练集上单独执行fit_transform,测试集只执行transform,确保测试集的信息不会影响训练过程(这是最关键的优势!)。
- 简化代码,便于复用:将复杂流程封装成一个对象,调参、保存、部署都只需操作管道,代码更简洁,且可直接复用在新数据上。
Pipeline 注意事项
- 
步骤名的命名规则: - 步骤名可自定义(如scaler、pca),但不能包含空格或特殊字符;
- 后续调参时需要用 "步骤名__参数名" 的格式(如scaler__with_mean),所以命名要简洁易懂。
 
- 步骤名可自定义(如
- 
最后一步必须是估计器: - 管道的最后一个步骤必须是有fit方法的估计器(如模型),前面的步骤必须是有fit_transform的转换器;
- 错误示例:最后一步放PCA(转换器),管道无法调用predict(因为PCA没有predict方法)。
 
- 管道的最后一个步骤必须是有
- 
查看管道内部步骤: 用 named_steps属性可访问管道中的某个步骤,方便查看中间结果或参数:python# 查看PCA步骤的解释方差比 print("PCA解释方差比:", pipe.named_steps['pca'].explained_variance_ratio_) # 查看模型的系数 print("逻辑回归系数:", pipe.named_steps['model'].coef_)
ColumnTransformer
为什么需要 ColumnTransformer?
现实中的数据集很少只有单一类型特征,比如一份用户数据可能包含:
- 数值特征(年龄、收入)→ 需要标准化 / 归一化;
- 类别特征(性别、城市)→ 需要独热编码 / 标签编码;
- 文本特征(用户评论)→ 需要 TF-IDF 转换。
如果用普通 Pipeline,所有特征会被同一套预处理流程处理(比如对类别特征做标准化,这显然不合理)。ColumnTransformer 的作用是:按特征类型拆分数据,对不同子集应用不同的预处理,最后再合并结果。
ColumnTransformer 基础用法:分而治之
以 "混合类型特征数据集" 为例,演示流程:
- 
准备数据(含数值和类别特征) pythonimport pandas as pd # 模拟用户数据:包含2个数值特征,1个类别特征,1个目标标签 data = pd.DataFrame({ 'age': [25, 32, 47, 51, 62, 36], # 数值特征 'income': [40000, 54000, 82000, 90000, 120000, 65000], # 数值特征 'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou', 'Shanghai', 'Shenzhen'], # 类别特征 'is_purchase': [0, 1, 1, 0, 1, 0] # 目标标签(是否购买) }) X = data[['age', 'income', 'city']] # 特征(包含数值和类别) y = data['is_purchase'] # 标签
- 
定义 "特征分组" 和 "对应预处理" 首先明确哪些特征是同一类型,需要哪些预处理: - 数值特征(age、income)→ 用StandardScaler标准化;
- 类别特征(city)→ 用OneHotEncoder独热编码(生成如city_Beijing等哑变量)。
 然后用 ColumnTransformer整合这两个预处理方案:pythonfrom sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder # 1. 定义特征分组(指定哪些列属于哪类) num_features = ['age', 'income'] # 数值特征列名 cat_features = ['city'] # 类别特征列名 # 2. 定义 ColumnTransformer:对不同特征组应用不同预处理 preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), num_features), # 名称:num;处理器:StandardScaler;作用列:num_features ('cat', OneHotEncoder(), cat_features) # 名称:cat;处理器:OneHotEncoder;作用列:cat_features ])- transformers参数是一个列表,每个元素是三元组- (名称, 处理器, 特征列):- 名称:自定义(后续调参用);
- 处理器:对该组特征的预处理工具(如- StandardScaler);
- 特征列:指定哪些列属于该组(可用列名或索引,推荐列名更清晰)。
 
 
- 数值特征(
- 
整合到 Pipeline:预处理 + 模型 ColumnTransformer本身是一个 "特征预处理管道",需要和模型一起整合到Pipeline中,形成完整流程:pythonfrom sklearn.pipeline import Pipeline from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split # 1. 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 2. 定义完整管道:预处理(ColumnTransformer)→ 模型 full_pipe = Pipeline([ ('preprocessor', preprocessor), # 第一步:用ColumnTransformer处理特征 ('classifier', LogisticRegression()) # 第二步:模型训练 ]) # 3. 训练管道(自动处理不同特征) full_pipe.fit(X_train, y_train) # 4. 评估 print("测试集准确率:", round(full_pipe.score(X_test, y_test), 4))
- 
查看预处理结果(理解内部逻辑) 通过 fit_transform可查看预处理后的特征矩阵,理解ColumnTransformer如何工作:python# 对训练集应用预处理,查看结果 X_train_processed = preprocessor.fit_transform(X_train) # 打印处理后的特征矩阵(稀疏矩阵转为数组,方便查看) print("预处理后的训练集特征矩阵:") print(X_train_processed.toarray() if hasattr(X_train_processed, 'toarray') else X_train_processed) # 查看特征名称(OneHotEncoder生成的哑变量名) cat_encoder = preprocessor.named_transformers_['cat'] # 获取类别处理器 cat_feature_names = cat_encoder.get_feature_names_out(cat_features) # 哑变量列名 all_feature_names = list(num_features) + list(cat_feature_names) # 合并所有特征名 print("\n预处理后的特征名称:", all_feature_names)输出结果: mathematica测试集准确率: 0.5 预处理后的训练集特征矩阵: [[-1.39776866 -1.21755191 0. 0. 0. 1. ] [-0.21504133 -0.36401036 1. 0. 0. 0. ] [ 1.39776866 1.54390603 0. 0. 1. 0. ] [ 0.21504133 0.03765624 0. 1. 0. 0. ]] 预处理后的特征名称: ['age', 'income', 'city_Beijing', 'city_Guangzhou', 'city_Shanghai', 'city_Shenzhen']- 数值特征 age、income被标准化(均值为 0,标准差为 1);
- 类别特征 city被转为哑变量(如city_Beijing为 1 表示该样本来自北京);
- 最终特征矩阵是两部分的拼接(数值特征在前,哑变量在后)。
 
- 数值特征 
ColumnTransformer 的关键参数
- 
remainder:未指定的特征如何处理?默认情况下, ColumnTransformer只会处理transformers中指定的特征,未指定的特征会被丢弃。若想保留未指定的特征(如无需预处理的特征),可设置remainder='passthrough':python# 假设数据新增一列无需处理的特征"user_id"(直接保留) data['user_id'] = [1001, 1002, 1003, 1004, 1005, 1006] X = data[['age', 'income', 'city', 'user_id']] # 定义ColumnTransformer,保留未指定的特征(user_id) preprocessor_with_remainder = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['age', 'income']), ('cat', OneHotEncoder(), ['city']) ], remainder='passthrough' # 未指定的特征直接保留 ) # 查看结果(最后一列是未处理的user_id) X_processed = preprocessor_with_remainder.fit_transform(X) print("保留未处理特征的结果:\n", X_processed)
- 
对不同特征组用 "子管道" 如果某类特征需要多步预处理(如 "缺失值填充→标准化"),可在 ColumnTransformer中嵌套Pipeline作为处理器:pythonfrom sklearn.impute import SimpleImputer # 缺失值填充 # 数值特征的预处理子管道:先填充缺失值,再标准化 num_pipe = Pipeline([ ('imputer', SimpleImputer(strategy='median')), # 用中位数填充缺失值 ('scaler', StandardScaler()) # 标准化 ]) # 类别特征的预处理子管道:先填充缺失值,再独热编码 cat_pipe = Pipeline([ ('imputer', SimpleImputer(strategy='most_frequent')), # 用众数填充缺失值 ('encoder', OneHotEncoder()) # 独热编码 ]) # 用子管道构建ColumnTransformer preprocessor_with_pipes = ColumnTransformer([ ('num', num_pipe, num_features), ('cat', cat_pipe, cat_features) ])这种 "子管道嵌套" 的方式,能处理更复杂的预处理逻辑(如多步缺失值处理、特征转换)。 
ColumnTransformer + GridSearchCV:跨特征组调参
ColumnTransformer 中的任何处理器参数,都能通过 GridSearchCV 调优,参数名格式为:
预处理步骤名__子处理器名__参数名例如,调优数值特征的标准化方式和模型的正则化系数:
            
            
              python
              
              
            
          
          from sklearn.model_selection import GridSearchCV
# 定义参数网格(注意参数名格式)
param_grid = {
    # 调优数值预处理管道中的标准化是否减去均值(步骤名preprocessor→子步骤num→参数with_mean)
    'preprocessor__num__with_mean': [True, False],
    # 调优模型的正则化系数C(步骤名classifier→参数C)
    'classifier__C': [0.1, 1, 10]
}
# 网格搜索
grid = GridSearchCV(full_pipe, param_grid, cv=3, scoring='accuracy')
grid.fit(X_train, y_train)
print("最佳参数:", grid.best_params_)
print("最佳交叉验证准确率:", grid.best_score_.round(4))FeatureUnion
在实际特征工程中,单一的特征处理方式(如仅用 PCA 降维)往往不够,我们可能需要同时使用多种方法(如 PCA 降维和统计特征选择),再将结果合并。FeatureUnion 就是实现这一需求的工具,它能让不同的特征提取管道 "并行工作",最后汇总成果。
为什么需要 FeatureUnion?
特征工程的核心是 "尽可能保留数据中的有效信息",但不同的特征提取方法擅长捕捉不同类型的信息:
- PCA:擅长提取数据中的线性主成分,压缩维度的同时保留最大方差;
- SelectKBest:擅长根据统计量(如卡方值)筛选与标签相关性高的特征;
- 自定义特征:比如手动构造的多项式特征、交互特征等。
如果只用其中一种方法,可能会丢失其他方法能捕捉的信息。FeatureUnion 的作用是:让多个特征提取管道并行处理同一批数据,然后将各自的结果横向拼接(按列合并),形成更全面的特征矩阵。
FeatureUnion 基础用法:并行提取,合并特征
以 "鸢尾花数据集" 为例,同时用 PCA 和 SelectKBest 提取特征,再合并后输入模型:
- 
准备数据与定义特征提取管道 pythonfrom sklearn.datasets import load_iris from sklearn.decomposition import PCA from sklearn.feature_selection import SelectKBest, f_classif from sklearn.pipeline import FeatureUnion, Pipeline from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split # 加载数据 X, y = load_iris(return_X_y=True) X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42) # 定义两个并行的特征提取管道 # 管道1:PCA降维(保留2个主成分) pca_pipe = Pipeline([ ('pca', PCA(n_components=2)) ]) # 管道2:SelectKBest(筛选2个与标签最相关的特征) select_k_best_pipe = Pipeline([ ('select', SelectKBest(score_func=f_classif, k=2)) # 用f_classif计算ANOVA得分 ])
- 
用 FeatureUnion 合并特征提取结果 python# 合并两个特征提取管道:同时执行PCA和SelectKBest,结果按列拼接 feature_union = FeatureUnion([ ('pca_features', pca_pipe), # 名称:pca_features;对应管道:pca_pipe ('selected_features', select_k_best_pipe) # 名称:selected_features;对应管道:select_k_best_pipe ])- FeatureUnion的参数是一个列表,每个元素是元组- (名称, 转换器/管道),格式与- Pipeline类似;
- 每个转换器 / 管道会独立处理输入数据(如 pca_pipe处理原始特征得到 PCA 结果,select_k_best_pipe处理原始特征得到筛选后的特征);
- 最终输出是两个结果的横向拼接(例如:原始特征 4 维 → PCA 得到 2 维 + 筛选得到 2 维 → 合并后 4 维特征矩阵)。
 
- 
整合到完整管道:特征合并 + 模型训练 python# 完整管道:特征合并(FeatureUnion)→ 模型(逻辑回归) full_pipe = Pipeline([ ('feature_engineering', feature_union), # 第一步:合并特征 ('classifier', LogisticRegression(max_iter=200)) # 第二步:模型训练 ]) # 训练与评估 full_pipe.fit(X_train, y_train) print("测试集准确率:", full_pipe.score(X_test, y_test).round(4)) # 输出:1.0(性能优异)
- 
查看合并后的特征(理解内部逻辑) 通过 fit_transform查看特征合并的具体结果:python# 对训练集应用特征合并 X_train_combined = feature_union.fit_transform(X_train, y_train) # 注意:部分特征提取需要标签(如SelectKBest) print("原始训练集形状:", X_train.shape) # (112, 4) → 112样本,4特征 print("合并后训练集形状:", X_train_combined.shape) # (112, 4) → 2(PCA)+ 2(筛选)=4特征 # 查看前5个样本的合并特征 print("\n前5个样本的合并特征:") print(X_train_combined[:5, :]) # 前2列是PCA结果,后2列是SelectKBest筛选的特征输出结果: mathematica测试集准确率: 1.0 原始训练集形状: (112, 4) 合并后训练集形状: (112, 4) 前5个样本的合并特征: [[-2.77109765 0.36609042 1.4 0.2 ] [-2.68813825 0.85121143 1.5 0.1 ] [ 1.37004014 -0.55462789 5.1 1.9 ] [ 0.76518066 0.21536736 4.5 1.6 ] [ 1.17701069 0.43853186 4.7 1.5 ]]- 合并后的特征矩阵保留了两种方法的结果:PCA 捕捉的全局方差信息 + SelectKBest 捕捉的与标签相关的局部信息;
- 这种 "多源特征融合" 往往比单一方法更有效(尤其在复杂数据上)。
 
FeatureUnion 注意事项
- 
与 ColumnTransformer 结合:先分类型,再并行提取 实际场景中,常需要先按特征类型拆分(用 ColumnTransformer),再对某类特征用多种方法并行提取(用FeatureUnion)。例如:- 数值特征:同时做 PCA 和标准化 + 多项式特征;
- 类别特征:独热编码。
 示例代码: pythonfrom sklearn.preprocessing import PolynomialFeatures, StandardScaler from sklearn.compose import ColumnTransformer # 假设数据有数值特征和类别特征(此处用鸢尾花数值特征模拟) num_features = [0, 1, 2, 3] # 鸢尾花的4个数值特征(用索引) # 数值特征的并行提取管道:PCA + 标准化+多项式特征 num_feature_union = FeatureUnion([ ('pca', PCA(n_components=2)), ('poly', Pipeline([ ('scaler', StandardScaler()), ('poly', PolynomialFeatures(degree=2)) # 生成二次多项式特征 ])) ]) # 用ColumnTransformer整合(此处只有数值特征,可扩展到多类型) preprocessor = ColumnTransformer([ ('num', num_feature_union, num_features) ]) # 完整管道 pipe = Pipeline([ ('preprocessor', preprocessor), ('classifier', LogisticRegression(max_iter=200)) ]) pipe.fit(X_train, y_train) print("结合ColumnTransformer的准确率:", round(pipe.score(X_test, y_test),4))
- 
调优 FeatureUnion 中的参数 FeatureUnion中的每个子管道参数,也可通过GridSearchCV调优,参数名格式为:FeatureUnion步骤名__子管道名__子参数名例如,调优 PCA 的主成分数量和 SelectKBest 的 k 值: pythonfrom sklearn.model_selection import GridSearchCV param_grid = { # 调优PCA的n_components(feature_engineering是FeatureUnion的步骤名) 'feature_engineering__pca_features__pca__n_components': [1, 2, 3], # 调优SelectKBest的k值 'feature_engineering__selected_features__select__k': [1, 2, 3] } grid = GridSearchCV(full_pipe, param_grid, cv=3, scoring='accuracy') grid.fit(X_train, y_train) print("最佳参数:", grid.best_params_) print("最佳准确率:", grid.best_score_.round(4))
- 
特征维度膨胀问题 FeatureUnion会合并多个特征提取结果,可能导致特征维度急剧增加(如两种方法各生成 100 维特征,合并后 200 维),带来两个问题:- 计算成本上升;
- 维度灾难(过拟合风险增加)。
 解决办法: - 控制每个子管道的输出维度(如 PCA 少保留主成分,SelectKBest 少选特征);
- 合并后增加特征选择步骤(如在模型前加 SelectFromModel)。
 
Pipeline + GridSearchCV
为什么需要 "管道 + 网格搜索" 的组合?
单独使用 GridSearchCV 时,若数据需要预处理(如标准化、编码),很容易出现 "信息泄露"(用全量数据的统计信息预处理验证集)。而 Pipeline 能保证 "预处理 + 模型" 的步骤在每折交叉验证中独立执行,再结合 GridSearchCV 对整个管道的参数调优,就能实现:
- 全程无信息泄露:每折训练集单独预处理,验证集严格 "unseen";
- 参数调优全覆盖:不仅能调模型参数,还能调预处理、特征工程的参数(如 PCA 主成分数、标准化方式);
- 代码简洁可复用:一行代码启动 "预处理→特征工程→模型训练→参数优化" 全流程。
自动化调参流程(以房价预测为例)
用加州房价数据集(回归任务),构建一个包含 "预处理→特征工程→模型" 的管道,并对全流程参数调优:
- 
数据与管道设计 加州房价数据包含 8 个数值特征(如平均收入、房龄),目标是预测房价中位数(连续值)。设计的管道流程: - 预处理:数值特征标准化(StandardScaler);
- 特征工程:可选 PCA 降维(探索是否需要降维);
- 模型:随机森林回归(调优树的数量和深度)。
 
- 
管道定义 + 网格搜索 pythonfrom sklearn.datasets import fetch_california_housing from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import r2_score # 1. 加载数据并划分 data = fetch_california_housing() X, y = data.data, data.target X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 2. 定义完整管道:标准化 → 可选PCA → 随机森林 pipe = Pipeline([ ('scaler', StandardScaler()), # 步骤1:标准化 ('pca', PCA()), # 步骤2:PCA(默认保留所有特征,后续调参控制n_components) ('rf', RandomForestRegressor(random_state=42)) # 步骤3:随机森林 ]) # 3. 定义参数网格(覆盖预处理、特征工程、模型的所有待调参数) param_grid = { # 调优PCA:是否降维?降维到多少?(None表示不降维) 'pca__n_components': [None, 5, 6, 7], # None即保留原始8维特征 # 调优随机森林:树的数量 'rf__n_estimators': [50, 100], # 调优随机森林:树的最大深度(控制复杂度) 'rf__max_depth': [None, 10, 20] } # 4. 网格搜索:用5折交叉验证评估所有参数组合 grid_search = GridSearchCV( estimator=pipe, param_grid=param_grid, cv=5, # 5折交叉验证 scoring='r2', # 回归任务用R²评分 n_jobs=-1, # 并行计算 verbose=1 # 输出调参过程(可选) ) # 5. 执行搜索(自动完成:每折训练集标准化→PCA→模型训练,并评估) grid_search.fit(X_train, y_train)
- 
提取最优结果并验证 python# 1. 最优参数组合 print("最佳参数组合:\n", grid_search.best_params_) # 示例输出:{'pca__n_components': None, 'rf__max_depth': None, 'rf__n_estimators': 100} # 解读:不做PCA降维,随机森林用100棵树,不限制深度时性能最优 # 2. 最优模型的交叉验证得分 print("交叉验证最佳R²:", grid_search.best_score_.round(4)) # 示例:0.8056 # 3. 用最优模型在测试集评估(泛化能力验证) best_model = grid_search.best_estimator_ y_pred = best_model.predict(X_test) print("测试集R²:", r2_score(y_test, y_pred).round(4)) # 示例:0.8123(与交叉验证得分接近,无过拟合)
- 
分析参数对性能的影响(可选) 通过网格搜索的结果,可分析不同参数如何影响模型性能: pythonimport pandas as pd # 将交叉验证结果转为DataFrame results = pd.DataFrame(grid_search.cv_results_) # 筛选关键列:参数组合、平均得分、排名 key_results = results[['params', 'mean_test_score', 'rank_test_score']].sort_values('rank_test_score') # 显示前5个最优参数组合 print("\n前5个最优参数组合:") print(key_results.head())输出结果: mathematica最佳参数组合: {'pca__n_components': None, 'pca__svd_solver': 'full', 'rf__max_depth': None, 'rf__n_estimators': 100} 交叉验证最佳R²: 0.731 测试集R²: 0.7194 前5个最优参数组合: params ... rank_test_score 1 {'pca__n_components': None, 'pca__svd_solver':... ... 1 7 {'pca__n_components': None, 'pca__svd_solver':... ... 1 11 {'pca__n_components': None, 'pca__svd_solver':... ... 3 5 {'pca__n_components': None, 'pca__svd_solver':... ... 3 0 {'pca__n_components': None, 'pca__svd_solver':... ... 5 [5 rows x 3 columns]- 若 "pca__n_components=None"(不降维)的得分更高,说明原始特征的信息比降维后更完整;
- 若 "rf__max_depth=10" 比 "None" 好,说明模型存在过拟合,需要限制树深度。
 
这种组合将 "数据预处理→特征工程→模型训练→参数优化" 整合为一个可复用的流程,解决了手动调参的三大痛点:信息泄露、步骤繁琐、结果不稳定。记住:任何需要严谨评估和调优的机器学习项目,都应该用这种端到端的自动化流程。