LeaveOneOutEncoder in sklearn.pipeline(Sklearn.eline中的LeaveOneOutEncode)
问题描述
我使用LeaveOneOutEncode创建了一个管道。当然,我用了一个玩具的例子。Leave One Out用于转换类别变量
import pandas as pd
import numpy as np
from sklearn import preprocessing
import sklearn
from sklearn.pipeline import Pipeline
from sklearn.pipeline import FeatureUnion
from category_encoders import LeaveOneOutEncoder
from sklearn import linear_model
from sklearn.base import BaseEstimator, TransformerMixin
df= pd.DataFrame({ 'y': [1,2,3,4,5,6,7,8], 'a': ['a', 'b','a', 'b','a', 'b','a', 'b' ], 'b': [5,5,3,4,8,6,7,3],})
class ItemSelector(BaseEstimator, TransformerMixin):
def __init__(self, key):
self.key = key
def fit(self, x, y=None):
return self
def transform(self, data_dict):
return data_dict[self.key]
class MyLEncoder(BaseEstimator, TransformerMixin):
def transform(self, X, **fit_params):
enc = LeaveOneOutEncoder()
encc = enc.fit(np.asarray(X), y)
enc_data = encc.transform(np.asarray(X))
return enc_data
def fit_transform(self, X,y=None, **fit_params):
self.fit(X,y, **fit_params)
return self.transform(X)
def fit(self, X, y, **fit_params):
return self
X = df[['a', 'b']]
y = df['y']
regressor = linear_model.SGDRegressor()
pipeline = Pipeline([
# Use FeatureUnion to combine the features
('union', FeatureUnion(
transformer_list=[
# categorical
('categorical', Pipeline([
('selector', ItemSelector(key='a')),
('one_hot', MyLEncoder())
])),
# year
])),
# Use a regression
('model_fitting', linear_model.SGDRegressor()),
])
pipeline.fit(X, y)
pipeline.predict(X)
我在列车和测试数据上使用它时,这些都是正确的!但当我尝试预测新数据时,出现错误
pipeline.predict(pd.DataFrame({ 'y': [3, 8], 'a': ['a', 'b' ], 'b': [3, 6],}))
帮助查找错误!这个错误肯定很简单,但我的眼睛湿透了。问题一定出在MyLEncoder类中。我必须更改什么?
推荐答案
您正在呼叫
encc = enc.fit(np.asarray(X), y)
在MyLEncoder
的transform()
方法中。
所以这里有几个问题:
1)您的LeaveOneOutEncoder
只记住传递给MyLEncoder
的transform
的最后数据,而忘记了以前的数据。
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
数据),这将给您错误的结果。
若要解决此问题,请将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看起来相同。
这篇关于Sklearn.eline中的LeaveOneOutEncode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!