Передать атрибут объекта из предыдущего шага конвейера sklearn в качестве аргумента методу следующего шага

tl;dr: есть ли способ вызвать .get_feature_names() для подгонки и преобразованных данных из предыдущего шага конвейера для использования в качестве гиперпараметра на следующем этапе конвейера? ?


У меня есть Pipeline, который включает подгонку и преобразование текстовых данных с помощью TfidfVectorizer, а затем запускает RandomForestClassifier. Я хочу GridSearchCV по различным уровням max_features в классификаторе, основываясь на количестве функций, полученных преобразованием из текста.

#setup pipeline
pipe = Pipeline([
    ('vect', TfidfVectorizer(max_df=.4,
                            min_df=3,
                            norm='l1',
                            stop_words='english',
                            use_idf=False)),
    ('rf', RandomForestClassifier(random_state=1,
                                  criterion='entropy',
                                  n_estimators=800))
])

#setup parameter grid
params = {
    'rf__max_features': np.arange(1, len(vect.get_feature_names()),1)
}

Создание экземпляра возвращает следующую ошибку:

NameError: name 'vect' is not defined

Редактировать:

Это более актуально (и не объяснено в примере кода), если бы я модулировал параметр TfidfVectorizer, такой как ngram_range, можно было бы увидеть, как это может изменить количество функций, выводимых на следующий шаг...


person Dij    schedule 27.07.2019    source источник


Ответы (1)


Сетка параметров заполняется до того, как что-либо в конвейере будет установлено, поэтому вы не можете сделать это напрямую. Возможно, вы сможете исправить gridsearch, как здесь, но я ожидаю, что это будет значительно сложнее так как ваш второй параметр зависит от результатов установки первого шага.

Я думаю, что лучший подход, хотя он и не даст именно то, что вам нужно, - просто использовать дробные значения для max_features, то есть процент столбцов, выходящих из векторизатора.

Если вам действительно нужна оценка для каждого целого числа max_features, я думаю, что самый простой способ может состоять в том, чтобы иметь два вложенных поиска по сетке, внутренний только создает экземпляр пространства параметров, когда вызывается его fit:

estimator = RandomForestClassifier(
    random_state=1,
    criterion='entropy',
    n_estimators=800
    )

class MySearcher(GridSearchCV):
    def fit(self, X, y):
        m = X.shape[1]
        self.param_grid = {'max_features': np.arange(1, m, 1)}
        return super().fit(X, y)

pipe = Pipeline([
    ('vect', TfidfVectorizer(max_df=.4,
                             min_df=3,
                             norm='l1',
                             stop_words='english',
                             use_idf=False)),
    ('rf', MySearcher(estimator=estimator, 
                      param_grid={'fake': ['passes', 'check']}))
])

Теперь результаты поиска будут неудобно вложены друг в друга (лучшие значения, скажем, ngram_range дадут вам перенастроенную копию pipe, второй шаг которой сам будет иметь наилучшее значение max_features и соответствующий перенастроенный случайный лес). Кроме того, данных, доступных для внутреннего поиска, будет немного меньше.

person Ben Reiniger    schedule 24.04.2020