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 = 38model = 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)) ])


