【问题标题】:Custom transformer mixin with FeatureUnion in scikit-learnscikit-learn 中带有 FeatureUnion 的自定义转换器 mixin
【发布时间】:2019-02-06 13:33:36
【问题描述】:

我正在 scikit-learn 中编写自定义转换器,以便对数组执行特定操作。为此,我使用 TransformerMixin 类的继承。 当我只处理一个变压器时它工作正常。 但是,当我尝试使用 FeatureUnion(或 make_union)链接它们时,数组被复制了 n 次。 我能做些什么来避免这种情况? 我是否按照应有的方式使用 scikit-learn?

import numpy as np
from sklearn.base import TransformerMixin
from sklearn.pipeline import FeatureUnion

# creation of array
s1 = np.array(['foo', 'bar', 'baz'])
s2 = np.array(['a', 'b', 'c'])
X = np.column_stack([s1, s2])
print('base array: \n', X, '\n')

# A fake example that appends a column (Could be a score, ...) calculated on specific columns from X
class DummyTransformer(TransformerMixin):
    def __init__(self, value=None):
        TransformerMixin.__init__(self)
        self.value = value

    def fit(self, *_):
        return self

    def transform(self, X):
        # appends a column (in this case, a constant) to X
        s = np.full(X.shape[0], self.value)
        X = np.column_stack([X, s])
        return X

# as such, the transformer gives what I need first
transfo = DummyTransformer(value=1)
print('single transformer: \n', transfo.fit_transform(X), '\n')

# but when I try to chain them and create a pipeline I run into the replication of existing columns
stages = []
for i in range(2):
    transfo = DummyTransformer(value=i+1)
    stages.append(('step'+str(i+1),transfo))
pipeunion = FeatureUnion(stages)
print('Given result of the Feature union pipeline: \n', pipeunion.fit_transform(X), '\n')
# columns 1&2 from X are replicated

# I would expect:
expected = np.column_stack([X, np.full(X.shape[0], 1), np.full(X.shape[0], 2) ])
print('Expected result of the Feature Union pipeline: \n', expected, '\n')

输出:

base array: 
 [['foo' 'a']
 ['bar' 'b']
 ['baz' 'c']] 

single transformer: 
 [['foo' 'a' '1']
 ['bar' 'b' '1']
 ['baz' 'c' '1']] 

Given result of the Feature union pipeline: 
 [['foo' 'a' '1' 'foo' 'a' '2']
 ['bar' 'b' '1' 'bar' 'b' '2']
 ['baz' 'c' '1' 'baz' 'c' '2']] 

Expected result of the Feature Union pipeline: 
   [['foo' 'a' '1' '2']
   ['bar' 'b' '1' '2']
   ['baz' 'c' '1' '2']] 

非常感谢

【问题讨论】:

    标签: python numpy scikit-learn


    【解决方案1】:

    FeatureUnion 只会连接它从内部变压器中得到的东西。现在在您的内部转换器中,您从每个转换器发送相同的列。由转换器正确发送正确的数据。

    我建议您只从内部转换器返回新数据,然后从FeatureUnion 外部或内部连接剩余的列。

    如果你还没有看这个例子:

    例如,您可以这样做:

    # This dont do anything, just pass the data as it is
    class DataPasser(TransformerMixin):
    
        def fit(self, X, y=None):
            return self
    
        def transform(self, X):
            return X
    
    # Your transformer
    class DummyTransformer(TransformerMixin):
        def __init__(self, value=None):
            TransformerMixin.__init__(self)
            self.value = value
    
        def fit(self, *_):
            return self
    
        # Changed this to only return new column after some operation on X
        def transform(self, X):
            s = np.full(X.shape[0], self.value)
            return s.reshape(-1,1)
    

    之后,在您的代码中进一步更改:

    stages = []    
    
    # Append our DataPasser here, so original data is at the beginning
    stages.append(('no_change', DataPasser()))
    
    
    for i in range(2):
        transfo = DummyTransformer(value=i+1)
        stages.append(('step'+str(i+1),transfo))
    
    pipeunion = FeatureUnion(stages)
    

    运行这个新代码有结果:

    ('Given result of the Feature union pipeline: \n', 
    array([['foo', 'a', '1', '2'],
           ['bar', 'b', '1', '2'],
           ['baz', 'c', '1', '2']], dtype='|S21'), '\n')
    ('Expected result of the Feature Union pipeline: \n', 
    array([['foo', 'a', '1', '2'],
           ['bar', 'b', '1', '2'],
           ['baz', 'c', '1', '2']], dtype='|S21'), '\n')
    

    【讨论】:

    • 谢谢。我对将整个数据 + 新数据作为输出的 Spark ML 转换器的行为感到困惑。
    猜你喜欢
    • 2020-02-04
    • 2021-10-25
    • 2019-11-20
    • 2020-02-03
    • 2019-01-12
    • 2018-04-26
    • 2016-04-16
    • 2020-02-05
    • 1970-01-01
    相关资源
    最近更新 更多