本文介绍了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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!