管道中的 sklearn 函数转换器
sklearn function transformer in pipeline
为 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
用于 "lift" 转换函数,我认为这有助于一些数据清理步骤。想象一下,你有一个主要是数字的数组,你想用一个 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 这样的库,它允许您按列定义特定的转换器。
为 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
用于 "lift" 转换函数,我认为这有助于一些数据清理步骤。想象一下,你有一个主要是数字的数组,你想用一个 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 这样的库,它允许您按列定义特定的转换器。