Sklearn.eline中的LeaveOneOutEncode [英] LeaveOneOutEncoder in sklearn.pipeline

查看:0
本文介绍了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)

MyLEncodertransform()方法中。

所以这里有几个问题:

1)您的LeaveOneOutEncoder只记住传递给MyLEncodertransform的最后数据,而忘记了以前的数据。

2)试衣时LeaveOneOutEncoder要求y在场。但当MyLEncodertransform()被调用时,这在预测期间不会出现。

3)当前您的线路:

pipeline.predict(X)

是靠运气工作的,因为您的X是相同的,当调用MyLEncodertransform()时,您已经定义了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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆