为了账号安全,请及时绑定邮箱和手机立即绑定

如何创建预处理管道,包括内置的 scikit 学习转换器、自定义转换器,其中之一用于特征工程?

如何创建预处理管道,包括内置的 scikit 学习转换器、自定义转换器,其中之一用于特征工程?

泛舟湖上清波郎朗 2023-06-20 10:49:09
概括我正在努力创建一个带有内置转换器和自定义转换器的预处理管道,其中包括一个可以向数据添加额外属性并进一步对添加的属性执行转换的转换器。附加属性示例:有一个 phValue 属性缺少数据。我想尝试创建一个附加属性,该属性将在 phLabel 列中将 phValue 标记为 (Acid, Neutral, Base)。也是每个序列特征的字符串长度。这将需要输入 phValue 的缺失值,然后创建其他属性和进一步的转换器,这些转换器也将转换 sequence_length 属性。我可怕的变压器。这是我如何创建自定义转换器的示例,我可以将其用于手动预处理,但是,在创建完整的预处理管道时,这不是处理它的正确方法。def data_to_frame(X):    if isinstance(X, pd.DataFrame):        return X    elif isinstance(X, sparse.csr_matrix):        return pd.DataFrame(X, indices, atributes)    elif isinstance(X, np.ndarray):        return pd.DataFrame(X, indices, atributes)    else:        raise Exception("Incorrect Data Structure Passed")class CombinedAttributesAdder(BaseEstimator, TransformerMixin):    def __init__(self, no_difference = True): # no *args or **kargs        self.no_difference = no_difference    def fit(self, X, y=None):        return self # nothing else to do    def transform(self, X):        atributes.extend(['sequence_length', 'difference', 'phLabel'])        sequence_length = X.sequence.str.len()        difference = X['residueCount'] - sequence_length        phLabel = X['phValue'].apply(ph_labels)        if self.no_difference:            atributes.append('no_difference')            no_difference = (difference == 0)            return np.c_[X, sequence_length, difference, phLabel, no_difference]        else:            return np.c_[X, sequence_length, difference, phLabel]变形金刚中的 Pandas 操作。我想在变形金刚中执行的操作特定于熊猫。我的解决方案是将输入的 numpy 数组转换为数据帧,并在转换函数中将其作为 numpy 数组返回。我将全局变量用于属性和索引。我意识到这是一种乏善可陈的方法。我如何在我的自定义转换器中使用 pandas 操作?
查看完整描述

1 回答

?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

这应该按预期工作——很可能你的实现有问题——可以尝试处理一个虚拟数据集。并不TransformerMixin真正关心输入是numpy还是pandas.DataFrame,它将按“预期”工作。


import pandas as pd

import numpy as np

from sklearn.base import TransformerMixin

from sklearn.preprocessing import StandardScaler

from sklearn.preprocessing import FunctionTransformer

from sklearn.pipeline import make_pipeline



class CustomTransformer(TransformerMixin):

    def __init__(self, some_stuff=None, column_names= []):

        self.some_stuff = some_stuff

        self.column_names = column_names

    def fit(self, X, y=None):

        return self


    def transform(self, X):

        # do stuff on X, and return dataframe

        # of the same shape - this gets messy

        # if the preceding item is a numpy array

        # and not a dataframe

        if isinstance(X, np.ndarray):

            X = pd.DataFrame(X, columns=self.column_names)

        

        X['str_len'] = X['my_str'].apply(lambda x: str(x)).str.len()

        X['custom_func'] = X['val'].apply(lambda x: 1 if x > 0.5 else -1)

        return X



df = pd.DataFrame({

    'my_str': [111, 2, 3333],

    'val': [0, 1, 1]

})


# mixing this works as expected

my_pipeline = make_pipeline(StandardScaler(), CustomTransformer(column_names=["my_str", "val"]))

my_pipeline.fit_transform(df)


# using this by itself works as well

my_pipeline = make_pipeline(CustomTransformer(column_names=["my_str", "val"]))

my_pipeline.fit_transform(df)

输出是:


In [  ]: my_pipeline = make_pipeline(StandardScaler(), CustomTransformer(column_names=["my_str", "val"])) 

    ...: my_pipeline.fit_transform(df)                                                                                                                                                                                                  

Out[  ]: 

     my_str       val  str_len  custom_func

0 -0.671543 -1.414214       19           -1

1 -0.742084  0.707107       18            1

2  1.413627  0.707107       17            1


In [  ]: my_pipeline = make_pipeline(CustomTransformer(column_names=["my_str", "val"])) 

    ...: my_pipeline.fit_transform(df)                                                                                                                                                                                                  

Out[  ]: 

   my_str  val  str_len  custom_func

0     111    0        3           -1

1       2    1        1            1

2    3333    1        4            1


sklearn-pandas或者,如果您想直接将事物映射到数据框,则可以使用


from sklearn_pandas import DataFrameMapper


# using sklearn-pandas

str_transformer = FunctionTransformer(lambda x: x.apply(lambda y: y.str.len()))

cust_transformer = FunctionTransformer(lambda x: (x > 0.5) *2 -1)



mapper = DataFrameMapper([

    (['my_str'], str_transformer),

    (['val'], make_pipeline(StandardScaler(), cust_transformer))

], input_df=True, df_out=True)


mapper.fit_transform(df)

输出:


In [  ]: mapper.fit_transform(df)                                                                                                                                                                                                       

Out[47]: 

   my_str  val

0       3   -1

1       2    1

2       1    1


使用 sklearn pandas 可以让您更具体地将输入作为数据框,将输出作为数据框,并允许您将每一列单独映射到每个感兴趣的管道,而不是将列名编码/硬编码为对象的一部分TransformerMixin。


查看完整回答
反对 回复 2023-06-20
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信