无法将组合的 SMOTE 和 RandomUnderSampler 管道送入主管道

问题描述

我目前正在处理一个 Imbalanced datatset,为了处理 Imbalance,我计划将 SMOTE 和 ADASYN 与 RandomUnderSampler 结合,以及单独的欠采样、过采样、SMOTE 和 ADASYN(总共 6 种采样方式,我将通过作为 gridsearchcv 中的参数)。我为此创建了两个管道。

Smote_Under_pipeline = imb_Pipeline([
     ('smote',SMOTE(random_state=rnd_state,n_jobs=-1)),('under',RandomUnderSampler(random_state=rnd_state)),])

Adasyn_Under_pipeline = imb_Pipeline([
     ('adasyn',ADASYN(random_state=rnd_state,])

我的计划是将这两个管道送入主管道,如下所示:

Main_Pipeline = imb_Pipeline([
     ('feature_handler',FeatureTransformer(list(pearson_feature_vector.index))),('imb',Smote_Under_pipeline),('scaler',StandardScaler()),('pca',PCA(n_components=0.99)),('model',LogisticRegression(max_iter=1750)),])

FeatureTransformer()一个特征选择器类:

class FeatureTransformer(BaseEstimator,TransformerMixin):

    def __init__(self,feature_vector=None):
        self.feature_vector = feature_vector
    
    def fit(self,X,y):
        return self

    def transform(self,X):
        return X[self.feature_vector]

当我调用 Smote_Under_pipeline.fit()Adasyn_Under_pipeline.fit() 时,它有效(示例代码如下):

dumm_x,dumm_y = Smote_Under_pipeline.fit_resample(X_train,y_train)

但是当我尝试初始化 Main_Pipeline 时,解释器抛出一个错误

TypeError: All intermediate steps of the chain should be estimators that implement fit and transform or fit_resample. 'Pipeline(steps=[('smote',SMOTE(n_jobs=-1,random_state=42)),RandomUnderSampler(random_state=42))])' implements both)

我正在使用 Imbalance-learn 提供的管道。

我无法理解错误。在使用 scikit-learn 管道时,所有中间估计器都有自己的 fit()fit_transform() 方法,imblearn 管道提供了处理 fit_resample( ) 方法,由 Smote_Under_pipelineAdasyn_Under_pipeline 公开。那么,它可以在Main_Pipeline调用,那么为什么会抛出错误呢?两个采样管道都暴露了 fit() 方法以及 fit_resample(),这是原因吗?

解决方法

为了强调@glemaitre 的评论,是管道(内部管道)同时具有转换和重采样导致了问题。

因此扁平化管道(包括直接在主管道中的重采样器)似乎是解决方案。您仍然可以通过关闭各个步骤来测试不同的重采样策略作为超参数:

Main_Pipeline = imb_Pipeline([
     ('feature_handler',FeatureTransformer(list(pearson_feature_vector.index))),('oversamp',None),('undersamp',('scaler',StandardScaler()),('pca',PCA(n_components=0.99)),('model',LogisticRegression(max_iter=1750)),])

param_space = {
    'oversamp': [None,SMOTE(...),ADASYN(...),RandomOverSampler(...)],'undersamp': [None,RandomUnderSampler(...)],...,}

这将提供 8 种组合,除了您想要的组合之外,还包括 None-None 和过度欠采样。但这对我来说似乎没问题:与无重采样管道进行比较会很好,过采样与合成器欠采样组合相似。