python - 在 sklearn 中使用数据标签自定义 transformerMixin

标签 python scikit-learn pipeline

我正在做一个小项目,我正在尝试应用 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'

最佳答案

fit() 方法应该返回自身,而不是转换后的值。如果您只需要训练数据的功能而不需要测试,请实现 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() 时)Pipeline 将首先尝试调用 fit_transform()在内部对象上。如果没有找到,那么它将分别调用 fit()transform()

在测试数据上,只有 transform() 被每个内部对象调用,所以这里你提供的测试数据不应该被改变。

更新:上面的代码仍然会报错。 您会看到,当您对提供的数据进行过采样时,Xy 中的样本数都会发生变化。但管道将仅适用于 X 数据。它不会改变 y。因此,如果我更正上述错误,您将收到关于标签不匹配样本的错误。如果碰巧生成的样本与之前的样本相同,则 y 值也不会对应于新样本。

工作解决方案:傻我。

您可以只使用 Pipeline from the imblearn package代替 scikit-learn 管道。当在管道上调用 fit() 时,它会自动注意 re-sample,并且不会对测试数据重新采样(当调用 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))
    ])

关于python - 在 sklearn 中使用数据标签自定义 transformerMixin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49770851/

相关文章:

Python 继承 - 一个调用在子类中重写的方法的构造函数,使用哪个方法?

python - 如何处理 pandas 中的插补和热一编码?

python - 为什么 scikit-learn 中 SVC 上的 GridSearchCV 在给定相同输入的情况下会产生不同的概率?

arrays - 为什么$ A + $ B和$ A,$ B与测试路径交互不同

python - 从维基百科获取链接

python - 如何扫描所有工作表单元格

python - 类型错误:prepare_request_body() 获得关键字参数 'redirect_uri' 的多个值

python - 忽略来自 Python 模块(seaborn、sklearn)的警告

powershell - PowerShell 是否具有 "window"函数?

hadoop - 未使用流集将文件从本地加载到HDFS中(已成功验证!)