管道中的 sklearn 函数转换器

Posted

技术标签:

【中文标题】管道中的 sklearn 函数转换器【英文标题】:sklearn function transformer in pipeline 【发布时间】:2017-01-17 07:22:37 【问题描述】:

在为 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

【问题讨论】:

不应该是XoneColumn = X[columnsNumber]XoneColumn = mydf[columnsNumber] 也在你的github中查看问题2,从train_test_split返回的索引是序数索引值,所以我建议在dfs上使用.ilocX_train = X.iloc[train_index] X_test = X.iloc[test_index] y_train = y.iloc[train_index] y_test = y.iloc[test_index] sklearn 代码假定一切都是 np 数组,因此您可以选择使用属性 .values 将 pandas df 转换为 np 数组或使用 pandas 索引器,例如 @987654335 @、locix @EdChurn 在单元格 3 中我转换 mydf itno 2 部分 X, y = transform(mydf) 所以 X 应该没问题。无论如何,mydf 也不能正常工作。谢谢你帮我解决了问题2。但是最后一个问题3没有解决。 如果我在这里尝试使用cv.cross_val_score(pipeline, XoneColumn.values, y, cv=folds, scoring=kappaScore).values,同样的错误仍然存​​在 【参考方案1】:

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()
)

最终会根据需要对其进行规范化。然后你可以在更多地方使用这个 sn-p 而不会乱扔你的代码 .fillna(0)

在您的示例中,您传入的是['numeric1'],它是list,而不是类似类型的df[['numeric1']] 的提取器。你可能想要的更像是

FunctionTransformer(operator.itemgetter(columns))

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

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

【讨论】:

以上是关于管道中的 sklearn 函数转换器的主要内容,如果未能解决你的问题,请参考以下文章

mlflow 如何使用自定义转换器保存 sklearn 管道?

在 sklearn 管道中转换估计器的结果

如何保存 sklearn 管道/特征转换器

如何将 sklearn 管道转换为 pyspark 管道?

sklearn 转换管道和功能联合

如何在具有多个数据帧列输入的 sklearn 管道中编写转换器