在编写第一个用于sk-learn的管道时,当只有一部分列进入管道时,我偶然发现了一些问题:

mydf = pd.DataFrame({'classLabel':[0,0,0,1,1,0,0,0],
                   'categorical':[7,8,9,5,7,5,6,4],
                   'numeric1':[7,8,9,5,7,5,6,4],
                   'numeric2':[7,8,9,5,7,5,6,"N.A"]})
columnsNumber = ['numeric1']
XoneColumn = X[columnsNumber]

我使用functionTransformer像这样:
def extractSpecificColumn(X, columns):
    return X[columns]

pipeline = Pipeline([
    ('features', FeatureUnion([
        ('continuous', Pipeline([
            ('numeric', FunctionTransformer(columnsNumber)),
            ('scale', StandardScaler())
        ]))
    ], n_jobs=1)),
    ('estimator', RandomForestClassifier(n_estimators=50, criterion='entropy', n_jobs=-1))
])

cv.cross_val_score(pipeline, XoneColumn, y, cv=folds, scoring=kappaScore)

结果为:启用功能转换器时的TypeError: 'list' object is not callable

编辑:

如果我实例化下面的ColumnExtractor,则不会返回错误。但是functionTransformer并非仅适用于像这样的简单情况,并且应该可以工作吗?
class ColumnExtractor(TransformerMixin):
    def __init__(self, columns):
        self.columns = columns

    def transform(self, X, *_):
        return X[self.columns]

    def fit(self, *_):
        return self

最佳答案

FunctionTransformer用于将功能“提升”到转换,我认为这可以帮助完成某些数据清理步骤。想象一下,您有一个主要为数字的数组,并且想用一个Transformer对其进行转换,如果它得到nan(如Normalize),它将出错。您可能最终会遇到类似

df.fillna(0, inplace=True)
...
cross_val_score(pipeline, ...)

但是也许您只需要在一次转换中使用fillna,所以不必像上面那样使用fillna
normalize = make_pipeline(
    FunctionTransformer(np.nan_to_num, validate=False),
    Normalize()
)

最终根据需要将其标准化。然后,您可以在更多地方使用该代码段,而不会用.fillna(0)乱丢您的代码

在您的示例中,您传递的是['numeric1']而不是类似类型的list的提取器df[['numeric1']]。您可能想要的更像是
FunctionTransformer(operator.itemgetter(columns))

但这仍然行不通,因为最终传递给FunctionTransformer的对象将是np.array而不是DataFrame

为了对DataFrame的特定列进行操作,您可能需要使用sklearn-pandas之类的库,该库允许您按列定义特定的转换器。

10-03 00:00