Sklearn.ensemble.AdaBoostClassifier не может использовать SVM как base_estimator?

Я выполняю задачу классификации текста. Теперь я хочу использовать ensemble.AdaBoostClassifier с LinearSVC как base_estimator. Однако, когда я пытаюсь запустить код

clf = AdaBoostClassifier(svm.LinearSVC(),n_estimators=50, learning_rate=1.0,    algorithm='SAMME.R')
clf.fit(X, y)

Произошла ошибка. TypeError: AdaBoostClassifier with algorithm='SAMME.R' requires that the weak learner supports the calculation of class probabilities with a predict_proba method

Первый вопрос Не может ли svm.LinearSVC() вычислить вероятности классов? Как подсчитать вероятности?

Затем меняем параметр algorithm и снова запускаем код.

clf = AdaBoostClassifier(svm.LinearSVC(),n_estimators=50, learning_rate=1.0, algorithm='SAMME')
clf.fit(X, y)

На этот раз TypeError: fit() got an unexpected keyword argument 'sample_weight'. Как сказано в AdaBoostClassifier, Sample weights. If None, the sample weights are initialized to 1 / n_samples. Даже если я назначу целое число n_samples, также возникла ошибка.

Второй вопрос: Что означает n_samples? Как решить эту проблему?

Надеюсь, что кто-нибудь сможет мне помочь.

Согласно комментарию @jme, однако, после попытки

clf = AdaBoostClassifier(svm.SVC(kernel='linear',probability=True),n_estimators=10,  learning_rate=1.0, algorithm='SAMME.R')
clf.fit(X, y)

Программа не может получить результат, и память, используемая на сервере, не изменяется.

Третий вопрос:, как я могу сделать AdaBoostClassifier работать с SVC как base_estimator?

Ответ 1

Правильный ответ будет зависеть именно от того, что вы ищете. LinearSVC не может предсказать вероятности класса (требуется по алгоритму по умолчанию, используемому AdaBoostClassifier) ​​и не поддерживает sample_weight.

Вы должны знать, что машина поддержки поддержки не номинально прогнозирует вероятности класса. Они вычисляются с использованием масштабирования Platt (или расширения масштабирования Platt в многоклассовом случае), метод, который имеет известные проблемы. Если вам нужно меньше "искусственных" вероятностей класса, возможно, SVM не подходит.

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

from sklearn.svm import SVC
from sklearn.ensemble import AdaBoostClassifier

clf = AdaBoostClassifier(SVC(probability=True, kernel='linear'), ...)

У вас есть другие варианты. Вы можете использовать SGDClassifier с функцией потери петли и установить AdaBoostClassifier для использования алгоритма SAMME (который не требует функции pred_proba, но требует поддержки sample_weight):

from sklearn.linear_model import SGDClassifier

clf = AdaBoostClassifier(SGDClassifier(loss='hinge'), algorithm='SAMME', ...)

Возможно, лучшим ответом будет использование классификатора, который имеет встроенную поддержку вероятности класса, например Logistic Regression, если вы хотите использовать алгоритм по умолчанию для AdaBoostClassifier. Вы можете сделать это, используя scikit.linear_model.LogisticRegression или используя SGDClassifier с функцией потери журнала, как используется в коде, предоставленном Kris.

Надеюсь, что это поможет, если вам интересно, что такое масштабирование Platt, посмотреть здесь оригинальную бумагу Джона Плата.

Ответ 2

Вам нужно использовать ученика, который имеет метод pred_proba, так как это не доступно в LinearSVC, попробуйте SVC с ядром, установленным в 'linear'

clf = AdaBoostClassifier(svm.SVC(probability=True,kernel='linear'),n_estimators=50,       learning_rate=1.0, algorithm='SAMME')
clf.fit(X, y)

пока я не уверен, что это даст идентичные результаты LinearSVC, из документации:

Подобно SVC с параметром kernel = linear, но реализуется в терминах liblinear, а не libsvm, поэтому он обладает большей гибкостью в выборе штрафов и функций потерь и должен лучше масштабироваться (до большого количества выборок).

Также упоминается что-то о One vs All и One vs One с точки зрения того, как они отличаются.

Ответ 3

На самом деле, LinearSVC может применяться к AdaBoostClassifier без масштабирования SVC-вывода через масштабирование Platt и алгоритм AdaBoost.M1 был первоначально разработан, классификатор принимает {-1, 1} в качестве вывода. Выбор алгоритма по умолчанию в AdaBoostClassifier - алгоритм AdaBoost.SAMME [2] (с указанием "SAMME.R" в аргументе ключевого слова алгоритма), который предназначен для классификации нескольких классов.

Тем не менее, ваш LinearSVC AdaBoost не сможет предоставить optim_proba. С другой стороны, если вы хотите сохранить знак на выходе вместо того, чтобы вводить SVM-выход в сигмовидную кривую, чтобы обеспечить вероятность. Затем вы изменяете алгоритм от SAMME.R до SAMME - это простой способ сделать.

[1] Y. Фрейнд, Р. Шапир, "Теоретико-теоретическое обобщение онлайн-обучения и приложения к усилению" , 1995.
[2] Zhu, H. Zou, S. Rosset, T. Hastie, "Multi-class AdaBoost" , 2009 г.

Ответ 4

У меня была аналогичная проблема, пытающаяся использовать AdaBoostClassifier с LogisticRegression. В документах упоминается, что слабый классификатор (или base_estimator) должен иметь метод fit, который принимает необязательный аргумент ключевого слова sample_weight=..., ср. вопрос # 18306416.

Если вы хотите использовать SVM или логистическую регрессию с помощью AdaBoost, вы используете классификатор спуска градиента sklearn с loss='hinge' (svm) или loss='log' (логистикой), например

from sklearn.linear_model import SGDClassifier
from sklearn.ensemble import AdaBoostClassifier

clf = AdaBoostClassifier(SGDClassifier(loss='log'), ...)

YMMV