Как выполнить поиск по сетке оценки, встроенной в OneVsRestClassifier с использованием конвейера - PullRequest
0 голосов
/ 02 апреля 2020

Я делаю выбор модели и настройку гиперпараметра с помощью GridSearchCV. Из первоначального эксперимента оказалось, что SV C с ядром rdf имеет лучшую производительность. Проблема в том, что это слишком медленная (200К +) выборка. Используя OneVsRestClassifier можно распараллелить SV C (n_jobs). Однако gridsearchcv не работает для этой встроенной оценки, когда я использую Pipeline для тестирования нескольких оценок одновременно.

pipe = Pipeline([('clf', SVC())]) # Placeholder Estimator

# Candidate learning algorithms and their hyperparameters
search_space = [{'clf': [OneVsRestClassifier(SVC(tol=0.1, gamma='scale', probability=True), n_jobs=-1],
                 'clf__kernel': ['rbf', 'linear'],
                 'clf__C': [1, 10, 100]},

                {'clf': [LogisticRegression(tol=0.1, penalty='l1', solver='saga', multi_class='multinomial', n_jobs=8)], 
                 'clf__C': [1, 10, 100]},

                {'clf': [RandomForestClassifier(n_jobs=8)],
                 'clf__n_estimators': [50, 100, 200, 300, 400],
                 'clf__max_depth': [10, 20, 30],
                 'clf__min_samples_leaf': [1, 2, 4],
                 'clf__min_samples_split': [2, 5, 10]},

                {'clf': [MultinomialNB()],
                 'clf__alpha': [0.1, 0.5, 1]}]

gs = GridSearchCV(pipe, search_space, cv=skf, scoring='accuracy', verbose=10)

Я получил ошибку

Invalid Parameter __kernel

Но согласно GridSearch для оценщика внутри OneVsRestClassifier , этот метод должен работать. Я думаю, что это испортил конвейер, так как он добавляет еще один слой поверх OneVsRestClassifier. Как именно выполнить gridsearchcv для этого вложенного оценщика?

1 Ответ

0 голосов
/ 02 апреля 2020

Как есть, конвейер ищет параметр kernel в OneVsRestClassifier, не может его найти (что неудивительно, поскольку модуль не имеет такого параметра) и выдает ошибку. Поскольку вы действительно хотите, чтобы параметр kernel (и, следовательно, C) равнялся SVC, вам следует go уровень глубже: измените первые 3 записи вашего search_space на:

{'clf': [OneVsRestClassifier(SVC(tol=0.1, gamma='scale', probability=True), n_jobs=-1],
 'clf__estimator__kernel': ['rbf', 'linear'],
 'clf__estimator__C': [1, 10, 100]}

и с вами все будет в порядке.

Независимо от ошибки, однако, ваше обоснование для использования этого подхода:

Проблема в том, что он слишком медленный (200K +) образец. Использование OneVsRestClassifier может распараллелить SV C (n_jobs).

не правильно. OneVsRestClassifier будет распараллеливать подгонку n_classes различных SVC оценок, не самого SVC. По сути, вы пытаетесь избежать узкого места (SVC), оборачивая вокруг него что-то еще (здесь OneVsRestClassifier), что налагает свою собственную дополнительную вычислительную сложность, только чтобы (неудивительно) снова найти его перед вами.

Мы можем продемонстрировать это с некоторыми временными интервалами для фиктивных данных - давайте попробуем несколько реалистичный c набор данных из 10K выборок, 5 функций и 3 классов:

from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
from sklearn.datasets import make_classification

X, y = make_classification(n_samples = 10000, n_features=5, n_redundant=0, n_informative=5,
                             n_classes = 3, n_clusters_per_class=1, random_state=42)

%timeit for x in range(10): SVC().fit(X,y)
# 1 loop, best of 3: 7.72 s per loop

%timeit for x in range(10): OneVsRestClassifier(SVC()).fit(X, y)
# 1 loop, best of 3: 21.1 s per loop

Ну, это ваша базовая разница ; теперь установка n_jobs=-1 помогает:

%timeit for x in range(10): OneVsRestClassifier(SVC(), n_jobs=-1).fit(X, y)
# 1 loop, best of 3: 19 s per loop

, но, что неудивительно, это происходит только по отношению к непараллелизированным OneVsRestClassifier, , а не по отношению к SVC.

Разница усиливается с появлением новых функций и классов; не вдаваясь в подробности, вот ситуация с 10 функциями и 5 классами (то же самое количество образцов, 10K):

X1, y1 = make_classification(n_samples = 10000, n_features=10, n_redundant=0, n_informative=10,
                             n_classes = 5, n_clusters_per_class=1, random_state=42)

%timeit for x in range(10): SVC().fit(X1,y1)
# 1 loop, best of 3: 10.3 s per loop

%timeit for x in range(10): OneVsRestClassifier(SVC()).fit(X1, y1)
# 1 loop, best of 3: 30.7 s per loop

%timeit for x in range(10): OneVsRestClassifier(SVC(), n_jobs=-1).fit(X1, y1)
# 1 loop, best of 3: 24.9 s per loop

Итак, я бы серьезно предложил пересмотреть ваш подход (и ваши цели ) здесь.

(Все тайминги в Google Colab).

...