sklearn StackingClassifer 与管道

Posted

技术标签:

【中文标题】sklearn StackingClassifer 与管道【英文标题】:sklearn StackingClassifer with pipeline 【发布时间】:2021-03-29 11:46:46 【问题描述】:

设置:

我有一个包含一些 NaN 的数据集。 我想拟合 LogisticRegression 并将这些预测输入 HistGradiantBoostingClassifier 我希望 HistGradiantBoostingClassifier 使用其自己的内部 NaN 处理

首先,Debug 类可以帮助查看发生了什么

from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np

class Debug(BaseEstimator, TransformerMixin):
    
    def __init__(self, msg='DEBUG'):
        self.msg=msg

    def transform(self, X):
        self.shape = X.shape
        print(self.msg)
        print(f'Shape: self.shape')
        print(f'NaN count: np.count_nonzero(np.isnan(X))')
        return X

    def fit(self, X, y=None, **fit_params):
        return self

现在是我的管道

from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.ensemble import StackingClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer

data = load_breast_cancer()
X = data['data']
y = data['target']

X[0, 0] = np.nan   # make a NaN

lr_pipe = make_pipeline(
    Debug('lr_pipe START'),
    SimpleImputer(),
    StandardScaler(),
    LogisticRegression()
)

pipe = StackingClassifier(
    estimators=[('lr_pipe', lr_pipe)],
    final_estimator=HistGradientBoostingClassifier(),
    passthrough=True, 
    cv=2,
    verbose=10
)

pipe.fit(X, y)

应该发生什么:

Lo​​gisticRegression 适合整个数据集以供以后预测(此处未使用) 为了将特征输入 HGB,LogisticRegression 需要cross_val_predict,我指定了 2 折。我应该看到lr_pipe 被称为两次,以便生成折叠预测。

实际会发生什么:


lr_pipe START
Shape: (569, 30)
NaN count: 1

lr_pipe START
Shape: (284, 30)
NaN count: 0

lr_pipe START
Shape: (285, 30)
NaN count: 1

lr_pipe START
Shape: (285, 30)
NaN count: 1

lr_pipe START
Shape: (284, 30)
NaN count: 0
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   1 out of   1 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done   2 out of   2 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done   2 out of   2 | elapsed:    0.0s finished

为什么lr_pipe 被调用了 5 次?我应该看到它被调用了 3 次。

【问题讨论】:

【参考方案1】:

其实lr_pipefit()函数被调用了3次,而transform()函数被调用了5次。您可以通过在 fit() 函数中添加 print() 来查看它。

根据StackingClassifier的文档:

请注意estimators_ 安装在完整的X 上,而final_estimator_ 使用cross_val_predict 对基本估计器的交叉验证预测进行训练。

当你的estimator 被完整地安装在X 上时,transform() 被调用了一次,但是为了适应final_estimatortransform() 被调用了 2*2 次(对于训练集和验证套,2折)。

【讨论】:

为什么我们需要变换折叠的训练集?我们没有使用这些信息。我们只保留不相关的预测。 @Jonathan,您需要在训练逻辑回归之前转换训练集(在 2 折中的每一个上,然后在最终估计器拟合之前再次)。

以上是关于sklearn StackingClassifer 与管道的主要内容,如果未能解决你的问题,请参考以下文章

无法从 sklearn.externals.joblib 导入 Sklearn

sklearn的PCA

sklearn数据库-老鱼学sklearn

使用sklearn画二分类模型ROC曲线,PR曲线

Keras Sklearn Tuner 模块“sklearn”没有属性“管道”

导入sklearn时出现conda sklearn错误