Обнаружение и удаление выбросов как этап конвейера - PullRequest
1 голос
/ 09 июля 2020

У меня проблема, я пытаюсь создать свой собственный класс, чтобы поместить его в конвейер в python, но это не работает.

Проблема, которую я пытаюсь решить, - это мультикласс проблема классификации.

Я хочу сделать это, чтобы добавить шаг в конвейер для обнаружения и удаления выбросов. Я обнаружил, что это обнаруживает и удаляет выбросы в конвейере python, что очень похоже на то, что я сделал. Это мой класс:

from sklearn.neighbors import LocalOutlierFactor
from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np

class OutlierExtraction(BaseEstimator, TransformerMixin):
    def __init__(self, **kwargs ):
        self.kwargs = kwargs

    def transform(self, X, y):
        """
            X should be of shape (n_samples, n_features)
            y should be of shape (n_samples,)
        """

        lof = LocalOutlierFactor(**self.kwargs)
        lof.fit(X)
        nof = lof.negative_outlier_factor_
        return X[nof > np.quantile(nof, 0.95), :], y[nof > np.quantile(nof, 0.95)]

    def fit(self, X, y = None):
        return self

Но я получаю эту ошибку in fit_transform return self.fit(X, y, **fit_params).transform(X) TypeError: transform() missing 1 required positional argument: 'y'

Следующий код - это код, который я использую для вызова этого класса:

scaler = preprocessing.RobustScaler()
outlierExtractor = OutlierExtraction()
pca = PCA()
classfier = svm.SVC()

pipeline = [('scaler', scaler),
            ('outliers', outlierExtractor),
        ('reduce_dim', pca),
        ('classfier', classfier)]

pipe = Pipeline(pipeline)

params = {
    'reduce_dim__n_components': [5, 15],
    'classfier__kernel': ['rbf'],
    'classfier__gamma': [0.1],
    'classfier__C': [1],
    'classfier__decision_function_shape':['ovo']}

my_scoring = 'f1_macro'
n_folds = 5
gscv = GridSearchCV(pipe, param_grid=params, scoring=my_scoring, n_jobs=-1, cv=n_folds, refit=True)
gscv.fit(train_x, train_y)

Ответы [ 2 ]

2 голосов
/ 10 июля 2020

@ TimCroydon прав: sklearn в настоящее время предполагает, что трансформаторы преобразуют только свои независимые переменные. Было несколько долгих дискуссий о том, как лучше всего расслабиться:

Пакет scikit-learn-contrib imbalanced-learn поддерживает ряд ресамплеров, которые имеют схожий эффект, но другой контекст ; вы можете использовать это, но, возможно, будет немного странно выглядеть fit_sample при удалении выбросов. В любом случае, у них есть собственная версия Pipeline, которая элегантно справляется с этой передискретизацией.

Наконец, вы можете просто переопределить метод fit_transform в своем настраиваемом классе. Похоже, это должно сработать в этой ситуации, хотя может вызвать проблемы в другом месте.

1 голос
/ 09 июля 2020

Ошибка связана с тем, что метод преобразования def transform(self, X, y) требует передачи и X, и y, но все, что вызывает его, передает только X. (Я не вижу, откуда он вызывается в вашем коде, поэтому предположим, что он вызывается базовой библиотекой).

Я не знаю, сделает ли y необязательный (def transform(self, X, y=None) и изменение вашего метода) работать в этом случае. В противном случае вам придется выяснить, как заставить вызывающий код передать y, или предоставить его другим способом.

Я не знаком с библиотекой, но смотрю исходный код показывает, что transform() должен принимать только один параметр X:

        if y is None:
            # fit method of arity 1 (unsupervised transformation)
            return self.fit(X, **fit_params).transform(X)
        else:
            # fit method of arity 2 (supervised transformation)
            return self.fit(X, y, **fit_params).transform(X)
...