如何编写适配Sklearn Pipeline的自定义类实现高相关特征剔除并解决运行报错
全问题修复方案
报错根因对应拆解
'MyDecorrelator' object has no attribute 'set_params':自定义去相关类未继承scikit-learn 标准化 estimator 基类,缺少框架要求的参数读写接口,Pipeline 与 HalvingGridSearchCV 无法统一调度该步骤。'numpy.ndarray' object has no attribute 'corr':Pipeline 中上游的 MinMaxScaler 输出为 numpy 格式数组,并非带列名的 pandas DataFrame,原代码直接调用 pandas 专属的.corr()方法触发格式不匹配错误。- 非有限分数警告:原
MyDecorrelator实现存在多处逻辑缺陷,包括:- 调用
X.drop()时设置inplace=True,该操作会直接返回None,导致下游步骤接收到空值 - 未在 fit 阶段记录待删除的特征索引,而是在 transform 阶段临时计算相关矩阵,违背 sklearn 转换器的流程规范,交叉验证时极易出现数据泄露或维度不匹配
- 高相关特征筛选逻辑和后续 SelectKBest 的 k 值没有联动校验,出现剩余可筛选特征数小于 SelectKBest 指定的 k 值时,模型输入维度异常,最终输出 nan 分数。
- 调用
修复后的核心自定义转换器代码
将原有 MyDecorrelator 替换为符合 sklearn 接口规范的实现,全流程兼容 numpy 数组输入、无 pandas 依赖、无 inplace 副作用:
import numpy as np from sklearn.base import BaseEstimator, TransformerMixin class MyDecorrelator(BaseEstimator, TransformerMixin): def __init__(self, threshold=0.9): self.threshold = threshold # 存储fit阶段识别出的需保留特征索引,避免transform阶段重复计算 self.kept_feature_indices_ = None def fit(self, X, y=None): # 计算特征间皮尔逊相关矩阵,适配numpy数组输入 corr_matrix = np.corrcoef(X, rowvar=False) n_total_features = corr_matrix.shape[0] correlated_col_idx = set() for i in range(n_total_features): for j in range(i): # 筛选相关系数绝对值超过阈值的列,保留排序靠前的列 if abs(corr_matrix[i, j]) > self.threshold: correlated_col_idx.add(i) # 计算最终保留的特征索引 all_feature_idx = set(range(n_total_features)) self.kept_feature_indices_ = np.array(sorted(all_feature_idx - correlated_col_idx)) return self def transform(self, X, y=None): if self.kept_feature_indices_ is None: raise ValueError("需先调用fit方法拟合数据,再执行特征转换") # 仅根据预存的索引筛选特征,无inplace副作用 return X[:, self.kept_feature_indices_]
网格搜索环节的配套修正
对原有 Pipeline 和 HalvingGridSearchCV 参数做针对性调整,避免错误被吞掉为 nan 值:
# 调整HalvingGridSearchCV参数,开启错误抛出模式,避免nan分数掩盖真实问题 grid = HalvingGridSearchCV( estimator=estimator, param_grid=param_grid, n_jobs=-1, cv=KFold(n_splits=5), verbose=10, error_score="raise" # 遇到维度不匹配、输入异常等问题时直接抛出错误,不返回nan )
额外注意事项
- 新版 TensorFlow 的
KerasRegressor已将原有的build_fn参数更名为build,若使用较新版本的 tensorflow 需同步修正该参数名 - 交叉验证过程中需保证
MyDecorrelator去相关后剩余的特征数大于等于SelectKBest设置的k值,否则会触发维度不匹配错误,可通过error_score="raise"快速定位这类问题 - 原代码中
transform方法的inplace=True属于致命bug,即使将输入转为DataFrame,该操作也会直接返回None,导致Pipeline流程中断
内容的提问来源于stack exchange,提问作者Gio
相关产品推荐
相关产品推荐

