Sklearn StackingClassifer с конвейером

Настройка:

  • У меня есть набор данных с некоторыми 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)

Что должно произойти:

  • Логистическая регрессия подходит для всего набора данных для последующего прогнозирования (здесь не используется)
  • Чтобы функцию можно было передать в 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 раза.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python.
Некоторые методы, о которых вы не знали, что они существуют в Python.
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
404
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

На самом деле функция fit() в lr_pipe вызывается 3 раза, а функция transform() вызывается 5 раз. Вы можете увидеть это, добавив print() внутри вашей fit() функции.

Согласно документации StackingClassifier:

Обратите внимание, что estimators_ установлены на полную X, а final_estimator_ обучается с использованием перекрестно проверенных прогнозов базовых оценок с использованием cross_val_predict.

В то время как ваш estimator установлен на полном X, transform() вызывается один раз, но чтобы соответствовать final_estimator, transform() вызывается 2 * 2 раза (для набора поездов и набора проверки, из 2 раз).

Зачем нам нужно трансформировать набор поездов сгиба? Мы не используем эту информацию. Мы сохраняем только неверные прогнозы.

Jonathan 18.12.2020 22:25

@Jonathan, вам нужно преобразовать набор поездов, прежде чем тренировать логистическую регрессию (в каждом из двух сгибов, а затем еще раз, прежде чем окончательная оценка будет подходящей).

Ben Reiniger 18.12.2020 22:31

Другие вопросы по теме