【问题标题】:How to apply each step on sklearn Pipeline on selected columns?如何在选定列上应用 sklearn Pipeline 上的每个步骤?
【发布时间】:2021-01-23 08:49:45
【问题描述】:

当我在查找如何准备好 sklearn.Pipeline 中的一个步骤以仅在某些列上运行时,我偶然发现了 sklearn.Pipeline.FeatureUnion from this answer on stackoverflow。但是,我不太清楚,如何不对我不想要的列应用任何东西并将完整的数据传递到下一步。例如,在我的第一步中,我只想在某些列上应用StandardScaler,可以使用下面显示的代码来完成,但问题是下一步将只有标准缩放的列。如何在下一步中使用从上一步标准缩放的列获得完整数据?

下面是一些示例代码:

from sklearn.pipeline import Pipeline, FeatureUnion, make_pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.neighbors import KNeighborsClassifier

class Columns(BaseEstimator, TransformerMixin):
    def __init__(self, names=None):
        self.names = names

    def fit(self, X, y=None, **fit_params):
        return self

    def transform(self, X):
        return X[self.names]


pipe = Pipeline([
    # steps below applies on only some columns
    ("features", FeatureUnion([
        ('numeric', make_pipeline(Columns(names=[list of numeric column names]), StandardScaler())),
    ])),
    ('feature_engineer_step1', FeatEng_1()),
    ('feature_engineer_step2', FeatEng_2()),
    ('feature_engineer_step3', FeatEng_3()),
    ('remove_skew', Skew_Remover()),

    # below step applies on all columns
    ('model', RandomForestRegressor())
])

编辑:

由于选择的答案没有任何示例代码,我将我的粘贴在这里,以供可能遇到此问题并希望找到有效代码的任何人使用。 下例中使用的数据是google colab自带的加州住房数据。

from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestRegressor

# writing a column transformer that operates on some columns
num_cols = ['housing_median_age', 'total_rooms','total_bedrooms', 'population', 'households', 'median_income']
p_stand_scaler_1 = ColumnTransformer(transformers=[('stand_scale', StandardScaler(), num_cols)],
                                     # set remainder to passthrough to pass along all the un-specified columns untouched to the next steps
                                     remainder='passthrough')

# make a pipeline now with all the steps
pipe_1 = Pipeline(steps=[('standard_scaler', p_stand_scaler_1),
                         ('rf_regressor', RandomForestRegressor(random_state=100))])

# pass the data now to fit
pipe_1.fit(house_train.drop('median_house_value', axis=1), house_train.loc[:,'median_house_value'])

# make predictions
pipe_predictions = pipe_1.predict(house_test.drop('median_house_value', axis=1))

【问题讨论】:

  • 如果 feat_eng1() 是一种通用转换,可以应用于任何两列,例如 additon,subtraction 。所以我想将特征名称传递给转换器并将结果存储在具有此特征名称的数据框中是可能的
  • 我无法完全理解你。您希望您的转换器将完整的数据框作为输入并将一些转换功能(例如加法或减法)应用到两列,是吗?如果是,那是可能的,我已经做到了。
  • def transform(self,X,y=None): for tpl in self.dif_columns: print('diff caclulator') X.loc[:,tpl[2]] = X[tpl[ 0]] - X[tpl[1]] return X 这就是我想要做的。我将一个元组('AMT_PMT','AMT_INST','AMT_PER') 传递给构造函数。元组有两列第三项是新列名。我收到两个错误 1. settingwithcopy 使用 loc 2. 关键字不能是表达式。第二个错误是新列名必须是硬编码的并且不能是表达式。因此你能分享你的 feat_eng1() 结构吗
  • 请打开一个新问题并在此处发布它的网址。我会尽力回答。以这种方式查看代码并理解它并不容易。
  • 链接到我在上面的评论中谈到的问题stackoverflow.com/questions/65164203/…

标签: python python-3.x scikit-learn pipeline


【解决方案1】:

您可以使用 sklearn 中的 ColumnTransformer。这是一个可以帮助您的 sn-p。

from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import RandomForestClassifier

#transform columns
#num_cols = numerical columns, categorical_col = categorical columns
preprocessor = ColumnTransformer(transformers = [('minmax',MinMaxScaler(), num_cols),
                                                 ('onehot', OneHotEncoder(), categorical_col)])

#model
model = RandomForestClassifier(random_state=0)

#model pipeline
model_pipeline = Pipeline(steps=[('preprocessor', preprocessor), ('model', model)])

model_pipeline.fit(x_train, y_train)

【讨论】:

  • 在示例中,您在数值列上使用了 minm max 缩放器,在分类列上使用了一个热编码器。我必须在该示例中进行哪些更改才能仅在该步骤中应用 min max scaler 并让所有其他列保持不变并将所有这些都传递到下一步?
  • 只需从 ColumnTransformer 中移除一个热编码器
  • 我发现删除它会删除列转换器中未指定的列,并且只将指定的列传递到下一步。一个名为 remainder='passthrough' 的参数必须显式设置为不删除并在列转换器中包含未指定的列。
【解决方案2】:

我相信使用 ColumnTransformer(来自 sklearn.compose import ColumnTransformer)应该可以解决问题。

在实例化列转换器时,您可以设置剩余的='passthrough',这将使剩余的列保持不变。
然后,第一步使用列转换器实例化一个管道对象。
这样,下一个管道步骤将根据需要接收所有列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-17
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 2021-04-09
    • 1970-01-01
    • 2018-12-29
    • 2021-08-29
    相关资源
    最近更新 更多