sklearn中带有数据标签的定制变压器Mixin

发布于 2021-01-29 16:19:38

我正在做一个小项目,试图在我的数据不平衡的情况下应用SMOTE“综合少数族裔过采样技术”。

我为SMOTE功能创建了一个定制的TransformerMixin ..

class smote(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        print(X.shape, ' ', type(X)) # (57, 28)   <class 'numpy.ndarray'>
        print(len(y), ' ', type)     #    57      <class 'list'>
        smote = SMOTE(kind='regular', n_jobs=-1)
        X, y = smote.fit_sample(X, y)

        return X

    def transform(self, X):
        return X

model = Pipeline([
        ('posFeat1', featureVECTOR()),
        ('sca1', StandardScaler()),
        ('smote', smote()),
        ('classification', SGDClassifier(loss='hinge', max_iter=1, random_state = 38, tol = None))
    ])
    model.fit(train_df, train_df['label'].values.tolist())
    predicted = model.predict(test_df)

我在FIT函数上实现了SMOTE,因为我不希望将其应用于测试数据。

不幸的是,我得到了这个错误:

     model.fit(train_df, train_df['label'].values.tolist())
  File "C:\Python35\lib\site-packages\sklearn\pipeline.py", line 248, in fit
    Xt, fit_params = self._fit(X, y, **fit_params)
  File "C:\Python35\lib\site-packages\sklearn\pipeline.py", line 213, in _fit
    **fit_params_steps[name])
  File "C:\Python35\lib\site-packages\sklearn\externals\joblib\memory.py", line 362, in __call__
    return self.func(*args, **kwargs)
  File "C:\Python35\lib\site-packages\sklearn\pipeline.py", line 581, in _fit_transform_one
    res = transformer.fit_transform(X, y, **fit_params)
  File "C:\Python35\lib\site-packages\sklearn\base.py", line 520, in fit_transform
    return self.fit(X, y, **fit_params).transform(X)
AttributeError: 'numpy.ndarray' object has no attribute 'transform'
关注者
0
被浏览
363
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    fit()Mehtod应该返回自身,而不是转换后的值。如果只需要功能用于火车数据而不需要测试,请实施该fit_transform()方法。

    class smote(BaseEstimator, TransformerMixin):
        def fit(self, X, y=None):
            print(X.shape, ' ', type(X)) # (57, 28)   <class 'numpy.ndarray'>
            print(len(y), ' ', type)     #    57      <class 'list'>
            self.smote = SMOTE(kind='regular', n_jobs=-1).fit(X, y)
    
            return self
    
        def fit_transform(self, X, y=None):
            self.fit(X, y)
            return self.smote.sample(X, y)
    
        def transform(self, X):
            return X
    

    说明:在火车数据(即何时pipeline.fit()调用)上,管道将首先尝试调用fit_transform()内部对象。如果找不到,它将分别调用fit()transform()

    在测试数据上,transform()每个内部对象仅调用,因此此处提供的测试数据不应更改。

    更新
    :上面的代码仍将引发错误。您会看到,当对提供的数据进行过度采样时,其中的采样数会发生变化,X并且y两者都会发生变化。但是管道只会对X数据起作用。它不会改变y。因此,如果我纠正上述错误,您将得到关于标签不匹配样本的错误。如果偶然地,所生成的样本等于先前的样本,那么这些y值也将不对应于新的样本。

    工作解决方案 :愚蠢的我。

    您可以只使用imblearn包中的Pipeline代替scikit-learn
    Pipeline。它会自动注意re- sample何时fit()在管道上调用,并且不会对测试数据进行重新采样(调用transform()或时predict())。

    实际上,我知道imblearn.Pipeline处理sample()方法,但是当您实现自定义类并说测试数据不得更改时就被抛出了。我没有想到这就是默认行为。

    只需更换

    from sklearn.pipeline import Pipeline
    

    from imblearn.pipeline import Pipeline
    

    你们都准备好了。无需像您一样进行自定义类。只需使用原始的SMOTE。就像是:

    random_state = 38
    model = Pipeline([
            ('posFeat1', featureVECTOR()),
            ('sca1', StandardScaler()),
    
            # Original SMOTE class
            ('smote', SMOTE(random_state=random_state)),
            ('classification', SGDClassifier(loss='hinge', max_iter=1, random_state=random_state, tol=None))
        ])
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看