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