VotingClassifier в sсikit-learn: построение и оптимизация ансамбля моделей классификации +7



В рамках реализации большой задачи по Sentiment Analysis (анализ отзывов) я решил уделить некоторое время дополнительному изучению её отдельного элемента — использованию VotingClassifier из модуля sklearn.ensemble как инструмента для построения ансамбля моделей классификации и повышению итогового качества предсказаний. Почему это важно и какие есть нюансы?



Часто случается, что по ходу решения прикладной задачи по анализу данных не сразу очевидно (или совсем неочевидно) какая модель обучения подходит наилучшим образом. Одним способом решения может быть выбор наиболее популярной и/или интуитивно подходящей модели исходя из характера имеющихся данных. В этом случае параметры выбранной модели оптимизируются (например, через GridSearchCV) и она используется в работе. Другим подходом может быть использование ансамбля моделей, когда результаты сразу нескольких из них участвуют в формировании конечного результата. Сразу оговорюсь, что цель статьи заключается не в описании преимущества использования ансамбля моделей или принципах его построения (об этом можно прочесть здесь), а скорей в одном отдельно прикладном подходе к решению задачи на конкретном примере и разборе возникающих по ходу такого решения нюансах.

Постановка глобальной задачи следующая: дано всего 100 отзывов на мобильные телефоны в качестве тестовой выборки и нам нужна предобученная модель, которая на этих 100 отзывах покажет лучший результат — а именно определит отзыв является положительным или отрицательным. Дополнительной сложностью, как следует из условий задачи, является отсутствие обучающей выборки. Для преодоления данной сложности с помощью библиотеки Beautiful Soup были успешно спарсены 10000 отзывов о мобильных телефонах и оценках к ним с одного из российских сайтов.

Пропуская этапы парсинга, предобработки данных и изучении их исходной структуры, мы переходом к моменту, когда имеются:

  • обучающая выборка, состоящая из 10000 отзывов о телефонах, каждый отзыв размечен бинарно (положительный или отрицательный). Разметка получения определением отзывов с оценками 1-3 как отрицательных и оценками 4-5 как положительных.
  • с использованием Count Vectorizer данные представлены в виде, который подходит для обучения моделей классификаторов

Как решить какая модель подойдет лучше всего? У нас нет возможности ручного перебора моделей, т.к. тестовая выборка лишь из 100 отзывов создает огромный риск того, что какая-то модель просто лучше подойдет под эту тестовую выборку, но если её использовать на дополнительной, скрытой от нас выборке или в «бою» результат будет ниже среднего.

Для решения этой проблемы в библиотеке Scikit-learn есть модуль VotingClassifier, являющийся отличным инструментом использования сразу нескольких, не похожих между собой, моделей машинного обучения и их объединения в один классификатор. Это позволяет снизить риск переобучения, а также неправильной интерпретации результатов какой-либо одной отдельно взятой модели. Модуль VotingClassifier импортируется следующей командой:
from sklearn.ensemble import VotingClassifier

Практические детали при работе с данным модулем:

1) Первое и самое важное — каким образом происходит получение отдельного взятого предсказания объединенного классификатора после получения предсказаний от каждой из входящих в него моделей. Среди параметров VotingClassifier есть параметр voting с двумя возможными значениями: 'hard' и 'soft'.

1.1) В первом случае итоговый ответ объединенного классификатора будет соответствовать «мнению» большинства входящих в него членов. Например, в вашем объединённом классификаторе используется данные от трех различных моделей. Две из них на конкретном наблюдении предсказывают ответ «отзыв положительный», третий — «отзыв отрицательный». Таким образом, для данного наблюдения итоговым предсказанием будет «отзыв положительный», так как у нас 2 — «за» и 1 «против».

1.2) Во втором случае, т.е. при использовании значения 'soft' параметра voting идет полноценное «голосование» и взвешивание предсказаний моделей для каждого класса, таким образом итоговый ответ объединенного классификатор — это argmax суммы предсказанных вероятностей. ВАЖНО! Для возможности использования такого метода «голосования» каждый классификатор из входящих в ваш ансамбль должен поддерживать метод predict_proba() для получения количественной оценки вероятности вхождения в каждый из классов. Обратите внимание, что не все модели классификаторов поддерживают этот метод и, соответственно, могут быть использованы в рамках VotingClassifier при использовании метода взвешенных вероятностей (Soft Voting).

Разберемся на примере: есть три классификатора и два класса отзывов: положительный и отрицательный. Каждый классификатор через метод predict_proba выдаст некое значение вероятности (p), с которой конкретное наблюдение отнесено им к классу 1 и, соответственно, с вероятностью (1-p) к классу два. Объединенный классификатор после получения ответа каждой из моделей, проводит взвешивание полученных оценок и выдает итоговый результат, полученный как

$$display$$max (w1*p1+w2*p1+w3*p1, w1*p2+w2*p2+w3*p3) $$display$$

, где w1,w2,w3 — это веса ваших классификатор, входящих в ансамбль, по умолчанию имеющих равные веса, а p1,p2 — оценка принадлежности к классу 1 или классу 2 каждого из них. Обратите внимание также на то, что веса классификаторов при использовании Soft Vote могут быть изменены с помощью параметра weights, таким образом вызов модуля должен выглядеть так:
... = VotingClassifier(estimators=[('..', clf1), ('..', clf2), ('...', clf3)], voting='soft', weights=[*,*,*]) , где звездочек могут быть указано требуемые веса для каждой модели.

2) Возможность одновременного использования модуля VotingClassifier и GridSearch для оптимизации гиперпараметров каждого из классификаторов, входящих в ансамбль.

Когда вы планируете использовать ансамбль и хотите, чтобы входящие в него модели были оптимизированы, можно воспользоваться GridSearch уже на объединенном классификаторе. И код, приведенный ниже, показывает как можно работать с входящими в него моделями (Логистическая регрессия, наивный Байес, стохастический градиентный спуск) оставаясь при этом в рамках объединенного классификатора (VotingClassifier):

clf1 = LogisticRegression()
clf2 = MultinomialNB()
clf3 = SGDClassifier(max_iter=1000, loss='log')
eclf = VotingClassifier(estimators=[ ('lr', clf1), ('nb', clf2),('sgd', clf3)], voting='hard') # задаем метод голосования через большинство (hard voting), см. п. 1.1

<b>params = {'lr__C' : [0.5,1,1.5], 'lr__class_weight': [None,'balanced'],
          'nb__alpha' : [0.1,1,2], 
          'sgd__penalty' : ['l2', 'l1'], 'sgd__alpha': [0.0001,0.001,0.01]} </b> # задаем сетку параметров для перебора и сравнения, важен синтаксис, чтобы оптимизировалась нужная модель  

grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5, scoring='accuracy', n_jobs=-1)
grid = grid.fit(data_messages_vectorized, df_texts['Binary_Rate']) # когда задали все условия, проводим обучение и оптимизацию на 5 фолдах на собранной обучающий выборке 

Таким образом, словарь params должен быть задан таким образом, чтобы при обращении к нему через GridSearch можно было определить к какой из входящих в ансамбль моделей относится параметр, значение которого требуется оптимизировать.

Вот и все, что требуется знать для полноценного использования инструмента VotingClassifier как способа построения ансамбля моделей и его оптимизации. Посмотрим на результаты:

 print grid.best_params_
{'lr__class_weight': 'balanced', 'sgd__penalty': 'l1', 'nb__alpha': 1, 'lr__C': 1, 'sgd__alpha': 0.001}

Оптимальные значения параметров найдены, остается сравнить результаты работы для ансамбля классификаторов (VotingClassifier) с оптимальными параметрами, проведем кросс-валидацию на обучающей выборке и сравним модели с оптимальными параметрами и ансамбль, состоящей из них:

for clf, label in zip([clf1, clf2, clf3, eclf], ['Logistic Regression', 'Naive Bayes', 'SGD', 'Ensemble_HardVoting']):
    scores = cross_val_score(clf, data_messages_vectorized, df_texts['Binary_Rate'], cv=3, scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))

Итоговый результат:

Accuracy: 0.75 (± 0.02) [Logistic Regression]
Accuracy: 0.79 (± 0.02) [Naive Bayes]
Accuracy: 0.79 (± 0.02) [SGD]
Accuracy: 0.79 (± 0.02) [Ensemble_HardVoting]

Как видно, модели проявили себя несколько по-разному на обучающей выборке (при стандартных параметрах это различие было более заметно). При этом итоговое значение (по метрике accuracy) ансамбля не обязательно должно превышать лучшего значения из входящих в него моделей, т.к. ансамбль скорей является более стабильной моделью, способной показать ± схожий результат на тестовой выборке и в «бою», а значит снизить риск переобучения, подгонки под обучающую выборку, и других сопутствующих обучению классификаторов проблем. Удачи в решении прикладных задачи и спасибо за внимание!

P.S. Учитывая специфику и правила публикации в песочнике, не могу привести ссылку на github и исходный код для анализа, приведенного в данной статье, также как и ссылки на Kaggle, в рамках InClass соревнования на котором предоставлялся тест сет и инструменты для проверки моделей на нем. Могу только сказать, что данный ансамбль существенно побил бейзлайн и занял достойное место на лидерборде после проверки на тест сете. Надеюсь в следующих публикациях смогу поделиться.

Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (9):

  1. lair
    /#19385484

    ансамбль скорей является более стабильной моделью, способной показать ± схожий результат на тестовой выборке и в «бою», а значит снизить риск переобучения

    Это, конечно, теоретически очень привлекательное утверждение, но можно увидеть какие-то цифры, которые подтверждают эффективность такого решения?


    А то ведь если вас послушать, то получается, что можно всегда брать ансамбль — потерь нет, а "риск переобучения" ниже. Так ли это на самом деле?

    • roryorangepants
      /#19385820

      Это так на самом деле. Какие-то цифры, подтверждающие данный факт — это топ каждого конкурса на кагле, где выигрывает ансамбль (чаще всего не такой простой, как описано в статье, а стекинг, но все же).


      Другое дело, что в реальной жизни использовать ансамбли очень дорого по перфомансу.

      • lair
        /#19385854

        Это так на самом деле. [...] Другое дело, что в реальной жизни использовать ансамбли очень дорого

        Одно противоречит другому. Перформанс — это тоже потеря; следовательно, можно делать анализ того, насколько (потенциальный) выигрыш оправдан.


        Какие-то цифры, подтверждающие данный факт — это топ каждого конкурса на кагле, где выигрывает ансамбль

        Беда в том, что одно дело — применять что-то для того, чтобы выиграть Каггл, и совсем другое — утверждать, что это гарантированно правильная стратегия для "в бою".


        Ну и отдельным пунктом идет то, что повторить условия Каггл, чтобы продемонстрировать, что в них ансамбль имеет преимущество, вполне возможно. Это тоже дало бы полезные цифры для обсуждения.

        • roryorangepants
          /#19386002

          Одно противоречит другому. Перформанс — это тоже потеря; следовательно, можно делать анализ того, насколько (потенциальный) выигрыш оправдан.

          Где противоречие? У автора про точность, а перфоманс — это про скорость работы или требуемую память. Это разные характеристики, и теряя в одной мы приобретаем другую, но в контексте статьи речь исключительно про метрики точности модели, и когда я писал «это так на самом деле», я говорил тоже про метрики.

          Беда в том, что одно дело — применять что-то для того, чтобы выиграть Каггл, и совсем другое — утверждать, что это гарантированно правильная стратегия для «в бою».

          Ну автор же и рассказывает про Kaggle InClass соревнование, а не про продакшен.

          • lair
            /#19386036

            Ну автор же и рассказывает про Kaggle InClass соревнование, а не про продакшен.

            "Часто случается, что по ходу решения прикладной задачи по анализу данных не сразу очевидно (или совсем неочевидно) какая модель обучения подходит наилучшим образом."


            Где противоречие?

            Там, где забыли, что производительность — тоже метрика модели.


            У автора про точность

            Потенциальную. Из поста так и не видно, где выигрыш.

            • roryorangepants
              /#19386044

              «Часто случается, что по ходу решения прикладной задачи по анализу данных не сразу очевидно (или совсем неочевидно) какая модель обучения подходит наилучшим образом.»

              Справедливо. Но автор нигде вроде бы и не советовал использовать ансамбли как абсолютно правильную стратегию на все случаи жизни. Он лишь сказал, что будет гарантированно хорошая точность.

              Там, где забыли, что производительность — тоже метрика модели.

              Это не метрика качества. Придираться к этому в контексте фразы автора «ансамбль скорей является более стабильной моделью, способной показать ± схожий результат на тестовой выборке и в «бою», а значит снизить риск переобучения» — это демагогия.

              • lair
                /#19386052

                Он лишь сказал, что будет гарантированно хорошая точность.

                Это утверждение меня сильно интересует. Где его доказательство?


                Это не метрика качества.

                Это зависит от того, что вы считаете "качеством". Модель, неспособная дать предсказание за нужное время, или которую нельзя развернуть в нужных условиях, или которая не обучается на существующем объеме данных — это некачественная модель.

                • 1appleapple0
                  /#19386298

                  Во-первых спасибо за время, уделенное прочтению статьи!

                  Относительно дискуссии о корректности приведенных высказываний, я не берусь от частного переходить к общему, потому что согласен с Вами — частный случай никоим образом не должен претендовать на универсальную теорию.

                  Более того, рассуждать о том, насколько уместно «везде» использовать методику построения ансамблей я тоже не возьмусь, но хочу обратить Ваше внимание на ряд моментов:
                  — как верно высказался roryorangepants, в данной статье речь шла о, так скажем, соревновательном Data Science, который чаще всего встречается на kaggle competitions, и там очень часто (если не всегда) наилучший результат показывают ensemble модели, часто гораздо более сложные, чем приведенная в статье.
                  — несмотря на то, что целью данной статьи не было обосновать сам факт выбора ансамбля как оптимального подхода, а рассмотреть скорей специфику использования конкретного модуля из библиотеки skicit, в качестве теоретической базы для обоснования могут служить статьи Thomas G Dietterich: Ensemble Methods in Machine Learning , где в качестве заключения автор делает вывод о том, что:

                  Ensembles are well established as a method for obtaining highly accurate classiers by combining less accurate ones
                  , что в целом соответствует высказываниям, сделанным мною в тексте.
                  — в качестве доказательства распространенности подхода можно использовать статью «История развития ансамблевых методов классификации в машинном обучении» Юрия Каштинского, где приводится история вопроса и даются перечни работ, посвященных изучению «правильности» выбранного подхода.
                  — из всем известного курса Andrew Ng, а также по ссылке, которая дана в тексте на курс Open Data Science блог также следует, что практика объединения более слабых отдельно-взятых классификаторов для получения «улучшенного» объединенного набирает обороты и является если не стандартом, то уже зарекомендовавшим себя подходом.
                  — не берусь добавить к вышеуказанным статьям и ресурсам свое сильно субъективное мнение, но, учитывая что я больше практикуюсь в построении моделей для изучения финансовых рынков, хорошим подспорьем может служить также недавно вышедшая статья: Online Ensembles for Financial Trading, где утверждается, что
                  Diverse behavior of models on predicting complex dynamic systems: in problems with so many unrecorded factors in?uencing the dynamics of a systemis hard to ?nd a predictive model that is good for all regimes.
                  и исходя из этого, часто более практичным даже в решении прикладных задач с онлайн-обновляющимися данными является использование как раз нескольких моделей в виде ансамбля, что позволяет в целом повысить надежность предсказания.

                  В завершении хочу повторно сказать спасибо за высказанные мнения и замечания и все же уточнить, что статья скорей посвящена конкретному кейсу и должна была скорей ответить на вопрос «как применить ансамбль, если уже решились», чем «стоит ли его применять и насколько этот подход лучше других». Спасибо !)

                  • lair
                    /#19389852

                    в данной статье речь шла о, так скажем, соревновательном Data Science, который чаще всего встречается на kaggle competitions

                    Я специально еще раз перечитал статью. Kaggle (и вообще соревнования) первый раз упоминаются в постскриптуме. Зато вот о прикладных задачах вы пишете во втором абзаце (а прикладные задачи и соревновательные задачи — это две разные вещи).


                    качестве теоретической базы для обоснования могут служить статьи [...] автор делает вывод [...] "Ensembles are well established as a method for obtaining highly accurate classifiers by combining less accurate ones", что в целом соответствует высказываниям, сделанным мною в тексте

                    Вот. Это важный момент. Ваша цитата говорит о ансамблях, которые точнее, чем входящие в них базовые классификаторы. Возьмем, сначала, ваш "итоговый результат":


                    Accuracy: 0.75 (± 0.02) [Logistic Regression]
                    Accuracy: 0.79 (± 0.02) [Naive Bayes]
                    Accuracy: 0.79 (± 0.02) [SGD]
                    Accuracy: 0.79 (± 0.02) [Ensemble_HardVoting]

                    Как мы видим, ваш ансамбль не точнее, чем входящий в него базовый классификатор. Приведенное вами теоретическое обоснование не выполняется.


                    Теперь возьмем сделанное вами утверждение:


                    При этом итоговое значение (по метрике accuracy) ансамбля не обязательно должно превышать лучшего значения из входящих в него моделей, т.к. ансамбль скорей является более стабильной моделью, способной показать ± схожий результат на тестовой выборке и в «бою», а значит снизить риск переобучения, подгонки под обучающую выборку, и других сопутствующих обучению классификаторов проблем.

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


                    Возьмем статью Каштинского, вывод (выделение мое):


                    в настоящее время активно развиваются ансамблевые методы классификации, объединяющие в одной модели множество разных классификаторов, обученных на разных выборках данных

                    Я специально пошел и проверил: VotingClassifier не разбивает обучающую выборку, значит, эта часть к вам не применима. Дальше...


                    Один из наиболее точных методов, существующих на сегодняшний день, — это бустинг над решающими деревьями

                    … тоже не ваш случай.


                    Собственно (в меру моего понимания), единственное, что описывает VotingClassifier в этой статье — это абзац в разделе 3.2:


                    Интуитивно это можно представить так: при наличии пяти классификаторов с точностью предсказания 60% можно назначать классифицируемому объекту ту метку, которая предсказывается большинством из этих пяти слабых классификаторов. Это ансамблевый метод классификации простым голосованием (или голосованием большинством). В таком случае, как это легко показать, точность мета-классификатора повышается до 68%

                    Но это опять про точность, а не про защиту от переобучения. То же относится и к остальным приведенным вами примерам.


                    статья скорей посвящена конкретному кейсу и должна была скорей ответить на вопрос «как применить ансамбль, если уже решились», чем «стоит ли его применять и насколько этот подход лучше других».

                    В этом и проблема: после того, как вы решили что-то применить, надо проверить, есть ли от этого применения польза (я вот как-то решился применить для одной модели сначала PCA, потом LDA, а потом NMF, и был очень рад тому, что они показывают что-то осмысленное, но вот предсказания модели не улучшились ни на йоту). У вас же есть выдвинутая гипотеза ("ансамбль меньше переобучается"), но нет ни ее проверки, ни ее подтверждения.