Вы звоните
encc = enc.fit(np.asarray(X), y)
в методе transform()
из MyLEncoder
.
Итак, здесь есть пара проблем:
1) Ваш LeaveOneOutEncoder
запоминает только последние данные, переданные в transform
из MyLEncoder
, и забывает предыдущие данные.
2) Во время установки LeaveOneOutEncoder
требуется наличие y
.Но это не будет присутствовать во время предсказания, когда вызывается MyLEncoder
transform()
.
3) В настоящее время ваша строка:
pipeline.predict(X)
работает просто по счастливой случайности, потому что ваш X
то же самое, и когда вызывается MyLEncoder
transform()
, вы уже определили y
, поэтому он используется.Но это просто неправильно.
4) Несвязанная вещь (нельзя назвать это ошибкой).Когда вы делаете это:
pipeline.predict(pd.DataFrame({ 'y': [3, 8], 'a': ['a', 'b' ], 'b': [3, 6],}))
pipeline.predict()
требует только X
, а не y
.Но вы также отправляете y
.В настоящее время это не проблема, поскольку в конвейере вы используете только столбец a
и выбрасываете всю информацию, но, возможно, в сложных настройках это может ускользнуть, и данные, представленные в столбце y
, будут использоваться в качестве функций (X
data), который затем даст вам неправильные результаты.
Чтобы решить эту проблему, измените MyLEncoder
на:
class MyLEncoder(BaseEstimator, TransformerMixin):
# Save the enc during fitting
def fit(self, X, y, **fit_params):
enc = LeaveOneOutEncoder()
self.enc = enc.fit(np.asarray(X), y)
return self
# Here, no new learning should be done, so never call fit() inside this
# Only use the already saved enc here
def transform(self, X, **fit_params):
enc_data = self.enc.transform(np.asarray(X))
return enc_data
# No need to define this function, if you are not doing any optimisation in it.
# It will be automatically inherited from TransformerMixin
# I have only kept it here, because you kept it.
def fit_transform(self, X,y=None, **fit_params):
self.fit(X, y, **fit_params)
return self.transform(X)
Теперь, когда вы сделаете это:
pipeline.predict(pd.DataFrame({ 'y': [3, 8], 'a': ['a', 'b' ], 'b': [3, 6],}))
Вы не получите никакой ошибки, но все же, как сказано в пункте 4, я бы хотел, чтобы вы сделали что-то вроде этого:
new_df = pd.DataFrame({ 'y': [3, 8], 'a': ['a', 'b' ], 'b': [3, 6],})
new_X = new_df[['a', 'b']]
new_y = new_df['y']
pipeline.predict(new_X)
, чтобы X использовал время обучения, а new_X использовал время прогнозирования.появляются так же.