RandomizedSearchCV Pipeline выбирает гиперпараметры SelectPercentile с помощью duplic_info_classif - PullRequest
1 голос
/ 07 мая 2020

Что у меня есть

У меня есть конвейер, который работает с моими дистрибутивами гиперпараметров

pipe = Pipeline(steps=[
    ('scale', MinMaxScaler()),
    ('vt', VarianceThreshold()),
    ('pca', PCA(random_state=0)),
    ('select', SelectPercentile()),
    ('clf', RandomForestClassifier(random_state=0))
])

hyper_params0 = {
    'vt__threshold' : stats.distributions.uniform(0, 0.1),
    'pca__n_components' : stats.distributions.uniform(0.8, 0.19),
    'select__percentile' : stats.distributions.randint(1, 101),
    'clf__n_estimators' : stats.distributions.randint(50, 1000),
    'clf__criterion' : ['gini', 'entropy'],
    'clf__min_samples_split' : stats.distributions.uniform(0, 0.1),
    'clf__min_samples_leaf' : stats.distributions.uniform(0, 0.1),
    'clf__max_features' : ['sqrt', 'log2', None],
    'clf__bootstrap' : [True, False],
}

hyper_params=[
    {
        **hyper_params0,
        **{
            'select__score_func' : [mutual_info_classif],
        }
    },
    {
        **hyper_params0,
        **{
            'select__score_func' : [f_classif],
        }
    }
]

rscv = RandomizedSearchCV(
    estimator=pipe,
    param_distributions=hyper_params,
    n_iter=25,
    cv=5,
    scoring='f1_macro',
    n_jobs=-1,
    random_state=0,
    verbose=3
)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

rscv.fit(X_train, y_train)

Что я хочу

Я бы хотел выполнить поиск по n_neighbors параметр в mutual_info_classif в SelectPercentile.

Что я пробовал

Я пробовал редактировать hyper_params вот так:

hyper_params=[
    {
        **hyper_params0,
        **{
            'select__score_func' : [mutual_info_classif],
            'select__score_func__n_neighbors' : stats.distributions.randint(3, 15)
        }
    },
    {
        **hyper_params0,
        **{
            'select__score_func' : [f_classif],
        }
    }
]

Но я получаю ошибка AttributeError: 'function' object has no attribute 'set_params'. Я последовал простому примеру на сайте scikit-learn здесь , но далеко не продвинулся. Также пробовал использовать 'passthrough', например:

pipe = Pipeline(steps=[
    ('scale', MinMaxScaler()),
    ('vt', VarianceThreshold()),
    ('pca', PCA(random_state=0)),
    ('select', 'passthrough'),
    ('clf', RandomForestClassifier(random_state=0))
])
...
hyper_params=[
    {
        **hyper_params0,
        **{
            'select__score_func' : [SelectPercentile(mutual_info_classif)],
            'select__score_func__n_neighbors' : stats.distributions.randint(3, 15)
        }
    },
    {
        **hyper_params0,
        **{
            'select__score_func' : [SelectPercentile(f_classif)],
        }
    }
]

Но получаю ошибку AttributeError: 'str' object has no attribute 'set_params'.

Вопрос

Есть какие-нибудь советы, как это сделать?

1 Ответ

1 голос
/ 08 мая 2020

Поскольку ошибка предполагает, что mutual_info_classif является функцией, поэтому GridSearchCV не может устанавливать параметры для нее с помощью __. GridSearchCV может устанавливать параметр только для классов, поддерживающих дизайн BaseEstimator.

Во-первых, вам нужно создать пользовательский SelectPercentile, который может принимать n_neighbors в качестве параметра класса.

class SelectPercentileMI(SelectPercentile):
    def __init__(self, percentile=10, n_neighbors=3):
        self.n_neighbors=n_neighbors
        super().__init__(percentile=percentile,
                         score_func=partial(mutual_info_classif, n_neighbors=3))

Теперь ваша проблема решена.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.svm import LinearSVC
from sklearn.decomposition import PCA, NMF
from sklearn.feature_selection import SelectKBest, chi2, SelectPercentile, mutual_info_classif, f_classif
from scipy import stats
from functools import partial


pipe = Pipeline([
    ('feature_selector', 'passthrough'),
    ('classify', LinearSVC(dual=False, max_iter=10000))
])

C_OPTIONS = [1, 10]
param_grid = [
    {
        'feature_selector': [SelectPercentile(f_classif)],
        'classify__C': C_OPTIONS
    },
    {
        'feature_selector': [SelectPercentileMI()],
        'feature_selector__n_neighbors' : [2,3],
        'classify__C': C_OPTIONS
    },
]

grid = GridSearchCV(pipe, n_jobs=1, param_grid=param_grid)
X, y = load_digits(return_X_y=True)
grid.fit(X, y)

grid.best_params_

{'classify __ C': 10, 'feature_selector': SelectPercentileMI (n_neighbors = 3, percentile = 10), 'feature_selector__n_neighbors': 3}

...