我正在尝试建立包含几个用户定义列的管道
转变。当创建一个新的列转换器时,我继承了
sklearn.base.BaseEstimator
和sklearn.base.TransformerMixin
,以及
实现fit
和transform
方法。调用转换
直接按预期工作,但将其用作
sklearn.pipeline.Pipeline
实例无法给出模棱两可的错误。
假设我有一个pandas.DataFrame
实例df
,其中包含以下数据:
date genre
0 9/22/11 horror
1 1/16/04 NULL
2 10/11/96 NULL
3 3/28/13 drama
4 4/22/94 drama
我想实现两个转换器:
DateTransformer
,用于转换df['date']
中的日期字符串
放入一个numpy.array
实例,其中包含每一行的年,月和日。
GenreTransformer
,对于df['genre']
中的每个流派,如果
未指定(“ NULL”),否则未指定-1。
这是我的代码:
class GenreTransformer(BaseEstimator, TransformerMixin):
def fit(self, x, y=None):
return self
def transform(self, x):
x_copy = x.copy()
x_copy[x_copy != 'NULL'] = -1
x_copy[x_copy == 'NULL'] = 1
return x_copy.values
class DateTransformer(BaseEstimator, TransformerMixin):
def fit(self, x, y=None):
return self
def transform(self, x):
x_timestamp = x.apply(pd.to_datetime)
return np.column_stack((
x_timestamp.apply(lambda t: t.year).values,
x_timestamp.apply(lambda t: t.month).values,
x_timestamp.apply(lambda t: t.day).values,
))
两个变压器都能正常工作:
>>> GenreTransformer().fit_transform(df['genre'])
array([-1, 1, 1, -1, -1])
>>> DateTransformer().fit_transform(df['date'])
array([[2011, 9, 22],
[2004, 1, 16],
[1996, 10, 11],
[2013, 3, 28],
[1994, 4, 22]])
但是,当我使用合并变压器时
sklearn.compose.ColumnTransformer
,并创建管道,
DateTransformer
不起作用:
column_transformer = ColumnTransformer(
transformers=[
('date_trans', DateTransformer(), ['date']),
('genre_trans', GenreTransformer(), ['genre']),
],
remainder='drop',
)
pipe = Pipeline(
steps=[
('union', column_transformer),
# estimators
],
)
>>> pipe.fit(df)
---------------------------------------------------------------------------
Traceback (most recent call last)
...
AttributeError: ("'Series' object has no attribute 'year'", 'occurred at index date')
有趣的是,改用pandas.Series.apply
GenreTransformer.transform
内的遮罩方法集以及管件的装配
失败:
class GenreTransformer(BaseEstimator, TransformerMixin):
# ...
def transform(self, x):
return x.apply(lambda g: -1 if g != 'NULL' else 1)
>>> pipe.fit(df)
---------------------------------------------------------------------------
Traceback (most recent call last)
...
ValueError: ('The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().', 'occurred at index genre')
因此,我认为应用pandas.Series.apply
方法存在问题
内部管道。 scikit-learn源代码是否可能存在错误?
还是我做错了什么?如果是这样,请您指出
如何实现列转换器,以便可以将它们包含在管道中?
答案 0 :(得分:1)
您的代码中有一个细微的错误。
您为要应用['date']
的列指定了DateTransformer
。这样做时,[它表示DateTransformer
期望类似于2D数组],在这种情况下,它是DataFrame
。但是,实际上它期望像一维数组或Series
。
因此,当您实际需要DateTransformer().fit_transform(df[['date']])
时,您所做的等同于df['date']
。
相应地,将('date_trans', DateTransformer(), 'date')
传递给ColumnTransformer
,一切都会好起来。