Настройка:
Во-первых, класс 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)
Что должно произойти:
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 раза.
На самом деле функция 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, вам нужно преобразовать набор поездов, прежде чем тренировать логистическую регрессию (в каждом из двух сгибов, а затем еще раз, прежде чем окончательная оценка будет подходящей).
Зачем нам нужно трансформировать набор поездов сгиба? Мы не используем эту информацию. Мы сохраняем только неверные прогнозы.